GuruAnalytics_iOS/GuruAnalytics/Classes/Internal/DataModel/Models.swift

229 lines
8.4 KiB
Swift
Raw Normal View History

//
// DBEntities.swift
// Alamofire
//
// Created by mayue on 2022/11/4.
//
import Foundation
import CryptoSwift
internal enum Entity {
}
extension Entity {
struct EventRecord: Codable {
enum Priority: Int, Codable {
case EMERGENCE = 0
case HIGH = 5
case DEFAULT = 10
case LOW = 15
}
enum TransitionStatus: Int, Codable {
case idle = 0
case instransition = 1
}
let recordId: String
let eventName: String
let eventJson: String
///
let timestamp: Int64
let priority: Priority
let transitionStatus: TransitionStatus
init(eventName: String, event: Entity.Event, priority: Priority = .DEFAULT, transitionStatus: TransitionStatus = .idle) {
let now = Date()
let eventJson = event.asString ?? ""
if eventJson.isEmpty {
cdPrint("[WARNING] error for convert event to json")
}
self.recordId = "\(eventName)\(eventJson)\(now.timeIntervalSince1970)\(Int.random(in: Int.min...Int.max))".md5()
self.eventName = eventName
self.eventJson = eventJson
self.timestamp = event.timestamp
self.priority = priority
self.transitionStatus = transitionStatus
}
init(recordId: String, eventName: String, eventJson: String, timestamp: Int64, priority: Int, transitionStatus: Int) {
self.recordId = recordId
self.eventName = eventName
self.eventJson = eventJson
self.timestamp = timestamp
self.priority = .init(rawValue: priority) ?? .DEFAULT
self.transitionStatus = .init(rawValue: transitionStatus) ?? .idle
}
enum CodingKeys: String, CodingKey {
case recordId
case eventName
case eventJson
case timestamp
case priority
case transitionStatus
}
static func createTableSql(with name: String) -> String {
return """
CREATE TABLE IF NOT EXISTS \(name)(
\(CodingKeys.recordId.rawValue) TEXT UNIQUE NOT NULL PRIMARY KEY,
\(CodingKeys.eventName.rawValue) TEXT NOT NULL,
\(CodingKeys.eventJson.rawValue) TEXT NOT NULL,
\(CodingKeys.timestamp.rawValue) INTEGER,
\(CodingKeys.priority.rawValue) INTEGER,
\(CodingKeys.transitionStatus.rawValue) INTEGER);
"""
}
func insertSql(to tableName: String) -> String {
return "INSERT INTO \(tableName) VALUES ('\(recordId)', '\(eventName)', '\(eventJson)', '\(timestamp)', '\(priority.rawValue)', '\(transitionStatus.rawValue)')"
}
}
}
extension Entity {
struct Event: Codable {
///
let timestamp: Int64
let event: String
let userInfo: UserInfo
let param: [String: EventValue]
let properties: [String: String]
let eventId: String
enum CodingKeys: String, CodingKey {
case timestamp
case userInfo = "info"
case event, param, properties
case eventId
}
init(timestamp: Int64, event: String, userInfo: UserInfo, parameters: [String : Any], properties: [String : String]) throws {
guard let normalizedEvent = Self.normalizeKey(event),
normalizedEvent == event else {
cdPrint("drop event because of illegal event name: \(event)")
cdPrint("standard: https://developers.google.com/android/reference/com/google/firebase/analytics/FirebaseAnalytics.Event")
throw NSError(domain: "cunstrcting event error", code: 0, userInfo: [NSLocalizedDescriptionKey : "illegal event name: \(event)"])
}
self.eventId = UUID().uuidString.lowercased()
self.timestamp = timestamp
self.event = normalizedEvent
self.userInfo = userInfo
self.param = Self.normalizeParameters(parameters)
self.properties = properties
}
static let maxParametersCount = 25
static let maxKeyLength = 40
static let maxParameterStringValueLength = 128
static func normalizeParameters(_ parameters: [String : Any]) -> [String : EventValue] {
var params = [String : EventValue]()
var count = 0
parameters.sorted(by: { $0.key < $1.key }).forEach({ key, value in
guard count < maxParametersCount else {
cdPrint("too many parameters")
cdPrint("standard: https://developers.google.com/android/reference/com/google/firebase/analytics/FirebaseAnalytics.Event")
return
}
guard let normalizedKey = normalizeKey(key),
normalizedKey == key else {
cdPrint("drop event parameter because of illegal key: \(key)")
cdPrint("standard: https://developers.google.com/android/reference/com/google/firebase/analytics/FirebaseAnalytics.Event")
return
}
if let value = value as? String {
params[normalizedKey] = Entity.EventValue(stringValue: String(value.prefix(maxParameterStringValueLength)))
} else if let value = value as? Int {
params[normalizedKey] = Entity.EventValue(longValue: Int64(value))
} else if let value = value as? Int64 {
params[normalizedKey] = Entity.EventValue(longValue: value)
} else if let value = value as? Double {
params[normalizedKey] = Entity.EventValue(doubleValue: value)
} else {
params[normalizedKey] = Entity.EventValue(stringValue: String("\(value)".prefix(maxParameterStringValueLength)))
}
count += 1
})
return params
}
static func normalizeKey(_ key: String) -> String? {
var mutableKey = key
while let first = mutableKey.first,
!first.isLetter {
_ = mutableKey.removeFirst()
}
var normalizedKey = ""
var count = 0
mutableKey.forEach { c in
guard count < maxKeyLength,
c.isAlphabetic || c.isDigit || c == "_" else { return }
normalizedKey.append(c)
count += 1
}
return normalizedKey.isEmpty ? nil : normalizedKey
}
}
///
struct UserInfo: Codable {
///IDuid
let uid: String?
///IDIDiOSIDFVUUIDAndroidandroidID
let deviceId: String?
///adjust_idadjust
let adjustId: String?
///广 ID/广 (IDFA)
let adId: String?
///pseudo_id
let firebaseId: String?
enum CodingKeys: String, CodingKey {
case deviceId
case uid
case adjustId
case adId
case firebaseId
}
}
//
struct EventValue: Codable {
let stringValue: String? //
let longValue: Int64? //
let doubleValue: Double? // APPJSON
init(stringValue: String? = nil, longValue: Int64? = nil, doubleValue: Double? = nil) {
self.stringValue = stringValue
self.longValue = longValue
self.doubleValue = doubleValue
}
enum CodingKeys: String, CodingKey {
case stringValue = "s"
case longValue = "i"
case doubleValue = "d"
}
}
}
extension Entity {
struct SystemTimeResult: Codable {
let data: Int64
}
}