300 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			Swift
		
	
	
			
		
		
	
	
			300 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			Swift
		
	
	
| // StrategyConfig.swift
 | |
| // Defines configuration structures for ad strategies
 | |
| // Corresponds to StrategyConfig.kt in Android implementation
 | |
| 
 | |
| import Foundation
 | |
| 
 | |
| // MARK: - Strategy Types
 | |
| 
 | |
| public enum InterstitialStrategy: Int {
 | |
|     case `default` = 0
 | |
|     case mab = 1
 | |
| }
 | |
| 
 | |
| public enum RewardedStrategy: Int {
 | |
|     case `default` = 0
 | |
|     case mab = 1
 | |
| }
 | |
| 
 | |
| public enum BannerStrategy: Int {
 | |
|     case `default` = 0
 | |
| }
 | |
| 
 | |
| protocol StrategyConfig: Decodable {}
 | |
| 
 | |
| // MARK: - Default Config Classes
 | |
| 
 | |
| public struct DefaultInterstitialConfig: Codable, StrategyConfig {
 | |
|     public let adPlatform: String
 | |
|     public let adUnitId: String
 | |
|     public let adAmazonSlotId: String?
 | |
|     
 | |
|     public init(adPlatform: String, adUnitId: String, adAmazonSlotId: String? = nil) {
 | |
|         self.adPlatform = adPlatform
 | |
|         self.adUnitId = adUnitId
 | |
|         self.adAmazonSlotId = adAmazonSlotId
 | |
|     }
 | |
|     
 | |
|     private enum CodingKeys : String, CodingKey {
 | |
|         case adPlatform = "ad_platform",
 | |
|              adUnitId = "ad_unit_id",
 | |
|              adAmazonSlotId = "ad_amz_slot_id"
 | |
|     }
 | |
| }
 | |
| 
 | |
| public struct DefaultRewardedConfig: Codable, StrategyConfig {
 | |
|     public let adPlatform: String
 | |
|     public let adUnitId: String
 | |
|     public let adAmazonSlotId: String?
 | |
|     
 | |
|     public init(adPlatform: String, adUnitId: String, adAmazonSlotId: String? = nil) {
 | |
|         self.adPlatform = adPlatform
 | |
|         self.adUnitId = adUnitId
 | |
|         self.adAmazonSlotId = adAmazonSlotId
 | |
|     }
 | |
|     
 | |
|     private enum CodingKeys : String, CodingKey {
 | |
|         case adPlatform = "ad_platform",
 | |
|              adUnitId = "ad_unit_id",
 | |
|              adAmazonSlotId = "ad_amz_slot_id"
 | |
|     }
 | |
| }
 | |
| 
 | |
| public struct DefaultBannerConfig: Codable, StrategyConfig {
 | |
|     public let adPlatform: String
 | |
|     public let adUnitId: String
 | |
|     public let adAmazonSlotId: String?
 | |
|     
 | |
|     public init(adPlatform: String, adUnitId: String, adAmazonSlotId: String? = nil) {
 | |
|         self.adPlatform = adPlatform
 | |
|         self.adUnitId = adUnitId
 | |
|         self.adAmazonSlotId = adAmazonSlotId
 | |
|     }
 | |
|     
 | |
|     private enum CodingKeys : String, CodingKey {
 | |
|         case adPlatform = "ad_platform",
 | |
|              adUnitId = "ad_unit_id",
 | |
|              adAmazonSlotId = "ad_amz_slot_id"
 | |
|     }
 | |
| }
 | |
| 
 | |
| public struct DefaultMRecConfig: Codable, StrategyConfig {
 | |
|     public let adPlatform: String
 | |
|     public let adUnitId: String
 | |
|     public let adAmazonSlotId: String?
 | |
|     
 | |
|     public init(adPlatform: String, adUnitId: String, adAmazonSlotId: String? = nil) {
 | |
|         self.adPlatform = adPlatform
 | |
|         self.adUnitId = adUnitId
 | |
|         self.adAmazonSlotId = adAmazonSlotId
 | |
|     }
 | |
|     
 | |
|     private enum CodingKeys : String, CodingKey {
 | |
|         case adPlatform = "ad_platform",
 | |
|              adUnitId = "ad_unit_id",
 | |
|              adAmazonSlotId = "ad_amz_slot_id"
 | |
|     }
 | |
| }
 | |
| 
 | |
