ccburn 0.2.0__py3-none-any.whl → 0.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ccburn/display/chart.py +21 -12
- ccburn/display/gauges.py +2 -2
- ccburn/utils/formatting.py +32 -11
- {ccburn-0.2.0.dist-info → ccburn-0.2.1.dist-info}/METADATA +1 -1
- {ccburn-0.2.0.dist-info → ccburn-0.2.1.dist-info}/RECORD +9 -9
- {ccburn-0.2.0.dist-info → ccburn-0.2.1.dist-info}/WHEEL +0 -0
- {ccburn-0.2.0.dist-info → ccburn-0.2.1.dist-info}/entry_points.txt +0 -0
- {ccburn-0.2.0.dist-info → ccburn-0.2.1.dist-info}/licenses/LICENSE +0 -0
- {ccburn-0.2.0.dist-info → ccburn-0.2.1.dist-info}/top_level.txt +0 -0
ccburn/display/chart.py
CHANGED
|
@@ -10,8 +10,10 @@ from rich.jupyter import JupyterMixin
|
|
|
10
10
|
|
|
11
11
|
try:
|
|
12
12
|
from ..data.models import LimitData, UsageSnapshot
|
|
13
|
+
from ..utils.formatting import get_utilization_color
|
|
13
14
|
except ImportError:
|
|
14
15
|
from ccburn.data.models import LimitData, UsageSnapshot
|
|
16
|
+
from ccburn.utils.formatting import get_utilization_color
|
|
15
17
|
|
|
16
18
|
|
|
17
19
|
class BurnupChart(JupyterMixin):
|
|
@@ -143,8 +145,11 @@ class BurnupChart(JupyterMixin):
|
|
|
143
145
|
values.append(util_pct)
|
|
144
146
|
|
|
145
147
|
if times:
|
|
146
|
-
#
|
|
147
|
-
|
|
148
|
+
# Calculate budget pace for color determination
|
|
149
|
+
elapsed_hours = (now - original_window_start).total_seconds() / 3600
|
|
150
|
+
budget_pace = min(elapsed_hours / original_window_hours, 1.0)
|
|
151
|
+
# Determine line color based on utilization AND burn rate
|
|
152
|
+
color = self._get_plotext_color(self.limit_data.utilization, budget_pace)
|
|
148
153
|
# Use fillx=True for area chart effect (fills down to x-axis)
|
|
149
154
|
plt.plot(
|
|
150
155
|
times,
|
|
@@ -258,23 +263,27 @@ class BurnupChart(JupyterMixin):
|
|
|
258
263
|
|
|
259
264
|
return plt.build()
|
|
260
265
|
|
|
261
|
-
def _get_plotext_color(
|
|
262
|
-
|
|
266
|
+
def _get_plotext_color(
|
|
267
|
+
self, utilization: float, budget_pace: float = 0.0
|
|
268
|
+
) -> tuple[int, int, int]:
|
|
269
|
+
"""Get plotext RGB color based on utilization and burn rate.
|
|
263
270
|
|
|
264
271
|
Args:
|
|
265
272
|
utilization: Current utilization (0-1)
|
|
273
|
+
budget_pace: How much of window has elapsed (0-1)
|
|
266
274
|
|
|
267
275
|
Returns:
|
|
268
276
|
RGB tuple for plotext - bright vivid colors matching Rich progress bars
|
|
269
277
|
"""
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
+
# Reuse shared color logic, map Rich color names to RGB
|
|
279
|
+
color_name = get_utilization_color(utilization, budget_pace)
|
|
280
|
+
color_map = {
|
|
281
|
+
"green": (0, 255, 0),
|
|
282
|
+
"yellow": (255, 255, 0),
|
|
283
|
+
"bright_red": (255, 165, 0), # Orange
|
|
284
|
+
"red": (255, 0, 0),
|
|
285
|
+
}
|
|
286
|
+
return color_map.get(color_name, (255, 255, 0))
|
|
278
287
|
|
|
279
288
|
|
|
280
289
|
def create_simple_chart(
|
ccburn/display/gauges.py
CHANGED
|
@@ -110,9 +110,9 @@ def create_gauge_section(
|
|
|
110
110
|
utilization_percent = limit_data.utilization * 100
|
|
111
111
|
pace_percent = budget_pace * 100
|
|
112
112
|
|
|
113
|
-
# Usage bar - color by threshold
|
|
113
|
+
# Usage bar - color by threshold AND burn rate
|
|
114
114
|
# complete_style = filled portion (bright), style = unfilled portion (dim)
|
|
115
|
-
usage_color = get_utilization_color(limit_data.utilization)
|
|
115
|
+
usage_color = get_utilization_color(limit_data.utilization, budget_pace)
|
|
116
116
|
usage_bar = ProgressBar(
|
|
117
117
|
total=100,
|
|
118
118
|
completed=utilization_percent,
|
ccburn/utils/formatting.py
CHANGED
|
@@ -87,24 +87,45 @@ def format_reset_time(resets_at: datetime, now: datetime | None = None) -> str:
|
|
|
87
87
|
return f"Resets {day_name} {time_str}"
|
|
88
88
|
|
|
89
89
|
|
|
90
|
-
def get_utilization_color(utilization: float) -> str:
|
|
91
|
-
"""Get color based on utilization
|
|
90
|
+
def get_utilization_color(utilization: float, budget_pace: float = 0.0) -> str:
|
|
91
|
+
"""Get color based on utilization and burn rate.
|
|
92
92
|
|
|
93
93
|
Args:
|
|
94
|
-
utilization:
|
|
94
|
+
utilization: Current usage (0-1)
|
|
95
|
+
budget_pace: How much of window has elapsed (0-1)
|
|
95
96
|
|
|
96
97
|
Returns:
|
|
97
|
-
Color name: "green", "yellow", "
|
|
98
|
+
Color name: "green", "yellow", "bright_red", or "red"
|
|
98
99
|
"""
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
elif utilization < 0.75:
|
|
102
|
-
return "yellow"
|
|
103
|
-
elif utilization < 0.9:
|
|
104
|
-
return "bright_red" # Rich uses "bright_red" for orange-like
|
|
105
|
-
else:
|
|
100
|
+
# Critical: always red at very high utilization
|
|
101
|
+
if utilization >= 0.9:
|
|
106
102
|
return "red"
|
|
107
103
|
|
|
104
|
+
# Calculate burn ratio if we have meaningful data
|
|
105
|
+
burn_ratio = 1.0
|
|
106
|
+
if budget_pace >= 0.05 and utilization >= 0.01:
|
|
107
|
+
burn_ratio = utilization / budget_pace
|
|
108
|
+
|
|
109
|
+
# High utilization: at least orange, red if also burning fast
|
|
110
|
+
if utilization >= 0.75:
|
|
111
|
+
return "red" if burn_ratio > 1.5 else "bright_red"
|
|
112
|
+
|
|
113
|
+
# Moderate utilization: color based on burn rate
|
|
114
|
+
if utilization >= 0.5:
|
|
115
|
+
if burn_ratio > 2.0:
|
|
116
|
+
return "red"
|
|
117
|
+
if burn_ratio > 1.5:
|
|
118
|
+
return "bright_red"
|
|
119
|
+
return "yellow"
|
|
120
|
+
|
|
121
|
+
# Low utilization: escalate only if burning very fast
|
|
122
|
+
if burn_ratio > 3.0:
|
|
123
|
+
return "bright_red" # Will hit limit at ~33% of window
|
|
124
|
+
if burn_ratio > 2.0:
|
|
125
|
+
return "yellow" # Will hit limit at ~50% of window
|
|
126
|
+
|
|
127
|
+
return "green"
|
|
128
|
+
|
|
108
129
|
|
|
109
130
|
def get_status_indicator(utilization: float, budget_pace: float) -> str:
|
|
110
131
|
"""Get status indicator for compact output.
|
|
@@ -8,15 +8,15 @@ ccburn/data/history.py,sha256=ouBxrXpMp_eTs0kba1Bg55TI6bsBSMToJ32tH1wNHQI,12879
|
|
|
8
8
|
ccburn/data/models.py,sha256=Sd2T36gH6OaNHl9zRlnnQXI-ziBA8Gl6rPYQIzmr7G4,5403
|
|
9
9
|
ccburn/data/usage_client.py,sha256=_dGwmI5vYPk4S-HUe2_fnTwSuAfTPaOFff7mKPFnhps,4570
|
|
10
10
|
ccburn/display/__init__.py,sha256=aL7TV53kU5oxlIwJ8M17stG2aC6UeGB-pj2u5BOpegs,495
|
|
11
|
-
ccburn/display/chart.py,sha256=
|
|
12
|
-
ccburn/display/gauges.py,sha256=
|
|
11
|
+
ccburn/display/chart.py,sha256=HGDcMqaqyNtlQzV-d-gUOStq8qjpVt4EYvCIU6BTAx8,11983
|
|
12
|
+
ccburn/display/gauges.py,sha256=DCRunsEtv1HflRkTZLwnNbVZhe47gCIH78p3gfqFwDo,8594
|
|
13
13
|
ccburn/display/layout.py,sha256=UndPxyh32jWGdDgOZCvedz06WcKxYMSchLwpOkkXQKo,8093
|
|
14
14
|
ccburn/utils/__init__.py,sha256=N6EzUX9hUJkuga_l9Ci3of1CWNtQgpNmMmNyY2DgYrg,1119
|
|
15
15
|
ccburn/utils/calculator.py,sha256=QcFm5X-VWZzucHdInEjjqKV5oZaNsdpMgl8oKvHAQYc,6174
|
|
16
|
-
ccburn/utils/formatting.py,sha256=
|
|
17
|
-
ccburn-0.2.
|
|
18
|
-
ccburn-0.2.
|
|
19
|
-
ccburn-0.2.
|
|
20
|
-
ccburn-0.2.
|
|
21
|
-
ccburn-0.2.
|
|
22
|
-
ccburn-0.2.
|
|
16
|
+
ccburn/utils/formatting.py,sha256=MEVIohBmvSur0hcc67oyYRDooiUMf0rPa4LO1fc2Ud4,4174
|
|
17
|
+
ccburn-0.2.1.dist-info/licenses/LICENSE,sha256=Qf2mqNi2qJ35JytfoTdR1SgYhZ2Mt4Ohcf-tu_MuYC0,1068
|
|
18
|
+
ccburn-0.2.1.dist-info/METADATA,sha256=gnEPQbkE97in73KUywvp6hF7nrMUzYCG5Lvv1UU06ZI,6979
|
|
19
|
+
ccburn-0.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
20
|
+
ccburn-0.2.1.dist-info/entry_points.txt,sha256=GfFQ5VusMR8RJ9meygqWjaErdmYsf_arbILzf64WjLU,43
|
|
21
|
+
ccburn-0.2.1.dist-info/top_level.txt,sha256=SM8TwGQZqQKKIQObVWQkfpA0OI4gRut7bPl-iM3g5RI,7
|
|
22
|
+
ccburn-0.2.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|