File size: 3,673 Bytes
b1a8265
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7e55328
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b1a8265
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/**
 * Utility functions extracted per architect-reviewer:
 * no business logic in UI components.
 */

/**
 * Format ISO timestamp using Intl.DateTimeFormat (web-design-guidelines: no hardcoded formats)
 */
export function timeAgo(iso) {
    const diff = Date.now() - new Date(iso).getTime()
    const mins = Math.floor(diff / 60_000)
    if (mins < 1) return 'just now'
    if (mins < 60) return `${mins}m ago`
    const hrs = Math.floor(mins / 60)
    if (hrs < 24) return `${hrs}h ago`
    return new Intl.DateTimeFormat(undefined, { month: 'short', day: 'numeric' }).format(new Date(iso))
}

/**
 * Map a 0-100 credibility score to CSS color token
 */
export function scoreColor(score) {
    if (score >= 70) return 'var(--credible)'
    if (score >= 40) return 'var(--unverified)'
    return 'var(--fake)'
}

/**
 * Map verdict string to badge class
 */
export const VERDICT_MAP = {
    'Credible': { cls: 'badge-credible', label: 'VERIFIED', symbol: 'βœ“', explanation: 'This claim appears credible. Multiple signals and/or supporting evidence suggest this information is likely true.' },
    'Unverified': { cls: 'badge-unverified', label: 'UNVERIFIED', symbol: '?', explanation: 'We couldn\'t confirm or deny this claim. There isn\'t enough evidence either way β€” treat this information with caution and verify from other sources.' },
    'Likely Fake': { cls: 'badge-fake', label: 'FALSE', symbol: 'βœ—', explanation: 'This claim shows strong signs of being false or misleading. Our analysis detected multiple red flags β€” do not share this without verifying from trusted news sources.' },
}

/**
 * Human-readable interpretation of a 0-100 score
 */
export function scoreInterpretation(score) {
    if (score >= 85) return 'Very high credibility β€” strong evidence supports this claim.'
    if (score >= 70) return 'Likely credible β€” most signals point to this being true.'
    if (score >= 55) return 'Uncertain β€” some supporting evidence, but not enough to confirm.'
    if (score >= 40) return 'Questionable β€” limited evidence and some suspicious signals detected.'
    if (score >= 20) return 'Likely false β€” multiple red flags and contradicting evidence found.'
    return 'Very likely false β€” strong indicators of misinformation detected.'
}

/**
 * Human-readable explanation for Layer 1 ML confidence
 */
export function mlConfidenceExplanation(confidence, verdict) {
    const isFake = verdict === 'Likely Fake'
    if (confidence >= 85) return isFake
        ? 'The AI model is very confident this contains fake news patterns (clickbait, emotional manipulation, misleading language).'
        : 'The AI model is very confident this reads like legitimate, credible reporting.'
    if (confidence >= 60) return isFake
        ? 'The AI model detected several patterns commonly found in fake news.'
        : 'The AI model found this mostly consistent with credible content.'
    return 'The AI model has low confidence β€” the text doesn\'t clearly match fake or credible patterns.'
}

/**
 * Human-readable explanation for Layer 2 evidence score
 */
export function evidenceExplanation(score, sources) {
    const count = sources?.length || 0
    if (count === 0) return 'No matching news articles were found to cross-reference this claim. The score reflects a neutral default.'
    if (score >= 70) return `Found ${count} related article${count > 1 ? 's' : ''} from news sources that support this claim.`
    if (score >= 40) return `Found ${count} related article${count > 1 ? 's' : ''}, but evidence is mixed or inconclusive.`
    return `Found ${count} related article${count > 1 ? 's' : ''} β€” some contradict or debunk this claim.`
}