|
|
|
|
|
|
|
|
|
|
|
|
|
|
import type { AnalysisResult } from '../types/analysis.types.ts'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export type StanceStats = { |
|
|
total: number; |
|
|
pro: number; |
|
|
con: number; |
|
|
proPercentage: number; |
|
|
conPercentage: number; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export type TopicFrequency = { |
|
|
topic: string; |
|
|
count: number; |
|
|
proCount: number; |
|
|
conCount: number; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export type TimeStats = { |
|
|
date: string; |
|
|
count: number; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function calculateStanceStats(results: AnalysisResult[]): StanceStats { |
|
|
const total = results.length; |
|
|
const pro = results.filter((r) => r.predicted_stance === 'PRO').length; |
|
|
const con = results.filter((r) => r.predicted_stance === 'CON').length; |
|
|
|
|
|
return { |
|
|
total, |
|
|
pro, |
|
|
con, |
|
|
proPercentage: total > 0 ? (pro / total) * 100 : 0, |
|
|
conPercentage: total > 0 ? (con / total) * 100 : 0, |
|
|
}; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function calculateTopicFrequency( |
|
|
results: AnalysisResult[], |
|
|
limit: number = 10 |
|
|
): TopicFrequency[] { |
|
|
const topicMap = new Map<string, { count: number; proCount: number; conCount: number }>(); |
|
|
|
|
|
results.forEach((result) => { |
|
|
const topic = result.topic.trim(); |
|
|
if (!topic) return; |
|
|
|
|
|
const existing = topicMap.get(topic) || { count: 0, proCount: 0, conCount: 0 }; |
|
|
existing.count += 1; |
|
|
if (result.predicted_stance === 'PRO') { |
|
|
existing.proCount += 1; |
|
|
} else { |
|
|
existing.conCount += 1; |
|
|
} |
|
|
topicMap.set(topic, existing); |
|
|
}); |
|
|
|
|
|
return Array.from(topicMap.entries()) |
|
|
.map(([topic, stats]) => ({ |
|
|
topic, |
|
|
count: stats.count, |
|
|
proCount: stats.proCount, |
|
|
conCount: stats.conCount, |
|
|
})) |
|
|
.sort((a, b) => b.count - a.count) |
|
|
.slice(0, limit); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function calculateTimeStats(results: AnalysisResult[]): TimeStats[] { |
|
|
const dateMap = new Map<string, number>(); |
|
|
|
|
|
results.forEach((result) => { |
|
|
const date = new Date(result.created_at).toISOString().split('T')[0]; |
|
|
dateMap.set(date, (dateMap.get(date) || 0) + 1); |
|
|
}); |
|
|
|
|
|
return Array.from(dateMap.entries()) |
|
|
.map(([date, count]) => ({ date, count })) |
|
|
.sort((a, b) => a.date.localeCompare(b.date)); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function getUniqueTopicsCount(results: AnalysisResult[]): number { |
|
|
const uniqueTopics = new Set(results.map((r) => r.topic.trim()).filter((t) => t)); |
|
|
return uniqueTopics.size; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function getAverageArgumentLength(results: AnalysisResult[]): number { |
|
|
if (results.length === 0) return 0; |
|
|
const totalLength = results.reduce((sum, r) => sum + r.argument.length, 0); |
|
|
return Math.round(totalLength / results.length); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function getMostRecentAnalysisDate(results: AnalysisResult[]): string | null { |
|
|
if (results.length === 0) return null; |
|
|
const dates = results.map((r) => new Date(r.created_at).getTime()); |
|
|
const mostRecent = new Date(Math.max(...dates)); |
|
|
return mostRecent.toISOString().split('T')[0]; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function getOldestAnalysisDate(results: AnalysisResult[]): string | null { |
|
|
if (results.length === 0) return null; |
|
|
const dates = results.map((r) => new Date(r.created_at).getTime()); |
|
|
const oldest = new Date(Math.min(...dates)); |
|
|
return oldest.toISOString().split('T')[0]; |
|
|
} |
|
|
|
|
|
|