diff --git a/package.json b/package.json
index bc2b957736..60d1c5cddd 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,7 @@
"generate-schemas": "yarn generate-schema:StudyConfig && yarn generate-schema:GlobalConfig && yarn generate-schema:LibraryConfig",
"test": "playwright test",
"unittest": "vitest",
- "preinstall": "node -e 'if(!/yarn\\.js$/.test(process.env.npm_execpath))throw new Error(\"Use yarn\")'",
+ "preinstall": "node -e \"if(!/yarn\\.js$/.test(process.env.npm_execpath))throw new Error('Use yarn')\"",
"postinstall": "husky"
},
"lint-staged": {
diff --git a/src/analysis/individualStudy/stats/StatsView.tsx b/src/analysis/individualStudy/stats/StatsView.tsx
index 0ff52ceb3a..6f3c786066 100644
--- a/src/analysis/individualStudy/stats/StatsView.tsx
+++ b/src/analysis/individualStudy/stats/StatsView.tsx
@@ -10,6 +10,11 @@ import { StudyConfig } from '../../../parser/types';
import { TrialVisualization } from './TrialVisualization';
import { ComponentBlockWithOrderPath, StepsPanel } from '../../../components/interface/StepsPanel';
import { addPathToComponentBlock } from '../../../utils/getSequenceFlatMap';
+import { OverviewStats } from '../summary/OverviewStats';
+import {
+ calculateParticipantCounts, calculateCorrectnessStats, calculateTimeStats, calculateDateStats, calculateComponentStats,
+} from '../summary/utils';
+import { OverviewData } from '../../types';
export function StatsView(
{
@@ -29,9 +34,52 @@ export function StatsView(
const { trialId } = useParams();
+ const filteredParticipants = useMemo(() => {
+ // Before selecting a trial, show all participants
+ if (!trialId || trialId === 'end') return visibleParticipants;
+
+ return visibleParticipants
+ .map((p) => {
+ const filteredAnswers = Object.fromEntries(
+ Object.entries(p.answers).filter(([key]) => {
+ const parts = key.split('_');
+ const component = parts.length === 4 ? parts[2] : parts[0];
+ return component === trialId;
+ }),
+ );
+ return { ...p, answers: filteredAnswers } as ParticipantData;
+ })
+ .filter((p) => Object.keys(p.answers).length > 0);
+ }, [visibleParticipants, trialId]);
+
+ const overviewData = useMemo(() => {
+ if (filteredParticipants.length === 0) return null;
+
+ const participantCounts = calculateParticipantCounts(filteredParticipants);
+ const { avgTime, avgCleanTime } = calculateTimeStats(filteredParticipants);
+ const { startDate, endDate } = calculateDateStats(filteredParticipants);
+ const correctnessStats = calculateCorrectnessStats(filteredParticipants);
+
+ // Calculate component data
+ const componentStats = calculateComponentStats(visibleParticipants);
+ const componentData = componentStats.map((stat) => ({
+ component: stat.name,
+ participants: stat.participantCount,
+ avgTime: Number.isFinite(stat.avgTime) ? `${stat.avgTime.toFixed(1)}s` : 'N/A',
+ avgCleanTime: Number.isFinite(stat.avgCleanTime) ? `${stat.avgCleanTime.toFixed(1)}s` : 'N/A',
+ correctness: !Number.isNaN(stat.correctness) ? `${stat.correctness.toFixed(1)}%` : 'N/A',
+ }));
+
+ return {
+ participantCounts, avgTime, avgCleanTime, startDate, endDate, correctnessStats, componentData,
+ };
+ }, [filteredParticipants, studyConfig, trialId]);
+
return (
-
- {
+ <>
+
+
+ {
(visibleParticipants.length === 0)
? (
@@ -52,6 +100,7 @@ export function StatsView(
)
}
-
+
+ >
);
}
diff --git a/src/public/libraries/virtual-chinrest/assets/ViewingDistanceCalibration.tsx b/src/public/libraries/virtual-chinrest/assets/ViewingDistanceCalibration.tsx
index a5dc622062..0c07a55a5e 100644
--- a/src/public/libraries/virtual-chinrest/assets/ViewingDistanceCalibration.tsx
+++ b/src/public/libraries/virtual-chinrest/assets/ViewingDistanceCalibration.tsx
@@ -171,14 +171,14 @@ export default function ViewingDistanceCalibration({ parameters, setAnswer }: St
- Put your left hand on the
+ Put your left hand on the
space bar
.
Cover your right eye with your right hand.
Using your left eye, focus on the black square. Keep your focus on the black square.
- The
+ The
red ball
{' '}
will disappear as it moves from right to left.