package me.khodak.claudeusage.data data class UsageData( val messagesUsed: Int = -1, val messagesLimit: Int = -1, val messagesRemaining: Int = -1, val resetAtEpoch: Long = -1L, val isRateLimited: Boolean = false, val lastUpdated: Long = 0L, val errorMessage: String = "", val isLoggedIn: Boolean = false, val sessionStartEpoch: Long = 0L, val weeklyActiveDaysMask: Int = 0, // bitmask: bit0=Sun, bit1=Mon ... bit6=Sat // From /api/organizations/{id}/usage — utilization as percentage 0-100 val fiveHourUtilization: Float = -1f, val weeklyUtilization: Float = -1f, val utilizationResetAtEpoch: Long = -1L, val weeklyResetAtEpoch: Long = -1L ) { val hasRateLimitData: Boolean get() = messagesLimit > 0 || messagesRemaining >= 0 || fiveHourUtilization >= 0f val hasSessionData: Boolean get() = sessionStartEpoch > 0 val progressPercent: Int get() = when { messagesLimit > 0 && effectiveUsed >= 0 -> ((effectiveUsed.toFloat() / messagesLimit.toFloat()) * 100).toInt().coerceIn(0, 100) fiveHourUtilization >= 0f -> fiveHourUtilization.toInt().coerceIn(0, 100) else -> 0 } val effectiveUsed: Int get() = when { messagesUsed >= 0 -> messagesUsed messagesRemaining >= 0 && messagesLimit > 0 -> messagesLimit - messagesRemaining else -> -1 } val effectiveRemaining: Int get() = when { messagesRemaining >= 0 -> messagesRemaining messagesUsed >= 0 && messagesLimit > 0 -> messagesLimit - messagesUsed else -> -1 } val weeklyActiveDays: Int get() = Integer.bitCount(weeklyActiveDaysMask) // The best reset time we have (utilization endpoint is preferred) val effectiveResetEpoch: Long get() = when { utilizationResetAtEpoch > 0 -> utilizationResetAtEpoch resetAtEpoch > 0 -> resetAtEpoch else -> -1L } }