| public struct MabRewardedConfig: Codable, StrategyConfig {
 | |
|     public let aggregatorConfigs: [AggregatorConfig]
 | |
|     
 | |
|     public let showTimeoutInSecond: Double?
 | |
|     
 | |
|     init(aggregatorConfigs: [AggregatorConfig], showTimeoutInSecond: Double?) {
 | |
|         self.aggregatorConfigs = aggregatorConfigs
 | |
|         self.showTimeoutInSecond = showTimeoutInSecond
 | |
|     }
 | |
|     
 | |
|     private enum CodingKeys : String, CodingKey {
 | |
|         case aggregatorConfigs = "aggregator_configs",
 | |
|              showTimeoutInSecond = "show_timeout_second"
 | |
|     }
 | |
| }
 | |
| 
 | |
| public struct MabInterstitialConfig: Codable, StrategyConfig {
 | |
|     public let aggregatorConfigs: [AggregatorConfig]
 | |
|     
 | |
|     public let showTimeoutInSecond: Double?
 | |
|     
 | |
|     init(aggregatorConfigs: [AggregatorConfig], showTimeoutInSecond: Double?) {
 | |
|         self.aggregatorConfigs = aggregatorConfigs
 | |
|         self.showTimeoutInSecond = showTimeoutInSecond
 | |
|     }
 | |
|     
 | |
|     private enum CodingKeys : String, CodingKey {
 | |
|         case aggregatorConfigs = "aggregator_configs",
 | |
|              showTimeoutInSecond = "show_timeout_second"
 | |
|     }
 | |
| }
 | |
| 
 | |
| public struct AggregatorConfig: Codable {
 | |
|     public let aggregatorId: String
 | |
|     public let adPlatform: String
 | |
|     public let raiseRate: Double
 | |
|     public let selfRaiseRate: Double?
 | |
|     public let cacheExpireInSecond: Double
 | |
|     public let priority: Int
 | |
|     public let adUnitIds: [AdUnitSpec]
 | |
|     public let loadTimeoutInSecond: Double?
 | |
|     
 | |
|     init(aggregatorId: String, adPlatform: String, raiseRate: Double, selfRaiseRate: Double?, cacheExpireInSecond: Double, priority: Int, adUnitIds: [AdUnitSpec], loadTimeoutInSecond: Double?) {
 | |
|         self.aggregatorId = aggregatorId
 | |
|         self.adPlatform = adPlatform
 | |
|         self.raiseRate = raiseRate
 | |
|         self.selfRaiseRate = selfRaiseRate
 | |
|         self.cacheExpireInSecond = cacheExpireInSecond
 | |
|         self.priority = priority
 | |
|         self.adUnitIds = adUnitIds
 | |
|         self.loadTimeoutInSecond = loadTimeoutInSecond
 | |
|     }
 | |
|     
 | |
|     private enum CodingKeys : String, CodingKey {
 | |
|         case aggregatorId = "aggregator_id",
 | |
|              adPlatform = "ad_platform",
 | |
|              raiseRate = "raise_rate",
 | |
|              selfRaiseRate = "self_raise_rate",
 | |
|              cacheExpireInSecond = "cache_expire_second",
 | |
|              priority = "priority",
 | |
|              adUnitIds = "ad_unit_ids",
 | |
|              loadTimeoutInSecond = "load_timeout_second"
 | |
|     }
 | |
| }
 | |
| 
 | |
| public struct AdUnitSpec: Codable {
 | |
|     public let adUnitId: String
 | |
|     public let adAmazonSlotId: String?
 | |
|     
 | |
|     public let floorEcpm: Double
 | |
|     
 | |
|     public var floor: Double {
 | |
|         return floorEcpm / 1000
 | |
|     }
 | |
|     
 | |
|     init(adUnitId: String, adAmazonSlotId: String?, floorEcpm: Double = 0.0) {
 | |
|         self.adUnitId = adUnitId
 | |
|         self.adAmazonSlotId = adAmazonSlotId
 | |
|         self.floorEcpm = floorEcpm
 | |
|     }
 | |
|     
 | |
|     private enum CodingKeys : String, CodingKey {
 | |
|         case adUnitId = "ad_unit_id",
 | |
|              adAmazonSlotId = "ad_amz_slot_id",
 | |
|              floorEcpm = "floor_ecpm"
 | |
|     }
 | |
| }
 | |
| 
 | |
| // MARK: - AdEngineConfig
 | |
| 
 | |
| 
 | |
| public struct AdEngineConfig: Codable {
 | |
|     public let strategy: Int
 | |
|     public let faUnitId: String
 | |
|     public let config: [String: Any]
 | |
|     
 | |
|     public init(strategy: Int, faUnitId: String, config: [String: Any]) {
 | |
|         self.strategy = strategy
 | |
|         self.faUnitId = faUnitId
 | |
|         self.config = config
 | |
|     }
 | |
|     
 | |
|     public func encode(to encoder: Encoder) throws {
 | |
|         var container = encoder.container(keyedBy: CodingKeys.self)
 | |
|         try container.encode(strategy, forKey: .strategy)
 | |
|         try container.encode(faUnitId, forKey: .faUnitId)
 | |
|         try container.encode(JSONCodable(config), forKey: .config)
 | |
|     }
 | |
|     
 | |
|     public init(from decoder: Decoder) throws {
 | |
|         let container = try decoder.container(keyedBy: CodingKeys.self)
 | |
|         strategy = try container.decode(Int.self, forKey: .strategy)
 | |
|         faUnitId = try container.decode(String?.self, forKey: .faUnitId) ?? "default"
 | |
|         config = try container.decode(JSONCodable.self, forKey: .config).value as! Dictionary
 | |
|     }
 | |
|     
 | |
|     private enum CodingKeys: String, CodingKey {
 | |
|         case strategy = "strategy",
 | |
|              config = "config",
 | |
|             faUnitId = "fa_unit_id"
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| private struct JSONCodable: Codable {
 | |
|     let value: Any
 | |
|     
 | |
|     init(_ value: Any) {
 | |
|         self.value = value
 | |
|     }
 | |
|     
 | |
|     init(from decoder: Decoder) throws {
 | |
|         let container = try decoder.singleValueContainer()
 | |
|         
 | |
|         if container.decodeNil() {
 | |
|             self.value = NSNull()
 | |
|         } else if let bool = try? container.decode(Bool.self) {
 | |
|             self.value = bool
 | |
|         } else if let int = try? container.decode(Int.self) {
 | |
|             self.value = int
 | |
|         } else if let uint = try? container.decode(UInt.self) {
 | |
|             self.value = uint
 | |
|         } else if let double = try? container.decode(Double.self) {
 | |
|             self.value = double
 | |
|         } else if let string = try? container.decode(String.self) {
 | |
|             self.value = string
 | |
|         } else if let array = try? container.decode([JSONCodable].self) {
 | |
|             self.value = array.map { $0.value }
 | |
|         } else if let dictionary = try? container.decode([String: JSONCodable].self) {
 | |
|             self.value = dictionary.mapValues { $0.value }
 | |
|         } else {
 | |
|             throw DecodingError.dataCorruptedError(
 | |
|                 in: container,
 | |
|                 debugDescription: "AnyCodable cannot decode value"
 | |
|             )
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     func encode(to encoder: Encoder) throws {
 | |
|         var container = encoder.singleValueContainer()
 | |
|         
 | |
|         switch self.value {
 | |
|         case is NSNull:
 | |
|             try container.encodeNil()
 | |
|         case let bool as Bool:
 | |
|             try container.encode(bool)
 | |
|         case let int as Int:
 | |
|             try container.encode(int)
 | |
|         case let uint as UInt:
 | |
|             try container.encode(uint)
 | |
|         case let double as Double:
 | |
|             try container.encode(double)
 | |
|         case let string as String:
 | |
|             try container.encode(string)
 | |
|         case let array as [Any]:
 | |
|             try container.encode(array.map { JSONCodable($0) })
 | |
|         case let dictionary as [String: Any]:
 | |
|             try container.encode(dictionary.mapValues { JSONCodable($0) })
 | |
|         default:
 | |
|             let context = EncodingError.Context(
 | |
|                 codingPath: container.codingPath,
 | |
|                 debugDescription: "AnyCodable cannot encode value \(self.value)"
 | |
|             )
 | |
|             throw EncodingError.invalidValue(self.value, context)
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| extension StrategyConfig
 | |
| {
 | |
|     init<Key: Hashable>(_ dict: [Key: Any]) throws
 | |
|     {
 | |
|         do {
 | |
|             let data = try JSONSerialization.data(withJSONObject: dict, options: [])
 | |
|             self = try JSONDecoder().decode(Self.self, from: data)
 | |
|         } catch {
 | |
|             Logger.e(tag: "StrategyConfig", message: "strategy config deserialize to \(Self.self) fail, data is \(dict)")
 | |
|             throw error;
 | |
|         }
 | |
|     }
 | |
| }
 |