├── .github
└── workflows
│ └── swift.yml
├── .gitignore
├── .swiftpm
└── xcode
│ ├── package.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ └── xcschemes
│ └── ErgastAPI.xcscheme
├── LICENSE
├── Package.swift
├── README.md
├── Sources
└── Formula1API
│ ├── APIError.swift
│ ├── Formula1API.swift
│ ├── Helpers
│ ├── Endpoint.swift
│ ├── Extensions
│ │ ├── Decodable+Extension.swift
│ │ └── URLSession+Extension.swift
│ ├── Path.swift
│ └── Season.swift
│ └── Models
│ ├── Circuits.swift
│ ├── Constructors.swift
│ ├── DriverStandings.swift
│ ├── Drivers.swift
│ ├── FinishingStatus.swift
│ ├── Laps.swift
│ ├── PitStops.swift
│ ├── QualifyingResults.swift
│ ├── RaceResults.swift
│ ├── RaceSchedule.swift
│ └── Seasons.swift
└── Tests
├── ErgastAPITests
├── EndpointTests.swift
├── ErgastAPITests.swift
└── XCTestManifests.swift
└── LinuxMain.swift
/.github/workflows/swift.yml:
--------------------------------------------------------------------------------
1 | name: Swift
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: macos-latest
13 |
14 | steps:
15 | - uses: actions/checkout@v2
16 | - name: Build
17 | run: swift build -v
18 | - name: Run tests
19 | run: swift test -v
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /.build
3 | /Packages
4 | /*.xcodeproj
5 | xcuserdata/
6 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/xcshareddata/xcschemes/ErgastAPI.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
56 |
57 |
67 |
68 |
74 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Giovanni Noa
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.2
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "Formula1API",
8 | platforms: [
9 | .macOS(.v10_15),
10 | .watchOS(.v6),
11 | .iOS(.v13)
12 | ],
13 | products: [
14 | // Products define the executables and libraries produced by a package, and make them visible to other packages.
15 | .library(
16 | name: "Formula1API",
17 | targets: ["Formula1API"]),
18 | ],
19 | dependencies: [
20 | // Dependencies declare other packages that this package depends on.
21 | // .package(url: /* package url */, from: "1.0.0"),
22 | ],
23 | targets: [
24 | // Targets are the basic building blocks of a package. A target can define a module or a test suite.
25 | // Targets can depend on other targets in this package, and on products in packages which this package depends on.
26 | .target(
27 | name: "Formula1API",
28 | dependencies: []),
29 | ]
30 | )
31 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Formula 1 API
3 |
4 | > This Swift library provides endpoint access to Formula 1 data provided by the [Ergast API](https://ergast.com/mrd/). By using this library, you won't have to build the interactive layer yourself, and can just start consuming the data.
5 |
6 | ## Installing / Getting started
7 |
8 | > Formula 1 API supports Swift Package Manager. To use SwiftPM, you should use the most recent version of Xcode to add this project.
9 |
10 | Click `File` -> `Swift Packages` -> `Add Package Dependency`, enter Formula1API repo's [URL](https://github.com/gionoa/Formula1API.git). Or you can login Xcode with your GitHub account and just type Formula1API to search.
11 |
12 | ## Features
13 |
14 | Formula1API provides functions that allow you to access endpoints for data.
15 |
16 | Currently, you can fetch:
17 | * `Circuits (all, specified season)`
18 | * `Seasons`
19 | * `Constructors (all, specified season)`
20 | * `Race Schedule (specified season)`
21 | * `Race Results (specified season)`
22 | * `Qualifying Results (specified season)`,
23 | * `Pit Stops (specified season)`,
24 | * `Laps(specified season)`
25 |
26 | *More endpoints will be accessible as development progresses.*
27 |
28 | ## Usage
29 |
30 | Usage of this library within your app or package is simple.
31 |
32 | Access endpoints via the `Formula1API` object.
33 |
34 | Return closure example:
35 | ```swift
36 | Formula1API.constructors(for: .year(2022)) { result in
37 | switch result {
38 | case .success(let constructors):
39 | print(constructors)
40 | case .failure(let error):
41 | print(error)
42 | }
43 | }
44 |
45 | ```
46 |
47 | Async-await example:
48 | ```swift
49 | do {
50 | let constructors = try await Formula1API.constructors(for: .year(2022))
51 | } catch error {
52 | print(error)
53 | }
54 | ```
55 |
56 | ## Licensing
57 |
58 | The code in this project is licensed under MIT license.
59 |
--------------------------------------------------------------------------------
/Sources/Formula1API/APIError.swift:
--------------------------------------------------------------------------------
1 | //
2 | // APIError.swift
3 | //
4 | //
5 | // Created by Giovanni Noa on 4/28/20.
6 | //
7 |
8 | import Foundation
9 |
10 | // MARK: - Publisher Error
11 | /// Enum for passing errors during network interactions.
12 | public enum APIError: Error {
13 | /// A URL error.
14 | case url(String)
15 |
16 | /// A network error.
17 | case network(String)
18 |
19 | /// A parsing/decoding error.
20 | case parsing(String)
21 |
22 | /// An error for when error is nil, and data failed to be fetched,
23 | case data(String)
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/Formula1API/Formula1API.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Formula1API.swift
3 | //
4 | //
5 | // Created by Giovanni Noa on 4/28/20.
6 | //
7 |
8 | import Foundation
9 |
10 | /// Public interface of functions for fetching Formula 1 data from the Ergast REST API.
11 | public enum Formula1API {
12 | /// Fetches Formula 1 Circuits for a given year.
13 | /// - Parameters:
14 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020).
15 | /// - limit: Property to specify number of items to return per request.
16 | /// - offset: Property to indicate starting point of elements from API request.
17 | /// - completion: Asynchronous closure to inject functionality once the network interaction completes.
18 | public static func circuits(for season: Season,
19 | limit: String? = nil,
20 | offset: String? = nil,
21 | completion: @escaping (Result) -> Void) {
22 |
23 | URLSession.shared.fetch(.circuits,
24 | for: season,
25 | limit: limit,
26 | offset: offset) { result in
27 | completion(result)
28 | }
29 | }
30 |
31 | /// Asynchronously fetches Formula 1 Circuits for a given year.
32 | /// - Parameters:
33 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020).
34 | /// - limit: Property to specify number of items to return per request.
35 | /// - offset: Property to indicate starting point of elements from API request.
36 | /// - Returns: A model representing Circuits
37 | public static func circuits(for season: Season, limit: String? = nil, offset: String? = nil) async throws -> Circuits {
38 | try await URLSession.shared.fetch(.circuits, for: season, limit: limit, offset: offset)
39 | }
40 |
41 | /// Fetches Formula 1 Circuits for all seasons throughout history.
42 | /// - Parameters:
43 | /// - limit: Optional property to specify number of items to return per request.
44 | /// - offset: Optional property to indicate starting point of elements from API request.
45 | /// - completion: Asynchronous closure to inject functionality once the network interaction completes.
46 | public static func allCircuits(limit: String? = nil,
47 | offset: String? = nil,
48 | completion: @escaping (Result) -> Void) {
49 |
50 | URLSession.shared.fetch(.circuits,
51 | limit: limit,
52 | offset: offset) { result in
53 | completion(result)
54 | }
55 | }
56 |
57 | /// Asynchronously fetches Formula 1 Circuits for all seasons throughout history.
58 | /// - Parameters:
59 | /// - limit: Optional property to specify number of items to return per request.
60 | /// - offset: Optional property to indicate starting point of elements from API request.
61 | /// - Returns: A model representing Circuits
62 | public static func allCircuits(limit: String? = nil, offset: String? = nil) async throws -> Circuits {
63 | try await URLSession.shared.fetch(.circuits, limit: limit, offset: offset)
64 | }
65 |
66 | /// Fetches Formula 1 Drivers - either all, or for a given year.
67 | /// - Parameters:
68 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020).
69 | /// - limit: Property to specify number of items to return per request.
70 | /// - offset: Property to indicate starting point of elements from API request.
71 | /// - completion: Asynchronous closure to inject functionality once the network interaction completes.
72 | public static func drivers(for season: Season,
73 | limit: String? = nil,
74 | offset: String? = nil,
75 | completion: @escaping (Result) -> Void) {
76 |
77 | URLSession.shared.fetch(.drivers,
78 | for: season,
79 | limit: limit,
80 | offset: offset) { result in
81 | completion(result)
82 | }
83 | }
84 |
85 | /// Asynchronously fetches Formula 1 Drivers - either all, or for a given year.
86 | /// - Parameters:
87 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020).
88 | /// - limit: Property to specify number of items to return per request.
89 | /// - offset: Property to indicate starting point of elements from API request.
90 | /// - Returns: A model representing Drivers
91 | public static func drivers(for season: Season, limit: String? = nil, offset: String? = nil) async throws -> Drivers {
92 | try await URLSession.shared.fetch(.drivers, for: season, limit: limit, offset: offset)
93 | }
94 |
95 | /// Fetches Formula 1 Seasons throughout history.
96 | /// - Parameters:
97 | /// - limit: Optional property to specify number of items to return per request.
98 | /// - offset: Optional property to indicate starting point of elements from API request.
99 | /// - completion: Asynchronous closure to inject functionality once the network interaction completes.
100 | public static func seasons(limit: String? = nil,
101 | offset: String? = nil,
102 | completion: @escaping (Result) -> Void) {
103 |
104 | URLSession.shared.fetch(.seasons,
105 | limit: limit,
106 | offset: offset) { result in
107 | completion(result)
108 | }
109 | }
110 |
111 | /// Asynchronously fetches Formula 1 Seasons throughout history.
112 | /// - Parameters:
113 | /// - limit: Optional property to specify number of items to return per request.
114 | /// - offset: Optional property to indicate starting point of elements from API request.
115 | /// - Returns: A model representing Seasons
116 | public static func seasons(limit: String? = nil, offset: String? = nil) async throws -> Seasons {
117 | try await URLSession.shared.fetch(.seasons, limit: limit, offset: offset)
118 | }
119 |
120 | /// Fetches Formula 1 Constructors for all seasons throughout history.
121 | /// - Parameters:
122 | /// - limit: Optional property to specify number of items to return per request.
123 | /// - offset: Optional property to indicate starting point of elements from API request.
124 | /// - completion: Asynchronous closure to inject functionality once the network interaction completes.
125 | public static func allConstructors(limit: String? = nil,
126 | offset: String? = nil,
127 | completion: @escaping (Result) -> Void) {
128 |
129 | URLSession.shared.fetch(.constructors,
130 | limit: limit,
131 | offset: limit) { result in
132 | completion(result)
133 | }
134 | }
135 |
136 | /// Asynchronously fetches Formula 1 Constructors for all seasons throughout history.
137 | /// - Parameters:
138 | /// - limit: Optional property to specify number of items to return per request.
139 | /// - offset: Optional property to indicate starting point of elements from API request.
140 | /// - Returns: A model representing Constructors
141 | public static func allConstructors(limit: String? = nil, offset: String? = nil) async throws -> Constructors {
142 | try await URLSession.shared.fetch(.constructors, limit: limit, offset: limit)
143 | }
144 |
145 | /// Fetches Formula 1 Constructors for a given season.
146 | /// - Parameters:
147 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020).
148 | /// - limit: Optional property to specify number of items to return per request.
149 | /// - offset: Optional property to indicate starting point of elements from API request.
150 | /// - completion: Asynchronous closure to inject functionality once the network interaction completes.
151 | public static func constructors(for season: Season,
152 | limit: String? = nil,
153 | offset: String? = nil,
154 | completion: @escaping (Result) -> Void) {
155 |
156 | URLSession.shared.fetch(.constructors,
157 | for: season,
158 | limit: limit,
159 | offset: limit) { result in
160 | completion(result)
161 | }
162 | }
163 |
164 | /// Asynchronously fetches Formula 1 Constructors for all seasons throughout history.
165 | /// - Parameters:
166 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020).
167 | /// - limit: Optional property to specify number of items to return per request.
168 | /// - offset: Optional property to indicate starting point of elements from API request.
169 | /// - Returns: A model representing Constructors
170 | public static func constructors(for season: Season, limit: String? = nil, offset: String? = nil) async throws -> Constructors {
171 | try await URLSession.shared.fetch(.constructors, for: season, limit: limit, offset: limit)
172 | }
173 |
174 | /// Fetchs Formula 1 Driver standings for a given year
175 | /// - Parameters:
176 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020).
177 | /// - limit: Optional property to specify number of items to return per request.
178 | /// - offset: Optional property to indicate starting point of elements from API request.
179 | /// - completion: Asynchronous closure to inject functionality once the network interaction completes.
180 | public static func driverStandings(for season: Season,
181 | limit: String? = nil,
182 | offset: String? = nil,
183 | completion: @escaping (Result) -> Void) {
184 |
185 | URLSession.shared.fetch(.driverStandings,
186 | for: season,
187 | limit: limit,
188 | offset: limit) { result in
189 | completion(result)
190 | }
191 | }
192 |
193 | /// Asynchronously fetchs Formula 1 Driver standings for a given year
194 | /// - Parameters:
195 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020).
196 | /// - limit: Optional property to specify number of items to return per request.
197 | /// - offset: Optional property to indicate starting point of elements from API request.
198 | /// - Returns: a model object that represents the driver standings for the spocified year
199 | public static func driverStandings(for season: Season, limit: String? = nil, offset: String? = nil) async throws -> DriverStandings {
200 | try await URLSession.shared.fetch(.driverStandings, for: season, limit: limit, offset: limit)
201 | }
202 |
203 | /// Fetches Formula 1 Race Schedule for a given year.
204 | /// - Parameters:
205 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020).
206 | /// - limit: Optional property to specify number of items to return per request.
207 | /// - offset: Optional property to indicate starting point of elements from API request.
208 | /// - completion: Asynchronous closure to inject functionality once the network interaction completes.
209 | public static func raceSchedule(for season: Season,
210 | limit: String? = nil,
211 | offset: String? = nil,
212 | completion: @escaping (Result) -> Void) {
213 |
214 | URLSession.shared.fetch(.raceSchedule,
215 | for: season,
216 | limit: limit,
217 | offset: offset) { result in
218 | completion(result)
219 | }
220 | }
221 |
222 | /// Asynchronously fetches Formula 1 Race Schedule for a given year.
223 | /// - Parameters:
224 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020).
225 | /// - limit: Optional property to specify number of items to return per request.
226 | /// - offset: Optional property to indicate starting point of elements from API request.
227 | /// - Returns: A model representing a Race Schedule
228 | public static func raceSchedule(for season: Season, limit: String? = nil, offset: String? = nil) async throws -> RaceSchedule {
229 | try await URLSession.shared.fetch(.raceSchedule, for: season, limit: limit, offset: offset)
230 | }
231 |
232 | /// Fetches Formula 1 Race Results for a given year.
233 | /// - Parameters:
234 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020).
235 | /// - limit: Optional property to specify number of items to return per request.
236 | /// - offset: Optional property to indicate starting point of elements from API request.
237 | /// - completion: Asynchronous closure to inject functionality once the network interaction completes.
238 | public static func raceResults(for season: Season,
239 | limit: String? = nil,
240 | offset: String? = nil,
241 | completion: @escaping(Result) -> Void) {
242 |
243 | URLSession.shared.fetch(.raceResults,
244 | for: season,
245 | limit: limit,
246 | offset: offset) { result in
247 | completion(result)
248 | }
249 | }
250 |
251 | /// Asynchronously fetches Formula 1 Race Results for a given year.
252 | /// - Parameters:
253 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020).
254 | /// - limit: Optional property to specify number of items to return per request.
255 | /// - offset: Optional property to indicate starting point of elements from API request.
256 | /// - Returns: A model that represents a race result.
257 | public static func raceResults(for season: Season, limit: String? = nil, offset: String? = nil) async throws -> RaceResults {
258 | try await URLSession.shared.fetch(.raceResults, for: season, limit: limit, offset: offset)
259 | }
260 |
261 | /// Fetches Qualifying Results for a given year.
262 | /// - Parameters:
263 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020).
264 | /// - limit: Optional property to specify number of items to return per request.
265 | /// - offset: Optional property to indicate starting point of elements from API request.
266 | /// - completion: Asynchronous closure to inject functionality once the network interaction completes.
267 | public static func qualifyingResults(for season: Season,
268 | limit: String? = nil,
269 | offset: String? = nil,
270 | completion: @escaping (Result) -> Void) {
271 |
272 | URLSession.shared.fetch(.qualifyingResults,
273 | for: season,
274 | limit: limit,
275 | offset: offset) { result in
276 | completion(result)
277 | }
278 | }
279 |
280 | /// Fetches Qualifying Results for a given year.
281 | /// - Parameters:
282 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020).
283 | /// - limit: Optional property to specify number of items to return per request.
284 | /// - offset: Optional property to indicate starting point of elements from API request.
285 | /// - Returns: A model that represents a qualifying result.
286 | public static func qualifyingResults(for season: Season, limit: String? = nil, offset: String? = nil) async throws -> QualifyingResults {
287 | try await URLSession.shared.fetch(.qualifyingResults, for: season, limit: limit, offset: offset)
288 | }
289 |
290 | /// Fetches Pit Stops for a given year and round.
291 | /// - Parameters:
292 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020).
293 | /// - round: A race within the season.
294 | /// - limit: Property to specify number of items to return per request.
295 | /// - offset: Property to indicate starting point of elements from API request.
296 | /// - completion: Asynchronous closure to inject functionality once the network interaction completes.
297 | public static func pitStops(for season: Season,
298 | round: String,
299 | limit: String? = nil,
300 | offset: String? = nil,
301 | completion: @escaping (Result) -> Void) {
302 |
303 | URLSession.shared.fetch(.pitStops,
304 | for: season,
305 | round: round,
306 | limit: limit,
307 | offset: offset) { result in
308 | completion(result)
309 | }
310 | }
311 |
312 | /// Asynchronously fetches Pit Stops for a given year and round.
313 | /// - Parameters:
314 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020).
315 | /// - round: A race within the season.
316 | /// - limit: Property to specify number of items to return per request.
317 | /// - offset: Property to indicate starting point of elements from API request.
318 | /// - Returns: A model representing pit stops.
319 | public static func pitStops(for season: Season, round: String, limit: String? = nil, offset: String? = nil) async throws -> PitStops {
320 | try await URLSession.shared.fetch(.pitStops, for: season, round: round, limit: limit, offset: offset)
321 | }
322 |
323 | /// Fetches lap times for a lap within a race.
324 | /// - Parameters:
325 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020).
326 | /// - round: A race within the season.
327 | /// - lap: Lap of given race.
328 | /// - limit: Property to specify number of items to return per request.
329 | /// - offset: Property to indicate starting point of elements from API request.
330 | /// - completion: Asynchronous closure to inject functionality once the network interaction completes.
331 | public static func laps(for season: Season,
332 | round: String,
333 | lap: String? = nil,
334 | limit: String? = nil,
335 | offset: String? = nil,
336 | completion: @escaping (Result) -> Void) {
337 |
338 | URLSession.shared.fetch(.lapTimes(lap),
339 | for: season,
340 | round: round,
341 | limit: limit,
342 | offset: offset) { result in
343 | completion(result)
344 | }
345 | }
346 |
347 | /// Asynnchronouslt fetches lap times for a lap within a race.
348 | /// - Parameters:
349 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020).
350 | /// - round: A race within the season.
351 | /// - lap: Lap of given race.
352 | /// - limit: Property to specify number of items to return per request.
353 | /// - offset: Property to indicate starting point of elements from API request.
354 | /// - Returns: A model that represents laps.
355 | public static func laps(for season: Season, round: String, lap: String? = nil, limit: String? = nil, offset: String? = nil) async throws -> Laps {
356 | try await URLSession.shared.fetch(.lapTimes(lap), for: season, round: round, limit: limit, offset: offset)
357 | }
358 |
359 | /// Fetches finishing status for given season.
360 | /// - Parameters:
361 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020).
362 | /// - round: A race within the season.
363 | /// - limit: Property to specify number of items to return per request.
364 | /// - offset: Property to indicate starting point of elements from API request.
365 | /// - completion: Asynchronous closure to inject functionality once the network interaction completes.
366 | public static func finishingStatus(for season: Season,
367 | round: String? = nil,
368 | limit: String? = nil,
369 | offset: String? = nil,
370 | completion: @escaping (Result) -> Void) {
371 |
372 | URLSession.shared.fetch(.finishingStatus,
373 | for: season,
374 | limit: limit,
375 | offset: offset) { result in
376 | completion(result)
377 | }
378 | }
379 |
380 | /// Asynchronously fetches finishing status for given season.
381 | /// - Parameters:
382 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020).
383 | /// - round: A race within the season.
384 | /// - limit: Property to specify number of items to return per request.
385 | /// - offset: Property to indicate starting point of elements from API request.
386 | /// - Returns: A model that representes a finishing status.
387 | public static func finishingStatus(
388 | for season: Season,
389 | round: String? = nil,
390 | limit: String? = nil,
391 | offset: String? = nil
392 | ) async throws -> FinishingStatus {
393 | try await URLSession.shared.fetch(.finishingStatus, for: season, limit: limit, offset: offset)
394 | }
395 | }
396 |
--------------------------------------------------------------------------------
/Sources/Formula1API/Helpers/Endpoint.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Endpoint.swift
3 | //
4 | //
5 | // Created by Giovanni Noa on 4/28/20.
6 | //
7 |
8 | import Foundation
9 |
10 |
11 | /// Internal struct for query items used in Ergast URLs.
12 | private enum ErgastQueryItems {
13 | /// Limit indicator, to specify to the API how many items to return at a time per request.
14 | case limit(String?)
15 |
16 | /// Offset indicator, to specify to the API the starting point of elements.
17 | case offset(String?)
18 | }
19 |
20 | /// Indicates URL components for the Ergast REST API.
21 | private enum ErgastEndpoint {
22 | /// URL scheme.
23 | static let scheme = "https"
24 |
25 | /// URL host.
26 | static let host = "ergast.com"
27 | }
28 |
29 | /// Generates a URL for a given Path enum case.
30 | internal struct Endpoint {
31 | /// URL for Ergast API.
32 | private let urlPath: String
33 |
34 | /// Indicates number of items to return per request.
35 | private var limit: String?
36 |
37 | /// Indicates the starting point of elements from API request.
38 | private var offset: String?
39 |
40 | /// Initializer for an Endpoint object.
41 | /// - Parameters:
42 | /// - path: Specify a path, mapping to a specific endpoint of the Ergast REST API.
43 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020). All historical seasons will be fetched if nil.
44 | /// - limit: Optional property to specify number of items to return per request.
45 | /// - offset: Optional property to indicate starting point of elements from API request.
46 | init(with path: Path,
47 | for season: Season?,
48 | round: String?,
49 | lap: String?,
50 | limit: String?,
51 | offset: String?) {
52 |
53 | urlPath = path.urlPath(for: season, round: round, lap: lap)
54 |
55 | self.limit = limit
56 | self.offset = offset
57 | }
58 | }
59 |
60 | // MARK: - Endpoint URL Builder
61 | extension Endpoint {
62 | /// URL for the given path.
63 | var url: URL {
64 | var components = URLComponents()
65 | components.scheme = ErgastEndpoint.scheme
66 | components.host = ErgastEndpoint.host
67 | components.path = urlPath
68 |
69 | var queryItems: [URLQueryItem] = .init()
70 |
71 | if let limit = limit {
72 | let item = URLQueryItem(name: "limit", value: limit)
73 | queryItems.append(item)
74 | }
75 |
76 | if let offset = offset {
77 | let item = URLQueryItem(name: "offset", value: offset)
78 | queryItems.append(item)
79 | }
80 |
81 | components.queryItems = queryItems
82 |
83 | guard let validURL = components.url else { fatalError("Could not construct URL.") }
84 |
85 | return validURL
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/Sources/Formula1API/Helpers/Extensions/Decodable+Extension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Decodable+Extension.swift
3 | //
4 | //
5 | // Created by Giovanni Noa on 5/8/20.
6 | //
7 |
8 | import Foundation
9 |
10 | extension Decodable {
11 | static func decode(from: Data,
12 | using decoder: JSONDecoder = JSONDecoder()) throws -> Self {
13 | return try decoder.decode(self, from: from)
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Sources/Formula1API/Helpers/Extensions/URLSession+Extension.swift:
--------------------------------------------------------------------------------
1 | //
2 | // URLSession+Extension.swift
3 | //
4 | //
5 | // Created by Giovanni Noa on 4/28/20.
6 | //
7 |
8 | import Foundation
9 |
10 | // MARK: - URLSession
11 | extension URLSession {
12 | /// Callback-based networking data task. Called by the internal fetch function.
13 | /// - Parameters:
14 | /// - url: URL to reach.
15 | /// - session: URLSession instance.
16 | /// - completion: Asynchronous closure to inject functionality once the network interaction completes.
17 | private func dataTask(_ url: URL,
18 | _ session: URLSession,
19 | completion: @escaping ((Result) -> Void)) {
20 | session.dataTask(with: url) { data, response, error in
21 | guard let data = data, error == nil else {
22 | if let error = error {
23 | completion(.failure(.network(error.localizedDescription)))
24 | } else {
25 | completion(.failure(.data("Failed to generate data.")))
26 | }
27 | return
28 | }
29 | completion(.success(data))
30 | }
31 | .resume()
32 | }
33 |
34 | /// Callback-based networking fetch function. Calls the data task function and decodes the JSON response.
35 | /// - Parameters:
36 | /// - subPath: Path enum case to indicate which endpoint you wish to fetch from.
37 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020). Fetches data for all historical seasons of given endpoint if nil.
38 | /// - session: URLSession instance (URLSession.shared singleton by default)
39 | /// - decodingType: Decodable-conforming object to be used for serializing JSON response.
40 | /// - completion: Asynchronous closure to inject functionality once the network interaction finishes fetching.
41 | internal func fetch(_ subPath: Path,
42 | for season: Season? = nil,
43 | round: String? = nil,
44 | lap: String? = nil,
45 | limit: String? = nil,
46 | offset: String? = nil,
47 | session: URLSession = URLSession.shared,
48 | completion: @escaping ((Result) -> Void)) {
49 | let endpoint = Endpoint(with: subPath,
50 | for: season,
51 | round: round,
52 | lap: lap,
53 | limit: limit,
54 | offset: offset)
55 | let url = endpoint.url
56 |
57 | session.dataTask(url, session) { result in
58 | switch result {
59 | case .success(let data):
60 | do {
61 | let decode = try subPath.decodingType.decode(from: data)
62 |
63 | completion(.success(decode as! T))
64 | } catch (let error) {
65 | print(error)
66 | completion(.failure(.network(error.localizedDescription)))
67 | }
68 | case .failure(let error):
69 | print(error)
70 | completion(.failure(error))
71 | }
72 | }
73 | }
74 |
75 | /// Async/await networking fetch function.
76 | ///
77 | /// Calls the data task function and decodes the JSON response.
78 | ///
79 | /// - Parameters:
80 | /// - subPath: Path enum case to indicate which endpoint you wish to fetch from.
81 | /// - season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020). Fetches data for all historical seasons of given endpoint if nil.
82 | /// - round: A race within the season.
83 | /// - lap: Lap of given race.
84 | /// - limit: Property to specify number of items to return per request.
85 | /// - offset: Property to indicate starting point of elements from API request.
86 | /// - session: URLSession instance (URLSession.shared singleton by default)
87 | /// - Returns: A model represeting the decodeable model that is specified by the `subPath` parameter.
88 | internal func fetch(
89 | _ subPath: Path,
90 | for season: Season? = nil,
91 | round: String? = nil,
92 | lap: String? = nil,
93 | limit: String? = nil,
94 | offset: String? = nil,
95 | session: URLSession = URLSession.shared
96 | ) async throws -> T {
97 | try await withCheckedThrowingContinuation { [weak self] continuation in
98 | self?.fetch(
99 | subPath,
100 | for: season,
101 | round: round,
102 | lap: lap,
103 | limit: limit,
104 | offset: offset,
105 | session: session
106 | ) { result in
107 | continuation.resume(with: result)
108 | }
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/Sources/Formula1API/Helpers/Path.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Path.swift
3 | //
4 | //
5 | // Created by Giovanni Noa on 4/29/20.
6 | //
7 |
8 | // MARK: - Path
9 | /// Enum containing the sub-path for specifying an endpoint within the Ergast API.
10 | enum Path {
11 | private static let basePath = "/api/f1"
12 |
13 | /// Circuits (all, specific season)
14 | case circuits
15 |
16 | /// Constructors(all, specific season)
17 | case constructors
18 |
19 | /// Constructor Standings (all, specific season)
20 | case constructorStandings
21 |
22 | /// Drivers (all, specific season).
23 | case drivers
24 |
25 | /// Driver Standings.
26 | case driverStandings
27 |
28 | /// Finishing Status
29 | case finishingStatus
30 |
31 | /// Lap Times.
32 | case lapTimes(String?)
33 |
34 | /// Pit Stops.
35 | case pitStops
36 |
37 | /// Race Schedule.
38 | case raceSchedule
39 |
40 | /// Race Results.
41 | case raceResults
42 |
43 | /// Race Standings (all, specific season).
44 | case raceStandings
45 |
46 | /// Seasons throughout history.
47 | case seasons
48 |
49 | /// Qualifying Results for a given year.
50 | case qualifyingResults
51 | }
52 |
53 | extension Path {
54 | /// Function that generates the path for an endpoint within the Ergast API.
55 | /// - Parameter season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020). Data for historical seasons will be fetched if nil.
56 | /// - Returns: String to be added to the Endpoint path.
57 | private func subPath(for season: Season? = nil,
58 | round: String? = nil) -> String {
59 |
60 | let year = season?.query ?? ""
61 | let race = round ?? ""
62 |
63 | switch self {
64 | case .circuits:
65 | return "\(year)/circuits.json"
66 |
67 | case .constructors:
68 | return "\(year)/constructors.json"
69 |
70 | case .constructorStandings:
71 | return "\(year)/constructorStandings.json"
72 |
73 | case .drivers:
74 | return "\(year)/drivers.json"
75 |
76 | case .driverStandings:
77 | return "\(year)/driverStandings.json"
78 |
79 | case .finishingStatus:
80 | if race != "" {
81 | return "\(year)/\(race)/status.json"
82 | }
83 |
84 | return "\(year)/status.json"
85 |
86 | case .lapTimes(let lap):
87 | if let lap = lap {
88 | return "\(year)/\(race)/laps/\(lap).json"
89 | }
90 |
91 | return "\(year)/\(race)/laps.json"
92 |
93 | case .pitStops:
94 | return "\(year)/\(race)/pitstops.json"
95 |
96 | case .raceSchedule:
97 | return "\(year).json"
98 |
99 | case .raceResults:
100 | return "\(year)/results.json"
101 |
102 | case .raceStandings:
103 | return "\(year)/results.json"
104 |
105 | case .seasons:
106 | return "/seasons.json"
107 |
108 | case .qualifyingResults:
109 | return "\(year)/qualifying.json"
110 | }
111 | }
112 |
113 | /// Constructs a path.
114 | /// - Parameter season: Season enum case, specified by an Int, which indicates to fetch data for a given year (1950-2020). All historical seasons will be fetched if nil.
115 | /// - Returns: String representing a URL path.
116 | func urlPath(for season: Season?,
117 | round: String?,
118 | lap: String?) -> String {
119 | return Path.basePath + subPath(for: season,
120 | round: round)
121 | }
122 |
123 | /// Returns a Decodable type for a given endpoint.
124 | var decodingType: Decodable.Type {
125 | switch self {
126 | case .circuits: return Circuits.self
127 | case .constructors: return Constructors.self
128 | case .drivers: return Drivers.self
129 | case .driverStandings: return DriverStandings.self
130 | case .finishingStatus: return FinishingStatus.self
131 | case .lapTimes(_): return Laps.self
132 | case .seasons: return Seasons.self
133 | case .pitStops: return PitStops.self
134 | case .raceResults: return RaceResults.self
135 | case .raceSchedule: return RaceSchedule.self
136 | case .qualifyingResults: return QualifyingResults.self
137 | default: fatalError("Must provide Decodable type for enum case")
138 | }
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/Sources/Formula1API/Helpers/Season.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Season.swift
3 | //
4 | //
5 | // Created by Giovanni Noa on 5/4/20.
6 | //
7 |
8 | import Foundation
9 |
10 | // MARK: - Season
11 | /// Season enum to indicate whether a networking function is to fetch all historical data, or data for a single season.
12 | public enum Season {
13 | /// A year, representing a specific season (1950-2021).
14 | case year(Int)
15 |
16 | /// All historical data endpoint (1950-2021).
17 | case all
18 | }
19 |
20 | extension Season {
21 | /// Function to be used by the Path endpoint builder.
22 | /// - Returns: String that will be part of the resultant URL.
23 | var query: String? {
24 | switch self {
25 | case .year(let year):
26 | return "/\(year)"
27 | case .all:
28 | return ""
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Sources/Formula1API/Models/Circuits.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Circuits.swift
3 | //
4 | //
5 | // Created by Giovanni Noa on 5/5/20.
6 | //
7 |
8 | /// Codable struct, used for serializing JSON from the Circuits endpoint.
9 | public struct Circuits: Codable {
10 | public let data: CircuitData
11 |
12 | private enum CodingKeys: String, CodingKey {
13 | case data = "MRData"
14 | }
15 | }
16 |
17 | public extension Circuits {
18 | var currentCircuits: [Circuit] { self.data.circuitTable.circuits }
19 | }
20 |
21 | public struct CircuitData: Codable {
22 | public let url: String
23 | public let limit: String
24 | public let offset: String
25 | public let total: String
26 | public let circuitTable: CircuitTable
27 |
28 | private enum CodingKeys: String, CodingKey {
29 | case url
30 | case limit
31 | case offset
32 | case total
33 | case circuitTable = "CircuitTable"
34 | }
35 | }
36 |
37 | public struct CircuitTable: Codable {
38 | public let season: String?
39 | public let circuits: [Circuit]
40 |
41 | private enum CodingKeys: String, CodingKey {
42 | case circuits = "Circuits"
43 | case season
44 | }
45 | }
46 |
47 | public struct Circuit: Codable {
48 | public let circuitID: String
49 | public let circuitName: String
50 | public let location: Location
51 |
52 | private enum CodingKeys: String, CodingKey {
53 | case circuitID = "circuitId"
54 | case circuitName
55 | case location = "Location"
56 | }
57 | }
58 |
59 | public struct Location: Codable {
60 | public let lat: String
61 | public let long: String
62 | public let locality: String
63 | public let country: String
64 | }
65 |
--------------------------------------------------------------------------------
/Sources/Formula1API/Models/Constructors.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Constructors.swift
3 | //
4 | //
5 | // Created by Giovanni Noa on 5/9/20.
6 | //
7 |
8 | import Foundation
9 |
10 | /// Codable struct, used for serializing JSON from the Constructors endpoint.
11 | public struct Constructors: Codable {
12 | public let data: ConstructorsData
13 |
14 | private enum CodingKeys: String, CodingKey {
15 | case data = "MRData"
16 | }
17 | }
18 |
19 | public struct ConstructorsData: Codable {
20 | public let xmlns: String
21 | public let series: String
22 | public let url: String
23 | public let limit: String
24 | public let offset: String
25 | public let total: String
26 | public let constructorTable: ConstructorTable
27 |
28 | private enum CodingKeys: String, CodingKey {
29 | case xmlns
30 | case series
31 | case url
32 | case limit
33 | case offset
34 | case total
35 | case constructorTable = "ConstructorTable"
36 | }
37 | }
38 |
39 | public struct ConstructorTable: Codable {
40 | public let season: String?
41 | public let constructors: [Constructor]
42 |
43 | private enum CodingKeys: String, CodingKey {
44 | case season
45 | case constructors = "Constructors"
46 | }
47 | }
48 |
49 | public struct Constructor: Codable {
50 | public let constructorID: String
51 | public let url: String
52 | public let name: String
53 | public let nationality: String
54 |
55 | private enum CodingKeys: String, CodingKey {
56 | case constructorID = "constructorId"
57 | case url
58 | case name
59 | case nationality
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Sources/Formula1API/Models/DriverStandings.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DriverStandings.swift
3 | //
4 | //
5 | // Created by Giovanni Noa on 6/12/20.
6 | //
7 |
8 | import Foundation
9 |
10 | /// Codable struct, used for serializing JSON from the DriverStandings endpoint.
11 | public struct DriverStandings: Codable {
12 | public let data: DriverStandingsData
13 |
14 | private enum CodingKeys: String, CodingKey {
15 | case data = "MRData"
16 | }
17 | }
18 |
19 | public struct DriverStandingsData: Codable {
20 | public let series: String
21 | public let url: String
22 | public let limit: String
23 | public let offset: String
24 | public let total: String
25 | public let standingsTable: StandingsTable
26 |
27 | private enum CodingKeys: String, CodingKey {
28 | case series
29 | case url
30 | case limit
31 | case offset
32 | case total
33 | case standingsTable = "StandingsTable"
34 | }
35 | }
36 |
37 | public struct StandingsTable: Codable {
38 | public let season: String?
39 | public let standingsLists: [StandingsList]
40 |
41 | private enum CodingKeys: String, CodingKey {
42 | case season
43 | case standingsLists = "StandingsLists"
44 | }
45 | }
46 |
47 | public struct StandingsList: Codable {
48 | public let season, round: String
49 | public let driverStandings: [DriverStanding]
50 |
51 | private enum CodingKeys: String, CodingKey {
52 | case season
53 | case round
54 | case driverStandings = "DriverStandings"
55 | }
56 | }
57 |
58 | public struct DriverStanding: Codable {
59 | public let position: String
60 | public let positionText: String
61 | public let points: String
62 | public let wins: String
63 | public let driver: Driver
64 | public let constructors: [Constructor]
65 |
66 | private enum CodingKeys: String, CodingKey {
67 | case position
68 | case positionText
69 | case points
70 | case wins
71 | case driver = "Driver"
72 | case constructors = "Constructors"
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Sources/Formula1API/Models/Drivers.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DriverInfo.swift
3 | //
4 | //
5 | // Created by Giovanni Noa on 6/12/20.
6 | //
7 |
8 | import Foundation
9 |
10 | /// Codable struct, used for serializing JSON from the Drivers endpoint.
11 | public struct Drivers: Codable {
12 | public let data: DriversData
13 |
14 | private enum CodingKeys: String, CodingKey {
15 | case data = "MRData"
16 | }
17 | }
18 |
19 | public struct DriversData: Codable {
20 | public let series: String
21 | public let url: String
22 | public let limit: String
23 | public let offset: String
24 | public let total: String
25 | public let driverTable: DriverTable
26 |
27 | private enum CodingKeys: String, CodingKey {
28 | case series
29 | case url
30 | case limit
31 | case offset
32 | case total
33 | case driverTable = "DriverTable"
34 | }
35 | }
36 |
37 | public struct DriverTable: Codable {
38 | public let season: String?
39 | public let drivers: [Driver]
40 |
41 | private enum CodingKeys: String, CodingKey {
42 | case season
43 | case drivers = "Drivers"
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Sources/Formula1API/Models/FinishingStatus.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FinishingStatus.swift
3 | //
4 | //
5 | // Created by Giovanni Noa on 6/12/20.
6 | //
7 |
8 | import Foundation
9 |
10 | /// Codable struct, used for serializing JSON from the FinishingStatus endpoint.
11 | public struct FinishingStatus: Codable {
12 | public let data: FinishingStatusData
13 |
14 | private enum CodingKeys: String, CodingKey {
15 | case data = "MRData"
16 | }
17 | }
18 |
19 | public struct FinishingStatusData: Codable {
20 | public let series: String
21 | public let url: String
22 | public let limit: String
23 | public let offset: String
24 | public let total: String
25 | public let statusTable: StatusTable
26 |
27 | private enum CodingKeys: String, CodingKey {
28 | case series
29 | case url
30 | case limit
31 | case offset
32 | case total
33 | case statusTable = "StatusTable"
34 | }
35 | }
36 |
37 | public struct StatusTable: Codable {
38 | public let season: String
39 | public let status: [Status]
40 |
41 | private enum CodingKeys: String, CodingKey {
42 | case season
43 | case status = "Status"
44 | }
45 | }
46 |
47 | public struct Status: Codable {
48 | public let statusID: String
49 | public let count: String
50 | public let status: String
51 |
52 | private enum CodingKeys: String, CodingKey {
53 | case statusID = "statusId"
54 | case count
55 | case status
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Sources/Formula1API/Models/Laps.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Lap.swift
3 | //
4 | //
5 | // Created by Giovanni Noa on 6/11/20.
6 | //
7 |
8 | import Foundation
9 |
10 | /// Codable struct, used for serializing JSON from the Laps endpoint.
11 | public struct Laps: Codable {
12 | public let data: LapsData
13 |
14 | private enum CodingKeys: String, CodingKey {
15 | case data = "MRData"
16 | }
17 | }
18 |
19 | public struct LapsData: Codable {
20 | public let series: String
21 | public let url: String
22 | public let limit: String
23 | public let offset: String
24 | public let total: String
25 | public let raceTable: RaceTable
26 |
27 | private enum CodingKeys: String, CodingKey {
28 | case series
29 | case url
30 | case limit
31 | case offset
32 | case total
33 | case raceTable = "RaceTable"
34 | }
35 | }
36 |
37 | public struct LapElement: Codable {
38 | public let number: String
39 | public let timings: [Timing]
40 |
41 | private enum CodingKeys: String, CodingKey {
42 | case number
43 | case timings = "Timings"
44 | }
45 | }
46 |
47 | public struct Timing: Codable {
48 | public let driverID: String
49 | public let position: String
50 | public let time: String
51 |
52 | private enum CodingKeys: String, CodingKey {
53 | case driverID = "driverId"
54 | case position
55 | case time
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Sources/Formula1API/Models/PitStops.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PitStops.swift
3 | //
4 | //
5 | // Created by Giovanni Noa on 6/10/20.
6 | //
7 |
8 | import Foundation
9 |
10 | /// Codable struct, used for serializing JSON from the PitStops endpoint.
11 | public struct PitStops: Codable {
12 | public let data: PitStopsData
13 |
14 | private enum CodingKeys: String, CodingKey {
15 | case data = "MRData"
16 | }
17 | }
18 |
19 | public struct PitStopsData: Codable {
20 | public let series: String
21 | public let url: String
22 | public let limit: String
23 | public let offset: String
24 | public let total: String
25 | public let raceTable: RaceTable
26 |
27 | private enum CodingKeys: String, CodingKey {
28 | case series
29 | case url
30 | case limit
31 | case offset
32 | case total
33 | case raceTable = "RaceTable"
34 | }
35 | }
36 |
37 | public struct PitStop: Codable {
38 | public let driverID: String
39 | public let lap: String
40 | public let stop: String
41 | public let time: String
42 | public let duration: String
43 |
44 | private enum CodingKeys: String, CodingKey {
45 | case driverID = "driverId"
46 | case lap
47 | case stop
48 | case time
49 | case duration
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Sources/Formula1API/Models/QualifyingResults.swift:
--------------------------------------------------------------------------------
1 | //
2 | // QualifyingResults.swift
3 | //
4 | //
5 | // Created by Giovanni Noa on 6/3/20.
6 | //
7 |
8 | import Foundation
9 |
10 | /// Codable struct, used for serializing JSON from the QualifyingResults endpoint.
11 | public struct QualifyingResults: Codable {
12 | public let data: QualifyingResultsData
13 |
14 | enum CodingKeys: String, CodingKey {
15 | case data = "MRData"
16 | }
17 | }
18 |
19 | public struct QualifyingResultsData: Codable {
20 | public let series: String
21 | public let url: String
22 | public let limit: String
23 | public let offset: String
24 | public let total: String
25 | public let raceTable: RaceTable
26 |
27 | private enum CodingKeys: String, CodingKey {
28 | case series
29 | case url
30 | case limit
31 | case offset
32 | case total
33 | case raceTable = "RaceTable"
34 | }
35 | }
36 |
37 | public struct QualifyingResult: Codable {
38 | public let number: String
39 | public let position: String
40 | public let driver: Driver
41 | public let constructor: Constructor
42 | public let q1: String
43 | public let q2: String?
44 | public let q3: String?
45 |
46 | private enum CodingKeys: String, CodingKey {
47 | case number
48 | case position
49 | case driver = "Driver"
50 | case constructor = "Constructor"
51 | case q1 = "Q1"
52 | case q2 = "Q2"
53 | case q3 = "Q3"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Sources/Formula1API/Models/RaceResults.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RaceResults.swift
3 | //
4 | //
5 | // Created by Giovanni Noa on 5/11/20.
6 | //
7 |
8 | import Foundation
9 |
10 | /// Codable struct, used for serializing JSON from the RaceResults endpoint.
11 | public struct RaceResults: Codable {
12 | public let data: RaceResultsData
13 |
14 | private enum CodingKeys: String, CodingKey {
15 | case data = "MRData"
16 | }
17 | }
18 |
19 | public struct RaceResultsData: Codable {
20 | public let series: String
21 | public let url: String
22 | public let limit: String
23 | public let offset: String
24 | public let total: String
25 | public let raceTable: RaceTable
26 |
27 | private enum CodingKeys: String, CodingKey {
28 | case series
29 | case url
30 | case limit
31 | case offset
32 | case total
33 | case raceTable = "RaceTable"
34 | }
35 | }
36 |
37 | public struct RaceResult: Codable {
38 | public let number: String
39 | public let position: String
40 | public let positionText: String
41 | public let points: String
42 | public let driver: Driver
43 | public let constructor: Constructor
44 | public let grid, laps, status: String
45 | public let time: ResultTime?
46 | public let fastestLap: FastestLap
47 |
48 | private enum CodingKeys: String, CodingKey {
49 | case number
50 | case position
51 | case positionText
52 | case points
53 | case driver = "Driver"
54 | case constructor = "Constructor"
55 | case grid, laps, status
56 | case time = "Time"
57 | case fastestLap = "FastestLap"
58 | }
59 | }
60 |
61 | public struct Driver: Codable {
62 | public let driverID: String
63 | public let permanentNumber: String?
64 | public let code: String?
65 | public let url: String
66 | public let givenName: String
67 | public let familyName: String
68 | public let dateOfBirth: String
69 | public let nationality: String
70 |
71 | private enum CodingKeys: String, CodingKey {
72 | case driverID = "driverId"
73 | case permanentNumber
74 | case code
75 | case url
76 | case givenName
77 | case familyName
78 | case dateOfBirth
79 | case nationality
80 | }
81 | }
82 |
83 | public struct FastestLap: Codable {
84 | public let rank: String
85 | public let lap: String
86 | public let time: FastestLapTime
87 | public let averageSpeed: AverageSpeed
88 |
89 | private enum CodingKeys: String, CodingKey {
90 | case rank
91 | case lap
92 | case time = "Time"
93 | case averageSpeed = "AverageSpeed"
94 | }
95 | }
96 |
97 | public struct AverageSpeed: Codable {
98 | public let units: Units
99 | public let speed: String
100 | }
101 |
102 | public enum Units: String, Codable {
103 | case kph = "kph"
104 | }
105 |
106 | public struct FastestLapTime: Codable {
107 | public let time: String
108 | }
109 |
110 | public struct ResultTime: Codable {
111 | public let millis: String
112 | public let time: String
113 | }
114 |
--------------------------------------------------------------------------------
/Sources/Formula1API/Models/RaceSchedule.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RaceSchedule.swift
3 | //
4 | //
5 | // Created by Giovanni Noa on 5/10/20.
6 | //
7 |
8 | import Foundation
9 |
10 | /// Codable struct, used for serializing JSON from the RaceSchedule endpoint.
11 | public struct RaceSchedule: Codable {
12 | public let data: RaceScheduleData
13 |
14 | private enum CodingKeys: String, CodingKey {
15 | case data = "MRData"
16 | }
17 | }
18 |
19 | public struct RaceScheduleData: Codable {
20 | public let series: String
21 | public let url: String
22 | public let limit: String
23 | public let offset: String
24 | public let total: String
25 | public let raceTable: RaceTable
26 |
27 | private enum CodingKeys: String, CodingKey {
28 | case series
29 | case url
30 | case limit
31 | case offset
32 | case total
33 | case raceTable = "RaceTable"
34 | }
35 | }
36 |
37 | public struct RaceTable: Codable {
38 | public let season: String
39 | public let round: String?
40 | public let races: [Race]
41 |
42 | private enum CodingKeys: String, CodingKey {
43 | case season
44 | case round
45 | case races = "Races"
46 | }
47 | }
48 |
49 | public struct Race: Codable {
50 | public let season: String
51 | public let round: String
52 | public let url: String
53 | public let raceName: String
54 | public let circuit: Circuit
55 | public let date: String
56 | public let time: String
57 | public let qualifyingResults: [QualifyingResult]?
58 | public let pitStops: [PitStop]?
59 | public let laps: [LapElement]?
60 |
61 |
62 | private enum CodingKeys: String, CodingKey {
63 | case season
64 | case round
65 | case url
66 | case raceName
67 | case circuit = "Circuit"
68 | case date
69 | case time
70 | case qualifyingResults = "QualifyingResults"
71 | case pitStops = "PitStops"
72 | case laps = "Laps"
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Sources/Formula1API/Models/Seasons.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Seasons.swift
3 | //
4 | //
5 | // Created by Giovanni Noa on 5/7/20.
6 | //
7 |
8 | /// Codable struct, used for serializing JSON from the Seasons endpoint.
9 | public struct Seasons: Codable {
10 | public let data: SeasonData
11 |
12 | private enum CodingKeys: String, CodingKey {
13 | case data = "MRData"
14 | }
15 | }
16 |
17 | public struct SeasonData: Codable {
18 | public let series: String
19 | public let url: String
20 | public let limit: String
21 | public let offset: String
22 | public let total: String
23 | public let seasonTable: SeasonTable
24 |
25 | private enum CodingKeys: String, CodingKey {
26 | case series
27 | case url
28 | case limit
29 | case offset
30 | case total
31 | case seasonTable = "SeasonTable"
32 | }
33 | }
34 |
35 | public struct SeasonTable: Codable {
36 | public let seasons: [F1Season]
37 |
38 | private enum CodingKeys: String, CodingKey {
39 | case seasons = "Seasons"
40 | }
41 | }
42 |
43 | public struct F1Season: Codable {
44 | public let season: String
45 | public let url: String
46 | }
47 |
--------------------------------------------------------------------------------
/Tests/ErgastAPITests/EndpointTests.swift:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Tests/ErgastAPITests/ErgastAPITests.swift:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Tests/ErgastAPITests/XCTestManifests.swift:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Tests/LinuxMain.swift:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------