source/UberRides/Model/Product.swift (186 lines of code) (raw):
//
// Product.swift
// UberRides
//
// Copyright © 2015 Uber Technologies, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import UberCore
// MARK: Products
/**
* Internal object that contains a list of Uber products.
*/
struct UberProducts: Codable {
var list: [Product]?
enum CodingKeys: String, CodingKey {
case list = "products"
}
}
// MARK: Product
/**
* Contains information for a single Uber product.
*/
@objc(UBSDKProduct) public class Product: NSObject, Codable {
/// Unique identifier representing a specific product for a given latitude & longitude.
@objc public private(set) var productID: String?
/// Display name of product. Ex: "UberBLACK".
@objc public private(set) var name: String?
/// Description of product. Ex: "The original Uber".
@objc public private(set) var productDescription: String?
/// Capacity of product. Ex: 4, for a product that fits 4.
@nonobjc public private(set) var capacity: Int?
/// Capacity of product. Ex: 4, for a product that fits 4.
@objc public var objc_capacity: NSNumber? {
if let capacity = capacity {
return NSNumber(value: capacity)
} else {
return nil
}
}
/// Image URL representing the product.
@objc public private(set) var imageURL: URL?
/// The basic price details. See `PriceDetails` for structure.
@objc public private(set) var priceDetails: PriceDetails?
/// Specifies whether this product allows users to get upfront fares, instead of time + distance.
@nonobjc public private(set) var upfrontFareEnabled: Bool?
/// Specifies whether this product allows users to get upfront fares, instead of time + distance. Boolean value.
@objc public var objc_upfrontFareEnabled: NSNumber? {
if let upfrontFareEnabled = upfrontFareEnabled {
return NSNumber(value: upfrontFareEnabled)
} else {
return nil
}
}
/// Specifies whether this product allows cash payments
@nonobjc public private(set) var cashEnabled: Bool?
/// Specifies whether this product allows cash payments. Boolean value.
@objc public var objc_cashEnabled: NSNumber? {
if let cashEnabled = cashEnabled {
return NSNumber(value: cashEnabled)
} else {
return nil
}
}
/// Specifies whether this product allows for the pickup and drop off of other riders during the trip
@nonobjc public private(set) var isShared: Bool?
/// Specifies whether this product allows for the pickup and drop off of other riders during the trip. Boolean value.
@objc public var objc_isShared: NSNumber? {
if let isShared = isShared {
return NSNumber(value: isShared)
} else {
return nil
}
}
/// The product group that this product belongs to
@objc public private(set) var productGroup: ProductGroup
enum CodingKeys: String, CodingKey {
case productID = "product_id"
case name = "display_name"
case productDescription = "description"
case capacity = "capacity"
case imageURL = "image"
case priceDetails = "price_details"
case upfrontFareEnabled = "upfront_fare_enabled"
case cashEnabled = "cash_enabled"
case isShared = "shared"
case productGroup = "product_group"
}
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
productID = try container.decodeIfPresent(String.self, forKey: .productID)
name = try container.decodeIfPresent(String.self, forKey: .name)
productDescription = try container.decodeIfPresent(String.self, forKey: .productDescription)
capacity = try container.decodeIfPresent(Int.self, forKey: .capacity)
imageURL = try container.decodeIfPresent(URL.self, forKey: .imageURL)
priceDetails = try container.decodeIfPresent(PriceDetails.self, forKey: .priceDetails)
upfrontFareEnabled = try container.decodeIfPresent(Bool.self, forKey: .upfrontFareEnabled)
cashEnabled = try container.decodeIfPresent(Bool.self, forKey: .cashEnabled)
isShared = try container.decodeIfPresent(Bool.self, forKey: .isShared)
productGroup = try container.decodeIfPresent(ProductGroup.self, forKey: .productGroup) ?? .unknown
}
}
// MARK: PriceDetails
/**
* Contains basic price details for an Uber product.
*/
@objc(UBSDKPriceDetails) public class PriceDetails: NSObject, Codable {
/// Unit of distance used to calculate fare (mile or km).
@objc public private(set) var distanceUnit: String?
/// ISO 4217 currency code.
@objc public private(set) var currencyCode: String?
/// The charge per minute (if applicable).
@nonobjc public private(set) var costPerMinute: Double?
/// The charge per minute (if applicable).
@objc(costPerMinute) public var objc_costPerMinute: NSNumber? {
if let costPerMinute = costPerMinute {
return NSNumber(value: costPerMinute)
} else {
return nil
}
}
/// The charge per distance unit (if applicable).
@nonobjc public private(set) var costPerDistance: Double?
/// The charge per distance unit (if applicable).
@objc(costPerDistance) public var objc_costPerDistance: NSNumber? {
if let costPerDistance = costPerDistance {
return NSNumber(value: costPerDistance)
} else {
return nil
}
}
/// The base price.
@nonobjc public private(set) var baseFee: Double?
/// The base price.
@objc(baseFee) public var objc_baseFee: NSNumber? {
if let baseFee = baseFee {
return NSNumber(value: baseFee)
} else {
return nil
}
}
/// The minimum price of a trip.
@nonobjc public private(set) var minimumFee: Double?
/// The minimum price of a trip.
@objc(minimumFee) public var objc_minimumFee: NSNumber? {
if let minimumFee = minimumFee {
return NSNumber(value: minimumFee)
} else {
return nil
}
}
/// The fee if a rider cancels the trip after a grace period.
@nonobjc public private(set) var cancellationFee: Double?
/// The fee if a rider cancels the trip after a grace period.
@objc(cancellationFee) public var objc_cancellationFee: NSNumber? {
if let cancellationFee = cancellationFee {
return NSNumber(value: cancellationFee)
} else {
return nil
}
}
/// Array containing additional fees added to the price. See `ServiceFee`.
@objc public private(set) var serviceFees: [ServiceFee]?
enum CodingKeys: String, CodingKey {
case distanceUnit = "distance_unit"
case currencyCode = "currency_code"
case costPerMinute = "cost_per_minute"
case costPerDistance = "cost_per_distance"
case baseFee = "base"
case minimumFee = "minimum"
case cancellationFee = "cancellation_fee"
case serviceFees = "service_fees"
}
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
distanceUnit = try container.decodeIfPresent(String.self, forKey: .distanceUnit)
currencyCode = try container.decodeIfPresent(String.self, forKey: .currencyCode)
costPerMinute = try container.decodeIfPresent(Double.self, forKey: .costPerMinute)
costPerDistance = try container.decodeIfPresent(Double.self, forKey: .costPerDistance)
baseFee = try container.decodeIfPresent(Double.self, forKey: .baseFee)
minimumFee = try container.decodeIfPresent(Double.self, forKey: .minimumFee)
cancellationFee = try container.decodeIfPresent(Double.self, forKey: .cancellationFee)
serviceFees = try container.decodeIfPresent([ServiceFee].self, forKey: .serviceFees)
}
}
// MARK: ServiceFee
/**
* Contains information for additional fees that can be added to the price of an Uber product.
*/
@objc(UBSDKServiceFee) public class ServiceFee: NSObject, Codable {
/// The name of the service fee.
@objc public private(set) var name: String?
/// The amount of the service fee.
@nonobjc public private(set) var fee: Double?
/// The amount of the service fee.
@objc(fee) public var objc_fee: NSNumber? {
if let fee = fee {
return NSNumber(value: fee)
} else {
return nil
}
}
enum CodingKeys: String, CodingKey {
case name = "name"
case fee = "fee"
}
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
name = try container.decodeIfPresent(String.self, forKey: .name)
fee = try container.decodeIfPresent(Double.self, forKey: .fee)
}
}
/// Uber Product Category
@objc(UBSDKProductGroup) public enum ProductGroup: Int, Codable {
/// Shared rides products (eg, UberPOOL)
case rideshare
/// UberX
case uberX
/// UberXL
case uberXL
/// UberBLACK
case uberBlack
/// UberSUV
case suv
/// 3rd party taxis
case taxi
/// Unknown product group
case unknown
public init(from decoder: Decoder) throws {
let string = try decoder.singleValueContainer().decode(String.self).lowercased()
switch string {
case "rideshare":
self = .rideshare
case "uberx":
self = .uberX
case "uberxl":
self = .uberXL
case "uberblack":
self = .uberBlack
case "suv":
self = .suv
case "taxi":
self = .taxi
default:
self = .unknown
}
}
}