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 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
- # Determine line color based on current utilization
147
- color = self._get_plotext_color(self.limit_data.utilization)
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(self, utilization: float) -> tuple[int, int, int]:
262
- """Get plotext RGB color based on utilization.
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
- if utilization < 0.5:
271
- return (0, 255, 0) # Bright green
272
- elif utilization < 0.75:
273
- return (255, 255, 0) # Bright yellow
274
- elif utilization < 0.9:
275
- return (255, 165, 0) # Orange
276
- else:
277
- return (255, 0, 0) # Bright red
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,
@@ -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 percentage.
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: Float between 0 and 1
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", "orange", or "red"
98
+ Color name: "green", "yellow", "bright_red", or "red"
98
99
  """
99
- if utilization < 0.5:
100
- return "green"
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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ccburn
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Terminal-based Claude Code usage limit visualizer with real-time burn-up charts
5
5
  Author: JuanjoFuchs
6
6
  License-Expression: MIT
@@ -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=j1qM6YX_K5SfKCxaob3-mT1vJjr8VMdsHIN8ORJu-2c,11421
12
- ccburn/display/gauges.py,sha256=thxOOwjvg1cPcTq0wp7KzfGUzS77eLPNey2wnitciBw,8567
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=O6L3KoDEGdN4iBSXQFrO-ysk6i01Gp4veFXjeKqk0sc,3414
17
- ccburn-0.2.0.dist-info/licenses/LICENSE,sha256=Qf2mqNi2qJ35JytfoTdR1SgYhZ2Mt4Ohcf-tu_MuYC0,1068
18
- ccburn-0.2.0.dist-info/METADATA,sha256=mrI1KKGnyYkUubAy3xlZvRy60aZNoYgWzd9-kp7M5ec,6979
19
- ccburn-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
20
- ccburn-0.2.0.dist-info/entry_points.txt,sha256=GfFQ5VusMR8RJ9meygqWjaErdmYsf_arbILzf64WjLU,43
21
- ccburn-0.2.0.dist-info/top_level.txt,sha256=SM8TwGQZqQKKIQObVWQkfpA0OI4gRut7bPl-iM3g5RI,7
22
- ccburn-0.2.0.dist-info/RECORD,,
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