Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions Sources/PokeTokenBar/Core/TokenFormatter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,19 @@ enum TokenFormatter {
}

/// 메뉴바용 짧은 비용 표기: $9.5 / $311 / $1.2K
/// 구간 판정은 원값이 아니라 *반올림된 문자열*로 한다 — 99.96 은 "$100.0" 이 아니라 "$100".
static func costCompact(_ usd: Double) -> String {
if usd < 100 { return String(format: "$%.1f", usd) }
if usd < 10_000 { return String(format: "$%.0f", usd) }
let tenths = String(format: "%.1f", usd)
if let v = Double(tenths), v < 100 { return "$" + tenths }
let whole = String(format: "%.0f", usd)
if let v = Double(whole), v < 10_000 { return "$" + whole }
return String(format: "$%.1fK", usd / 1_000)
}

/// 79.96 → "80%" (not "80.0%"), 88.35 → "88.3%"
static func percent(_ value: Double) -> String {
value == value.rounded() ? String(format: "%.0f%%", value) : String(format: "%.1f%%", value)
let tenths = String(format: "%.1f", value)
return (tenths.hasSuffix(".0") ? String(tenths.dropLast(2)) : tenths) + "%"
}

private static func trim(_ value: Double, decimals: Int) -> String {
Expand Down
16 changes: 16 additions & 0 deletions Tests/PokeTokenBarTests/LocalUsageCacheTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -824,6 +824,22 @@ final class LocalUsageCacheTests: XCTestCase {
XCTAssertEqual(TokenFormatter.percent(88.35), "88.3%")
}

/// Branching on the raw value and then rounding prints a value the branch said was below the
/// cutoff: "80.0%" instead of "80%", "$100.0" instead of "$100", "$10000" instead of "$10.0K".
/// Cursor's `usedPercent` is fractional and remaining mode prints `100 − x`, so these reach
/// the menu bar and the popover.
func testFormatterRoundingBoundaries() {
XCTAssertEqual(TokenFormatter.percent(79.96), "80%")
XCTAssertEqual(TokenFormatter.percent(99.97), "100%")
XCTAssertEqual(TokenFormatter.percent(0.04), "0%")
XCTAssertEqual(TokenFormatter.percent(79.94), "79.9%")
XCTAssertEqual(TokenFormatter.costCompact(99.96), "$100")
XCTAssertEqual(TokenFormatter.costCompact(99.94), "$99.9")
XCTAssertEqual(TokenFormatter.costCompact(9_999.6), "$10.0K")
XCTAssertEqual(TokenFormatter.costCompact(9_999.4), "$9999")
XCTAssertEqual(TokenFormatter.costCompact(100), "$100")
}

/// 날짜 유틸 — 주/월 경계와 monthKey (집계 윈도우 계산의 기반).
func testDateHelpers() {
var c = Calendar.current
Expand Down
13 changes: 13 additions & 0 deletions docs/reference/defect-log.md
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,19 @@ read_when:
클로저 안에서 `.reservesScrollerLane()` 을 쓰는지 괄호 매칭으로 검사한다(주석·문자열 제외, 바깥에 붙인
패딩은 스크롤러까지 밀어 불인정). 다섯 곳 각각을 빼면 해당 `파일:줄` 로 실패하는 것을 확인했다.

- **숫자 표기 구간은 원값이 아니라 반올림된 문자열로 판정한다.**
`TokenFormatter.percent` 는 `value == value.rounded()` 로 정수 여부를 보고 아니면 `%.1f` 를 찍었다 —
79.96 은 정수가 아니라 `%.1f` 로 가서 "80.0%" 가 됐다(88% 는 "88%" 인데 80% 만 소수점). `costCompact` 도
`usd < 100` 을 원값으로 판정해 99.96 → "$100.0", 9 999.6 → "$10000"(K 구간 대신 5자리)이 나왔다.
Cursor `usedPercent`·잔여 모드 `100 − x`·리캡 증감 `abs(delta)*100`·토큰 단가 기반 비용은 전부 임의의
소수라 메뉴바·팝오버·알림에 실제로 나온다.
**왜 못 걸렀나:** `testFormatterEdges` 는 구간 한가운데 값(88, 88.35, 9.54, 311.4)만 넣었다. 반올림이
구간 경계를 넘는 값(x.95 이상)이 없으면 "판정 후 반올림" 순서 결함은 보이지 않는다.
**수정:** 먼저 그 구간의 정밀도로 포맷하고, 그 문자열(파싱값)로 구간을 고른다.
**회귀 가드:** `testFormatterRoundingBoundaries` — 경계 직전·직후 쌍(79.96/79.94, 99.96/99.94,
9 999.6/9 999.4). 수정 전 코드로 5건 실패 확인. 스윕: `L.difficultyValue` 도 같은 모양이지만
`snapDifficulty` 가 유효숫자 2자리로 스냅해 경계 넘는 입력이 존재하지 않아 손대지 않았다.

## 에너지 (상시 표시 애니메이션)

- **메뉴바 상태아이템 = idle CPU 저격수 (두 규칙 필수).** 실측: 라이브 앱 idle ~14% CPU → 수정 후 ~2%.
Expand Down
Loading