From 836c083506849c2c997f2db4bef3eb5d0da972e5 Mon Sep 17 00:00:00 2001 From: ribilynn Date: Thu, 9 Jun 2022 17:46:53 +0900 Subject: [PATCH 1/5] Replace Temp with Temperature --- Sources/YumemiWeather/YumemiWeather.swift | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Sources/YumemiWeather/YumemiWeather.swift b/Sources/YumemiWeather/YumemiWeather.swift index 049a86c..c2a3c75 100644 --- a/Sources/YumemiWeather/YumemiWeather.swift +++ b/Sources/YumemiWeather/YumemiWeather.swift @@ -7,8 +7,8 @@ struct Request: Decodable { struct Response: Codable, Equatable { let weather: String - let maxTemp: Int - let minTemp: Int + let maxTemperature: Int + let minTemperature: Int let date: Date } @@ -49,27 +49,27 @@ final public class YumemiWeather { /// 引数の値でResponse構造体を作成する。引数がnilの場合はランダムに値を作成する。 /// - Parameters: /// - weather: 天気を表すenum - /// - maxTemp: 最高気温 - /// - minTemp: 最低気温 + /// - maxTemperature: 最高気温 + /// - minTemperature: 最低気温 /// - date: 日付 /// - seed: シード値 /// - Returns: Response構造体 - static func makeRandomResponse(weather: Weather? = nil, maxTemp: Int? = nil, minTemp: Int? = nil, date: Date? = nil, seed: Int? = nil) -> Response { - return makeRandomResponse(weather: weather, maxTemp: maxTemp, minTemp: minTemp, date: date, seed: seed ?? Int.random(in: Int.min...Int.max)) + static func makeRandomResponse(weather: Weather? = nil, maxTemperature: Int? = nil, minTemperature: Int? = nil, date: Date? = nil, seed: Int? = nil) -> Response { + return makeRandomResponse(weather: weather, maxTemperature: maxTemperature, minTemperature: minTemperature, date: date, seed: seed ?? Int.random(in: Int.min...Int.max)) } - private static func makeRandomResponse(weather: Weather?, maxTemp: Int?, minTemp: Int?, date: Date?, seed seedValue: Int) -> Response { + private static func makeRandomResponse(weather: Weather?, maxTemperature: Int?, minTemperature: Int?, date: Date?, seed seedValue: Int) -> Response { var seed = SeedRandomNumberGenerator(seed: seedValue) let weather = weather ?? Weather.allCases.randomElement(using: &seed)! - let maxTemp = maxTemp ?? Int.random(in: 10...40, using: &seed) - let minTemp = minTemp ?? Int.random(in: -40.. Date: Thu, 9 Jun 2022 18:04:21 +0900 Subject: [PATCH 2/5] Replace Weather with WeatherCondition --- Sources/YumemiWeather/YumemiWeather.swift | 28 +++++++++---------- Sources/YumemiWeather/YumemiWeatherList.swift | 2 +- .../YumemiWeatherListTests.swift | 1 - .../YumemiWeatherTests.swift | 8 +++--- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/Sources/YumemiWeather/YumemiWeather.swift b/Sources/YumemiWeather/YumemiWeather.swift index c2a3c75..66c10e9 100644 --- a/Sources/YumemiWeather/YumemiWeather.swift +++ b/Sources/YumemiWeather/YumemiWeather.swift @@ -6,13 +6,13 @@ struct Request: Decodable { } struct Response: Codable, Equatable { - let weather: String + let weatherCondition: String let maxTemperature: Int let minTemperature: Int let date: Date } -enum Weather: String, CaseIterable { +enum WeatherCondition: String, CaseIterable { case sunny case cloudy case rainy @@ -48,26 +48,26 @@ final public class YumemiWeather { /// 引数の値でResponse構造体を作成する。引数がnilの場合はランダムに値を作成する。 /// - Parameters: - /// - weather: 天気を表すenum + /// - weatherCondition: 天気状況を表すenum /// - maxTemperature: 最高気温 /// - minTemperature: 最低気温 /// - date: 日付 /// - seed: シード値 /// - Returns: Response構造体 - static func makeRandomResponse(weather: Weather? = nil, maxTemperature: Int? = nil, minTemperature: Int? = nil, date: Date? = nil, seed: Int? = nil) -> Response { - return makeRandomResponse(weather: weather, maxTemperature: maxTemperature, minTemperature: minTemperature, date: date, seed: seed ?? Int.random(in: Int.min...Int.max)) + static func makeRandomResponse(weatherCondition: WeatherCondition? = nil, maxTemperature: Int? = nil, minTemperature: Int? = nil, date: Date? = nil, seed: Int? = nil) -> Response { + return makeRandomResponse(weatherCondition: weatherCondition, maxTemperature: maxTemperature, minTemperature: minTemperature, date: date, seed: seed ?? Int.random(in: Int.min...Int.max)) } - private static func makeRandomResponse(weather: Weather?, maxTemperature: Int?, minTemperature: Int?, date: Date?, seed seedValue: Int) -> Response { + private static func makeRandomResponse(weatherCondition: WeatherCondition?, maxTemperature: Int?, minTemperature: Int?, date: Date?, seed seedValue: Int) -> Response { var seed = SeedRandomNumberGenerator(seed: seedValue) - let weather = weather ?? Weather.allCases.randomElement(using: &seed)! + let weatherCondition = weatherCondition ?? WeatherCondition.allCases.randomElement(using: &seed)! let maxTemperature = maxTemperature ?? Int.random(in: 10...40, using: &seed) let minTemperature = minTemperature ?? Int.random(in: -40.. String { - return self.makeRandomResponse().weather + /// - Returns: 天気状況を表す文字列 "sunny" or "cloudy" or "rainy" + public static func fetchWeatherCondition() -> String { + return self.makeRandomResponse().weatherCondition } /// 擬似 天気予報API Throws ver /// - Parameters: /// - area: 天気予報を取得する対象地域 example: "tokyo" /// - Throws: YumemiWeatherError - /// - Returns: 天気を表す文字列 "sunny" or "cloudy" or "rainy" - public static func fetchWeather(at area: String) throws -> String { + /// - Returns: 天気状況を表す文字列 "sunny" or "cloudy" or "rainy" + public static func fetchWeatherCondition(at area: String) throws -> String { if Int.random(in: 0...4) == 4 { throw YumemiWeatherError.unknownError } - return self.makeRandomResponse().weather + return self.makeRandomResponse().weatherCondition } /// 擬似 天気予報API Json ver diff --git a/Sources/YumemiWeather/YumemiWeatherList.swift b/Sources/YumemiWeather/YumemiWeatherList.swift index c4142c4..a5c284d 100644 --- a/Sources/YumemiWeather/YumemiWeatherList.swift +++ b/Sources/YumemiWeather/YumemiWeatherList.swift @@ -43,7 +43,7 @@ public extension YumemiWeather { /// } /// - Throws: YumemiWeatherError パラメータが正常でもランダムにエラーが発生する /// - Returns: Json文字列 - /// example: [{area: Tokyo, info: {"max_temp":25,"date":"2020-04-01T12:00:00+09:00","min_temp":7,"weather":"cloudy"}}] + /// example: [{area: Tokyo, info: {"max_temperature":25,"date":"2020-04-01T12:00:00+09:00","min_temperature":7,"weather_condition":"cloudy"}}] static func fetchWeatherList(_ jsonString: String) throws -> String { guard let requestData = jsonString.data(using: .utf8), let request = try? decoder.decode(AreaRequest.self, from: requestData) else { diff --git a/Tests/YumemiWeatherTests/YumemiWeatherListTests.swift b/Tests/YumemiWeatherTests/YumemiWeatherListTests.swift index e46a7f0..b567e4a 100644 --- a/Tests/YumemiWeatherTests/YumemiWeatherListTests.swift +++ b/Tests/YumemiWeatherTests/YumemiWeatherListTests.swift @@ -114,5 +114,4 @@ final class YumemiWeatherListTests: XCTestCase { XCTFail() } } - } diff --git a/Tests/YumemiWeatherTests/YumemiWeatherTests.swift b/Tests/YumemiWeatherTests/YumemiWeatherTests.swift index e0b6649..6b85fa6 100644 --- a/Tests/YumemiWeatherTests/YumemiWeatherTests.swift +++ b/Tests/YumemiWeatherTests/YumemiWeatherTests.swift @@ -4,14 +4,14 @@ import XCTest final class YumemiWeatherTests: XCTestCase { func test_fetchWeather() { - let str = YumemiWeather.fetchWeather() - XCTAssertNotNil(Weather(rawValue: str)) + let str = YumemiWeather.fetchWeatherCondition() + XCTAssertNotNil(WeatherCondition(rawValue: str)) } func test_fetchWeather_at() { do { - let str = try YumemiWeather.fetchWeather(at: "tokyo") - XCTAssertNotNil(Weather(rawValue: str)) + let str = try YumemiWeather.fetchWeatherCondition(at: "tokyo") + XCTAssertNotNil(WeatherCondition(rawValue: str)) } catch let error as YumemiWeatherError { XCTAssertEqual(error, YumemiWeatherError.unknownError) From 93df0ba26d0174a3264b03e512cbcca7ef6a4028 Mon Sep 17 00:00:00 2001 From: ribilynn Date: Thu, 9 Jun 2022 18:38:24 +0900 Subject: [PATCH 3/5] Update comments --- Sources/YumemiWeather/YumemiWeather.swift | 123 ++++++++++++----- Sources/YumemiWeather/YumemiWeatherList.swift | 124 +++++++++++++----- 2 files changed, 181 insertions(+), 66 deletions(-) diff --git a/Sources/YumemiWeather/YumemiWeather.swift b/Sources/YumemiWeather/YumemiWeather.swift index 66c10e9..5ffb9cc 100644 --- a/Sources/YumemiWeather/YumemiWeather.swift +++ b/Sources/YumemiWeather/YumemiWeather.swift @@ -74,16 +74,16 @@ final public class YumemiWeather { ) } - /// 擬似 天気予報API Simple ver + /// 擬似 天気予報 API Simple ver /// - Returns: 天気状況を表す文字列 "sunny" or "cloudy" or "rainy" public static func fetchWeatherCondition() -> String { return self.makeRandomResponse().weatherCondition } - /// 擬似 天気予報API Throws ver + /// 擬似 天気予報 API Throws ver + /// - Throws: YumemiWeatherError /// - Parameters: /// - area: 天気予報を取得する対象地域 example: "tokyo" - /// - Throws: YumemiWeatherError /// - Returns: 天気状況を表す文字列 "sunny" or "cloudy" or "rainy" public static func fetchWeatherCondition(at area: String) throws -> String { if Int.random(in: 0...4) == 4 { @@ -93,16 +93,27 @@ final public class YumemiWeather { return self.makeRandomResponse().weatherCondition } - /// 擬似 天気予報API Json ver - /// - Parameter jsonString: 地域と日付を含むJson文字列 - /// example: - /// { - /// "area": "tokyo", - /// "date": "2020-04-01T12:00:00+09:00" - /// } + /// 擬似 天気予報 API JSON ver + /// + /// API に請求する JSON 文字列の例: + /// + /// { + /// "area": "tokyo", + /// "date": "2020-04-01T12:00:00+09:00" + /// } + /// + /// 返された天気 JSON 文字列の例: + /// + /// { + /// "max_temperature":25, + /// "date":"2020-04-01T12:00:00+09:00", + /// "min_temperature":7, + /// "weather_condition":"cloudy" + /// } + /// /// - Throws: YumemiWeatherError パラメータが正常でもランダムにエラーが発生する - /// - Returns: Json文字列 - /// example: {"max_temp":25,"date":"2020-04-01T12:00:00+09:00","min_temp":7,"weather":"cloudy"} + /// - Parameter jsonString: 地域と日付を含む JSON 文字列 + /// - Returns: Weather レスポンスの JSON 文字列 public static func fetchWeather(_ jsonString: String) throws -> String { guard let requestData = jsonString.data(using: .utf8), let request = try? decoder.decode(Request.self, from: requestData) else { @@ -119,28 +130,58 @@ final public class YumemiWeather { return String(data: responseData, encoding: .utf8)! } - /// 擬似 天気予報API Sync ver - /// - Parameter jsonString: 地域と日付を含むJson文字列 - /// example: - /// { - /// "area": "tokyo", - /// "date": "2020-04-01T12:00:00+09:00" - /// } + /// 擬似 天気予報 API Sync ver + /// + /// API に請求する JSON 文字列の例: + /// + /// { + /// "area": "tokyo", + /// "date": "2020-04-01T12:00:00+09:00" + /// } + /// + /// 返された天気 JSON 文字列の例: + /// + /// { + /// "max_temperature":25, + /// "date":"2020-04-01T12:00:00+09:00", + /// "min_temperature":7, + /// "weather_condition":"cloudy" + /// } + /// /// - Throws: YumemiWeatherError パラメータが正常でもランダムにエラーが発生する - /// - Returns: Json文字列 + /// - Parameter jsonString: 地域と日付を含む JSON 文字列 + /// - Returns: Weather レスポンスの JSON 文字列 public static func syncFetchWeather(_ jsonString: String) throws -> String { Thread.sleep(forTimeInterval: apiDuration) return try self.fetchWeather(jsonString) } - /// 擬似 天気予報API Callback ver + + /// - Throws: YumemiWeatherError パラメータが正常でもランダムにエラーが発生する + /// - Parameter jsonString: 地域と日付を含む JSON 文字列 + /// - Returns: Weather レスポンスの JSON 文字列 + + /// 擬似 天気予報 API Callback ver + /// + /// API に請求する JSON 文字列の例: + /// + /// { + /// "area": "tokyo", + /// "date": "2020-04-01T12:00:00+09:00" + /// } + /// + /// 成功に返された天気 Result の中に JSON 文字列の例: + /// + /// { + /// "max_temperature":25, + /// "date":"2020-04-01T12:00:00+09:00", + /// "min_temperature":7, + /// "weather_condition":"cloudy" + /// } + /// + /// また、YumemiWeatherError パラメータが正常でもランダムにエラーが発生する /// - Parameters: - /// - jsonString: 地域と日付を含むJson文字列 - /// example: - /// { - /// "area": "tokyo", - /// "date": "2020-04-01T12:00:00+09:00" - /// } + /// - jsonString: 地域と日付を含む JSON 文字列 /// - completion: 完了コールバック public static func callbackFetchWeather(_ jsonString: String, completion: @escaping (Result) -> Void) { DispatchQueue.global().asyncAfter(deadline: .now() + apiDuration) { @@ -157,15 +198,27 @@ final public class YumemiWeather { } } - /// 擬似 天気予報API Async ver - /// - Parameter jsonString: 地域と日付を含むJson文字列 - /// example: - /// { - /// "area": "tokyo", - /// "date": "2020-04-01T12:00:00+09:00" - /// } + /// 擬似 天気予報 API Async ver + /// + /// API に請求する JSON 文字列の例: + /// + /// { + /// "area": "tokyo", + /// "date": "2020-04-01T12:00:00+09:00" + /// } + /// + /// 返された天気 JSON 文字列の例: + /// + /// { + /// "max_temperature":25, + /// "date":"2020-04-01T12:00:00+09:00", + /// "min_temperature":7, + /// "weather_condition":"cloudy" + /// } + /// /// - Throws: YumemiWeatherError パラメータが正常でもランダムにエラーが発生する - /// - Returns: Json文字列 + /// - Parameter jsonString: 地域と日付を含む JSON 文字列 + /// - Returns: Weather レスポンスの JSON 文字列 @available(iOS 13, macOS 10.15, *) public static func asyncFetchWeather(_ jsonString: String) async throws -> String { return try await withCheckedThrowingContinuation { continuation in diff --git a/Sources/YumemiWeather/YumemiWeatherList.swift b/Sources/YumemiWeather/YumemiWeatherList.swift index a5c284d..d7a8eca 100644 --- a/Sources/YumemiWeather/YumemiWeatherList.swift +++ b/Sources/YumemiWeather/YumemiWeatherList.swift @@ -34,16 +34,30 @@ public enum Area: String, CaseIterable, Codable { public extension YumemiWeather { - /// 擬似 天気予報一覧API Json ver - /// - Parameter jsonString: 地域と日付を含むJson文字列 - /// example: - /// { - /// "areas": ["Tokyo"], - /// "date": "2020-04-01T12:00:00+09:00" - /// } + /// 擬似 天気予報一覧 API JSON ver + /// + /// API に請求する JSON 文字列の例: + /// + /// { + /// "areas": ["tokyo"], + /// "date": "2020-04-01T12:00:00+09:00" + /// } + /// 返された AreaResponse の JSON 文字列の例 + /// + /// [ + /// { + /// "area": "Tokyo", + /// "info": { + /// "max_temperature": 25, + /// "date": "2020-04-01T12:00:00+09:00", + /// "min_temperature": 7, + /// "weather_condition": "cloudy" + /// } + /// } + /// ] /// - Throws: YumemiWeatherError パラメータが正常でもランダムにエラーが発生する - /// - Returns: Json文字列 - /// example: [{area: Tokyo, info: {"max_temperature":25,"date":"2020-04-01T12:00:00+09:00","min_temperature":7,"weather_condition":"cloudy"}}] + /// - Parameter jsonString: 地域と日付を含む JSON 文字列 + /// - Returns: 返された AreaResponse の JSON 文字列 static func fetchWeatherList(_ jsonString: String) throws -> String { guard let requestData = jsonString.data(using: .utf8), let request = try? decoder.decode(AreaRequest.self, from: requestData) else { @@ -66,28 +80,61 @@ public extension YumemiWeather { return String(data: responseData, encoding: .utf8)! } - /// 擬似 天気予報一覧API Sync ver - /// - Parameter jsonString: 地域と日付を含むJson文字列 - /// example: - /// { - /// "areas": ["Tokyo"], - /// "date": "2020-04-01T12:00:00+09:00" - /// } + /// 擬似 天気予報一覧 API Sync ver + /// + /// API に請求する JSON 文字列の例: + /// + /// { + /// "areas": ["tokyo"], + /// "date": "2020-04-01T12:00:00+09:00" + /// } + /// 返された AreaResponse の JSON 文字列の例 + /// + /// [ + /// { + /// "area": "Tokyo", + /// "info": { + /// "max_temperature": 25, + /// "date": "2020-04-01T12:00:00+09:00", + /// "min_temperature": 7, + /// "weather_condition": "cloudy" + /// } + /// } + /// ] /// - Throws: YumemiWeatherError パラメータが正常でもランダムにエラーが発生する - /// - Returns: Json文字列 + /// - Parameter jsonString: 地域と日付を含む JSON 文字列 + /// - Returns: 返された AreaResponse の JSON 文字列 static func syncFetchWeatherList(_ jsonString: String) throws -> String { Thread.sleep(forTimeInterval: apiDuration) return try self.fetchWeatherList(jsonString) } - /// 擬似 天気予報一覧API Callback ver + /// 擬似 天気予報一覧 API Callback ver + /// + /// API に請求する JSON 文字列の例: + /// + /// { + /// "areas": ["tokyo"], + /// "date": "2020-04-01T12:00:00+09:00" + /// } + /// + /// 成功に返された天気 Result の中に JSON 文字列の例: + /// + /// [ + /// { + /// "area": "Tokyo", + /// "info": { + /// "max_temperature": 25, + /// "date": "2020-04-01T12:00:00+09:00", + /// "min_temperature": 7, + /// "weather_condition": "cloudy" + /// } + /// } + /// ] + /// + /// また、YumemiWeatherError パラメータが正常でもランダムにエラーが発生する /// - Parameters: - /// - jsonString: 地域と日付を含むJson文字列 - /// example: - /// { - /// "areas": ["Tokyo"], - /// "date": "2020-04-01T12:00:00+09:00" - /// } + /// - jsonString: 地域と日付を含む JSON 文字列 /// - completion: 完了コールバック static func callbackFetchWeatherList(_ jsonString: String, completion: @escaping (Result) -> Void) { DispatchQueue.global().asyncAfter(deadline: .now() + apiDuration) { @@ -105,14 +152,29 @@ public extension YumemiWeather { } /// 擬似 天気予報一覧API Async ver - /// - Parameter jsonString: 地域と日付を含むJson文字列 - /// example: - /// { - /// "areas": ["Tokyo"], - /// "date": "2020-04-01T12:00:00+09:00" - /// } + /// + /// API に請求する JSON 文字列の例: + /// + /// { + /// "areas": ["tokyo"], + /// "date": "2020-04-01T12:00:00+09:00" + /// } + /// 返された AreaResponse の JSON 文字列の例 + /// + /// [ + /// { + /// "area": "Tokyo", + /// "info": { + /// "max_temperature": 25, + /// "date": "2020-04-01T12:00:00+09:00", + /// "min_temperature": 7, + /// "weather_condition": "cloudy" + /// } + /// } + /// ] /// - Throws: YumemiWeatherError パラメータが正常でもランダムにエラーが発生する - /// - Returns: Json文字列 + /// - Parameter jsonString: 地域と日付を含む JSON 文字列 + /// - Returns: 返された AreaResponse の JSON 文字列 @available(iOS 13, macOS 10.15, *) static func asyncFetchWeatherList(_ jsonString: String) async throws -> String { return try await withCheckedThrowingContinuation { continuation in From c3d65ec5c5e8e26ed1e38e7ff1f34e84271e8a59 Mon Sep 17 00:00:00 2001 From: ribilynn Date: Thu, 9 Jun 2022 18:40:00 +0900 Subject: [PATCH 4/5] Minor improvement --- Sources/YumemiWeather/YumemiDisaster.swift | 2 +- Sources/YumemiWeather/YumemiWeather.swift | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Sources/YumemiWeather/YumemiDisaster.swift b/Sources/YumemiWeather/YumemiDisaster.swift index a9d8248..7af4390 100644 --- a/Sources/YumemiWeather/YumemiDisaster.swift +++ b/Sources/YumemiWeather/YumemiDisaster.swift @@ -7,7 +7,7 @@ import Foundation -public protocol YumemiDisasterHandleDelegate: class { +public protocol YumemiDisasterHandleDelegate: AnyObject { func handle(disaster: String) } diff --git a/Sources/YumemiWeather/YumemiWeather.swift b/Sources/YumemiWeather/YumemiWeather.swift index 5ffb9cc..e14c735 100644 --- a/Sources/YumemiWeather/YumemiWeather.swift +++ b/Sources/YumemiWeather/YumemiWeather.swift @@ -60,10 +60,10 @@ final public class YumemiWeather { } private static func makeRandomResponse(weatherCondition: WeatherCondition?, maxTemperature: Int?, minTemperature: Int?, date: Date?, seed seedValue: Int) -> Response { - var seed = SeedRandomNumberGenerator(seed: seedValue) - let weatherCondition = weatherCondition ?? WeatherCondition.allCases.randomElement(using: &seed)! - let maxTemperature = maxTemperature ?? Int.random(in: 10...40, using: &seed) - let minTemperature = minTemperature ?? Int.random(in: -40.. Date: Fri, 10 Jun 2022 10:51:35 +0900 Subject: [PATCH 5/5] Update documentation --- Documentation/API.md | 2 +- Documentation/Error.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/API.md b/Documentation/API.md index 5a415c3..94a1c9b 100644 --- a/Documentation/API.md +++ b/Documentation/API.md @@ -2,7 +2,7 @@ `YumemiWeather`のAPIを使用して、天気予報を取得しましょう。 Simple ver -`public static func fetchWeather() -> String` +`public static func fetchWeatherCondition() -> String` [APIの概要](YumemiWeather.md) ## 課題 diff --git a/Documentation/Error.md b/Documentation/Error.md index cc41cc6..b7db388 100644 --- a/Documentation/Error.md +++ b/Documentation/Error.md @@ -2,7 +2,7 @@ `YumemiWeather`のAPIがエラーをthrowしたときの実装をしましょう。 Throws ver -`static func fetchWeather(at area: String) throws -> String` +`static func fetchWeatherCondition(at area: String) throws -> String` [APIの概要](YumemiWeather.md) エラーが発生したときにどのように実装するか...