mirror of
https://github.com/BigMarc/grammargem.git
synced 2026-10-13 17:01:55 +02:00
Implements the highest-leverage items from docs/grammarly-value-plan.md: - Live Check: on-device 0-100 writing score, Correctness/Clarity/Polish count chips, and per-suggestion Dismiss / Add-to-dictionary (a cheap, always-available 'no' is what makes 'Apply' feel safe). - Value loop: day-streak, correction milestones and a 'subscription you didn't pay' figure on the dashboard + a streak line in the menu bar (all local, self-vs-self, no telemetry). - First-run demo: a planted sample the real engine cleans in one click, before any permission ask. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
21 lines
1013 B
Swift
21 lines
1013 B
Swift
import Foundation
|
||
|
||
/// A deterministic, on-device "cleanliness" score (0–100) for a chunk of text.
|
||
///
|
||
/// Honest by construction: it's defined relative to *this* text — weighted issues
|
||
/// per 100 words — never a hidden cloud cohort, and grammar/spelling are always
|
||
/// fully resolvable, so a clean document genuinely reaches 100. (Contrast with
|
||
/// Grammarly's percentile-vs-other-users score, which needs telemetry + an
|
||
/// account; see docs/grammarly-value-plan.md §5.)
|
||
enum WritingScore {
|
||
/// - Parameters:
|
||
/// - weightedIssues: sum of `GrammarKind.severity` across outstanding issues.
|
||
/// - words: total words in the scanned text.
|
||
static func score(weightedIssues: Int, words: Int) -> Int {
|
||
guard words > 0 else { return 100 }
|
||
let perHundredWords = Double(weightedIssues) / Double(words) * 100.0
|
||
// Each weighted issue per 100 words costs ~4 points; clamp to 0…100.
|
||
return max(0, min(100, Int((100.0 - perHundredWords * 4.0).rounded())))
|
||
}
|
||
}
|