Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  UsageData.swift   Sprache: unbekannt

 
Untersuchungsergebnis.swift Download desUnknown {[0] [0] [0]}zum Wurzelverzeichnis wechseln

import Foundation

struct GatewayUsageWindow: Codable {
    let label: String
    let usedPercent: Double
    let resetAt: Double?
}

struct GatewayUsageProvider: Codable {
    let provider: String
    let displayName: String
    let windows: [GatewayUsageWindow]
    let plan: String?
    let error: String?
}

struct GatewayUsageSummary: Codable {
    let updatedAt: Double
    let providers: [GatewayUsageProvider]
}

struct UsageRow: Identifiable {
    let id: String
    let providerId: String
    let displayName: String
    let plan: String?
    let windowLabel: String?
    let usedPercent: Double?
    let resetAt: Date?
    let error: String?

    var hasError: Bool {
        if let error, !error.isEmpty { return true }
        return false
    }

    var titleText: String {
        if let plan, !plan.isEmpty { return "\(self.displayName) (\(plan))" }
        return self.displayName
    }

    var remainingPercent: Int? {
        guard let usedPercent, usedPercent.isFinite else { return nil }
        return max(0, min(100, Int(round(100 - usedPercent))))
    }

    func detailText(now: Date = .init()) -> String {
        guard let remaining = self.remainingPercent else { return "No data" }
        var parts = ["\(remaining)% left"]
        if let windowLabel, !windowLabel.isEmpty { parts.append(windowLabel) }
        if let resetAt {
            let reset = UsageRow.formatResetRemaining(target: resetAt, now: now)
            if let reset { parts.append("⏱\(reset)") }
        }
        return parts.joined(separator: " · ")
    }

    private static func formatResetRemaining(target: Date, now: Date) -> String? {
        let diff = target.timeIntervalSince(now)
        if diff <= 0 { return "now" }
        let minutes = Int(floor(diff / 60))
        if minutes < 60 { return "\(minutes)m" }
        let hours = minutes / 60
        let mins = minutes % 60
        if hours < 24 { return mins > 0 ? "\(hours)h \(mins)m" : "\(hours)h" }
        let days = hours / 24
        if days < 7 { return "\(days)d \(hours % 24)h" }
        let formatter = DateFormatter()
        formatter.dateFormat = "MMM d"
        return formatter.string(from: target)
    }
}

extension GatewayUsageSummary {
    func primaryRows() -> [UsageRow] {
        self.providers.compactMap { provider in
            guard let window = provider.windows.max(by: { $0.usedPercent < $1.usedPercent }) else {
                return nil
            }

            return UsageRow(
                id: "\(provider.provider)-\(window.label)",
                providerId: provider.provider,
                displayName: provider.displayName,
                plan: provider.plan,
                windowLabel: window.label,
                usedPercent: window.usedPercent,
                resetAt: window.resetAt.map { Date(timeIntervalSince1970: $0 / 1000) },
                error: nil)
        }
    }
}

@MainActor
enum UsageLoader {
    static func loadSummary() async throws -> GatewayUsageSummary {
        let data = try await ControlChannel.shared.request(
            method: "usage.status",
            params: nil,
            timeoutMs: 5000)
        return try JSONDecoder().decode(GatewayUsageSummary.self, from: data)
    }
}

[Dauer der Verarbeitung: 0.1 Sekunden, vorverarbeitet 2026-06-10]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik