Improved analysis screen on focused mode.

This commit is contained in:
Nathan Schneider
2026-01-17 22:58:24 -07:00
parent d1f288cda8
commit 56d1f7e11e
3 changed files with 469 additions and 65 deletions
+106 -10
View File
@@ -7,6 +7,7 @@
import ExportControls from './components/ExportControls.svelte';
import HelpModal from './components/HelpModal.svelte';
import FormRecommendation from './components/FormRecommendation.svelte';
import AnalysisTransitionBanner from './components/AnalysisTransitionBanner.svelte';
import { BicorderClassifier } from './bicorder-classifier';
// Load bicorder data and model from build-time constants
@@ -57,12 +58,12 @@
});
});
// Analysis screens (not in shortform)
if (!isShortForm) {
data.analysis.forEach((gradient, index) => {
screens.push({ type: 'analysis', index, gradient });
});
}
// Analysis screens (shown in both shortform and longform)
// Show useful/not-useful gradient first (index 3), then the others
const analysisOrder = [3, 0, 1, 2]; // useful/not-useful, hardness, polarization, bureaucratic
analysisOrder.forEach((index) => {
screens.push({ type: 'analysis', index, gradient: data.analysis[index] });
});
// Export screen
screens.push({ type: 'export' });
@@ -106,7 +107,80 @@
return filled.repeat(filledCount) + empty.repeat(emptyCount);
}
$: progressBar = generateProgressBar(currentScreen + 1, totalScreens);
// Calculate total diagnostic screens (metadata + gradients only)
$: diagnosticScreenCount = screens.filter(s => s.type === 'metadata' || s.type === 'gradient').length;
// Calculate current position within diagnostic screens
$: diagnosticProgress = currentScreenData?.type === 'metadata' || currentScreenData?.type === 'gradient'
? currentScreen + 1
: diagnosticScreenCount; // Show as complete when in analysis or export
$: progressBar = generateProgressBar(diagnosticProgress, diagnosticScreenCount);
// Detect if we're on the first analysis screen
$: isFirstAnalysisScreen = currentScreenData?.type === 'analysis' &&
screens.findIndex(s => s.type === 'analysis') === currentScreen;
// Calculate completed gradients for the banner
$: completedGradientsCount = data.diagnostic
.flatMap(set => set.gradients)
.filter(g => !data.metadata.shortform || g.shortform)
.filter(g => g.value !== null).length;
$: totalGradientsCount = data.diagnostic
.flatMap(set => set.gradients)
.filter(g => !data.metadata.shortform || g.shortform).length;
// Calculate form recommendation (shared by FormRecommendation and AnalysisTransitionBanner)
let formRecommendation: any = null;
let hasEnoughDataForRecommendation = false;
$: {
// Collect ratings from diagnostic data
const ratings: Record<string, number> = {};
let valueCount = 0;
let shortFormTotal = 0;
data.diagnostic.forEach((diagnosticSet) => {
const setName = diagnosticSet.set_name;
diagnosticSet.gradients.forEach((gradient) => {
// Count shortform gradients
if (gradient.shortform) {
shortFormTotal++;
}
if (gradient.value !== null) {
const dimensionName = `${setName}_${gradient.term_left}_vs_${gradient.term_right}`;
ratings[dimensionName] = gradient.value;
// Only count shortform values for the threshold
if (gradient.shortform) {
valueCount++;
}
}
});
});
// Only calculate if at least half of shortform gradients are complete
const threshold = Math.ceil(shortFormTotal / 2);
hasEnoughDataForRecommendation = valueCount >= threshold;
if (hasEnoughDataForRecommendation && data.metadata.shortform) {
try {
const prediction = classifier.predict(ratings, { detailed: true });
const assessment = classifier.assessShortFormReadiness(ratings);
formRecommendation = {
...prediction,
...assessment,
};
} catch (error) {
console.error('Error calculating form recommendation:', error);
formRecommendation = null;
}
} else {
formRecommendation = null;
}
}
// Load saved state from localStorage
onMount(() => {
@@ -351,8 +425,8 @@
<div class="header-right">
<FormRecommendation
{classifier}
diagnosticData={data.diagnostic}
recommendation={formRecommendation}
hasEnoughData={hasEnoughDataForRecommendation}
isShortForm={data.metadata.shortform}
on:switchToLongForm={handleSwitchToLongForm}
/>
@@ -480,6 +554,28 @@
<div class="focused-screen gradient-screen">
<div class="screen-category">ANALYSIS</div>
{#if isFirstAnalysisScreen}
<AnalysisTransitionBanner
recommendation={formRecommendation}
isShortForm={data.metadata.shortform}
completedGradients={completedGradientsCount}
allAnalysisGradients={data.analysis}
on:switchToLongForm={handleSwitchToLongForm}
on:jumpToExport={() => {
// Jump to the export screen (last screen)
currentScreen = screens.length - 1;
}}
on:updateAnalysis={(e) => {
data.analysis[e.detail.index].value = e.detail.value;
data = data;
}}
on:updateAnalysisNotes={(e) => {
data.analysis[e.detail.index].notes = e.detail.notes;
data = data;
}}
/>
{/if}
<div class="gradient-focused">
<div class="term-desc left-desc">
<div class="term-name">{screen.gradient.term_left}</div>
@@ -554,7 +650,7 @@
>
{progressBar}
</div>
<div class="progress-numbers">{currentScreen + 1} / {totalScreens}</div>
<div class="progress-numbers">{diagnosticProgress} / {diagnosticScreenCount}</div>
</div>
</div>
{/if}