2022-05-01 18:30:30 +02:00
|
|
|
import Foundation
|
|
|
|
|
|
|
|
|
2023-04-11 18:18:31 +02:00
|
|
|
struct HistoryItem {
|
|
|
|
|
|
|
|
/// The sent/received date (local time, not including compensation offset)
|
|
|
|
let requestDate: Date
|
|
|
|
|
|
|
|
let request: Message.Content
|
|
|
|
|
|
|
|
let usedLocalConnection: Bool
|
|
|
|
|
2023-08-14 10:39:29 +02:00
|
|
|
var response: ClientState
|
2023-04-11 18:18:31 +02:00
|
|
|
|
|
|
|
let responseMessage: Message.Content?
|
|
|
|
|
2023-08-14 10:39:29 +02:00
|
|
|
let responseDate: Date
|
2023-04-11 18:18:31 +02:00
|
|
|
|
2023-08-14 10:39:29 +02:00
|
|
|
init(sent message: Message.Content, sentDate: Date, local: Bool, response: ClientState, responseDate: Date, responseMessage: Message.Content?) {
|
|
|
|
self.requestDate = sentDate
|
2023-04-11 18:18:31 +02:00
|
|
|
self.request = message
|
2023-08-14 10:39:29 +02:00
|
|
|
self.responseMessage = responseMessage
|
2022-05-01 18:30:30 +02:00
|
|
|
self.response = response
|
2023-08-14 10:39:29 +02:00
|
|
|
self.responseDate = responseDate
|
|
|
|
self.usedLocalConnection = local
|
2022-05-01 18:30:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: Statistics
|
|
|
|
|
2023-08-14 10:39:29 +02:00
|
|
|
var roundTripTime: TimeInterval {
|
|
|
|
responseDate.timeIntervalSince(requestDate)
|
2022-05-01 18:30:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
var deviceTime: Date? {
|
2023-04-11 18:18:31 +02:00
|
|
|
guard let timestamp = responseMessage?.time else {
|
2022-05-01 18:30:30 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return Date(timestamp: timestamp)
|
|
|
|
}
|
|
|
|
|
|
|
|
var requestLatency: TimeInterval? {
|
2023-04-11 18:18:31 +02:00
|
|
|
deviceTime?.timeIntervalSince(requestDate)
|
2022-05-01 18:30:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
var responseLatency: TimeInterval? {
|
|
|
|
guard let deviceTime = deviceTime else {
|
|
|
|
return nil
|
|
|
|
}
|
2023-08-14 10:39:29 +02:00
|
|
|
return responseDate.timeIntervalSince(deviceTime)
|
2022-05-01 18:30:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
var clockOffset: Int? {
|
2023-08-14 10:39:29 +02:00
|
|
|
guard let deviceTime = deviceTime else {
|
2022-05-01 18:30:30 +02:00
|
|
|
return nil
|
|
|
|
}
|
2023-08-14 10:39:29 +02:00
|
|
|
let estimatedArrival = requestDate.advanced(by: roundTripTime / 2)
|
2022-05-01 18:30:30 +02:00
|
|
|
return Int(deviceTime.timeIntervalSince(estimatedArrival))
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-04-11 18:18:31 +02:00
|
|
|
extension HistoryItem: Codable {
|
|
|
|
|
|
|
|
enum CodingKeys: Int, CodingKey {
|
|
|
|
case requestDate = 1
|
|
|
|
case request = 2
|
|
|
|
case usedLocalConnection = 3
|
|
|
|
case response = 4
|
|
|
|
case responseMessage = 5
|
|
|
|
case responseDate = 6
|
2022-05-01 18:30:30 +02:00
|
|
|
}
|
2023-04-11 18:18:31 +02:00
|
|
|
}
|
2022-05-01 18:30:30 +02:00
|
|
|
|
2023-04-11 18:18:31 +02:00
|
|
|
extension ClientState: Codable {
|
|
|
|
|
|
|
|
init(from decoder: Decoder) throws {
|
|
|
|
let code = try decoder.singleValueContainer().decode(UInt8.self)
|
|
|
|
self.init(code: code)
|
2022-05-01 18:30:30 +02:00
|
|
|
}
|
2023-04-11 18:18:31 +02:00
|
|
|
|
|
|
|
func encode(to encoder: Encoder) throws {
|
|
|
|
var container = encoder.singleValueContainer()
|
|
|
|
try container.encode(code)
|
2022-05-01 18:30:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extension HistoryItem: Identifiable {
|
|
|
|
|
|
|
|
var id: UInt32 {
|
2023-04-11 18:18:31 +02:00
|
|
|
requestDate.timestamp
|
2022-05-01 18:30:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extension HistoryItem: Comparable {
|
|
|
|
|
|
|
|
static func < (lhs: HistoryItem, rhs: HistoryItem) -> Bool {
|
2023-04-11 18:18:31 +02:00
|
|
|
lhs.requestDate < rhs.requestDate
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extension HistoryItem {
|
|
|
|
|
|
|
|
static var mock: HistoryItem {
|
2023-08-07 15:47:40 +02:00
|
|
|
let content = Message.Content(time: Date.now.timestamp, id: 123, device: 0)
|
|
|
|
let content2 = Message.Content(time: (Date.now + 1).timestamp, id: 124, device: 0)
|
2023-08-14 10:39:29 +02:00
|
|
|
return .init(
|
|
|
|
sent: content,
|
|
|
|
sentDate: .now,
|
|
|
|
local: false,
|
|
|
|
response: .openSesame,
|
|
|
|
responseDate: .now + 2,
|
|
|
|
responseMessage: content2)
|
2022-05-01 18:30:30 +02:00
|
|
|
}
|
|
|
|
}
|