518 lines
20 KiB
TypeScript
518 lines
20 KiB
TypeScript
import React, { useRef, useState, useEffect } from "react";
|
||
import { ArrowDown, Check, BookOpen, AlertTriangle, Zap } from "lucide-react";
|
||
import DataClaimWidget, {
|
||
type DataExercise,
|
||
} from "../../../components/lessons/DataClaimWidget";
|
||
import { PracticeFromDataset } from "../../../components/lessons/LessonShell";
|
||
import {
|
||
COMMAND_EVIDENCE_EASY,
|
||
COMMAND_EVIDENCE_MEDIUM,
|
||
} from "../../../data/rw/command-of-evidence";
|
||
|
||
interface LessonProps {
|
||
onFinish?: () => void;
|
||
}
|
||
|
||
const DATA_EXERCISES: DataExercise[] = [
|
||
{
|
||
title: "Bar — School Activities",
|
||
chart: {
|
||
type: "bar",
|
||
title:
|
||
"Student Participation in Extracurricular Activities (% of students)",
|
||
yLabel: "% of students",
|
||
xLabel: "Grade Level",
|
||
unit: "%",
|
||
source: "School District Survey, 2023",
|
||
series: [
|
||
{
|
||
name: "Sports",
|
||
data: [
|
||
{ label: "Gr 9", value: 45 },
|
||
{ label: "Gr 10", value: 42 },
|
||
{ label: "Gr 11", value: 38 },
|
||
{ label: "Gr 12", value: 30 },
|
||
],
|
||
},
|
||
{
|
||
name: "Arts & Music",
|
||
data: [
|
||
{ label: "Gr 9", value: 28 },
|
||
{ label: "Gr 10", value: 30 },
|
||
{ label: "Gr 11", value: 32 },
|
||
{ label: "Gr 12", value: 35 },
|
||
],
|
||
},
|
||
{
|
||
name: "Academic Clubs",
|
||
data: [
|
||
{ label: "Gr 9", value: 18 },
|
||
{ label: "Gr 10", value: 22 },
|
||
{ label: "Gr 11", value: 26 },
|
||
{ label: "Gr 12", value: 31 },
|
||
],
|
||
},
|
||
],
|
||
},
|
||
claims: [
|
||
{
|
||
text: "Sports participation declines as students advance from Grade 9 to Grade 12.",
|
||
verdict: "supported",
|
||
explanation:
|
||
"The chart shows sports falling from 45% (Grade 9) to 30% (Grade 12) — a consistent decrease at every grade level. This is directly supported.",
|
||
},
|
||
{
|
||
text: "Students drop sports because they find academic clubs more interesting.",
|
||
verdict: "neither",
|
||
explanation:
|
||
"The chart shows participation trends but gives no information about WHY students make these choices. Reasons (interest, time, pressure) cannot be inferred from percentages alone.",
|
||
},
|
||
{
|
||
text: "Sports is the most popular activity among students in every grade level shown.",
|
||
verdict: "contradicted",
|
||
explanation:
|
||
"Sports leads in Grades 9–11, but in Grade 12 Arts & Music (35%) exceeds Sports (30%). Since Sports is NOT the top activity in Grade 12, this claim is directly contradicted by the data.",
|
||
},
|
||
],
|
||
},
|
||
{
|
||
title: "Line — Temperature",
|
||
chart: {
|
||
type: "line",
|
||
title: "Average Global Temperature Anomaly (°C above 1951–1980 baseline)",
|
||
yLabel: "Anomaly (°C)",
|
||
xLabel: "Year",
|
||
unit: "°C",
|
||
source: "NASA GISS Surface Temperature Analysis",
|
||
series: [
|
||
{
|
||
name: "Temperature Anomaly",
|
||
data: [
|
||
{ label: "1980", value: 0.26 },
|
||
{ label: "1990", value: 0.44 },
|
||
{ label: "2000", value: 0.42 },
|
||
{ label: "2005", value: 0.67 },
|
||
{ label: "2010", value: 0.72 },
|
||
{ label: "2015", value: 0.87 },
|
||
{ label: "2020", value: 1.02 },
|
||
],
|
||
},
|
||
],
|
||
},
|
||
claims: [
|
||
{
|
||
text: "The temperature anomaly in 2020 was higher than in any previous year shown in the graph.",
|
||
verdict: "supported",
|
||
explanation:
|
||
"+1.02°C in 2020 is the highest data point — every prior year is lower. This is directly supported by the graph.",
|
||
},
|
||
{
|
||
text: "The temperature anomaly decreased between 1990 and 2000.",
|
||
verdict: "supported",
|
||
explanation:
|
||
"The graph shows +0.44°C in 1990 and +0.42°C in 2000 — a slight downward dip. This is directly supported, though the change is small.",
|
||
},
|
||
{
|
||
text: "Human industrial activity is the primary cause of the temperature increases shown.",
|
||
verdict: "neither",
|
||
explanation:
|
||
"The graph records temperature trends but provides no data on causes. Attributing increases to human activity requires additional scientific evidence not present in this graph.",
|
||
},
|
||
],
|
||
},
|
||
{
|
||
title: "Bar — Media Use",
|
||
chart: {
|
||
type: "bar",
|
||
title: "Average Daily Media Consumption by Age Group (hours per day)",
|
||
yLabel: "Hours per day",
|
||
xLabel: "Media Type",
|
||
unit: " hr",
|
||
source: "National Media Survey, 2024",
|
||
series: [
|
||
{
|
||
name: "Ages 13–17",
|
||
data: [
|
||
{ label: "Social Media", value: 4.8 },
|
||
{ label: "Streaming", value: 3.2 },
|
||
{ label: "Video Games", value: 2.5 },
|
||
{ label: "Reading", value: 0.7 },
|
||
],
|
||
},
|
||
{
|
||
name: "Ages 18–24",
|
||
data: [
|
||
{ label: "Social Media", value: 3.6 },
|
||
{ label: "Streaming", value: 3.9 },
|
||
{ label: "Video Games", value: 1.8 },
|
||
{ label: "Reading", value: 1.1 },
|
||
],
|
||
},
|
||
],
|
||
},
|
||
claims: [
|
||
{
|
||
text: "Teenagers (ages 13–17) spend more time on social media than on any other media type shown.",
|
||
verdict: "supported",
|
||
explanation:
|
||
"Social Media (4.8 hr) is the highest value for ages 13–17, exceeding Streaming (3.2 hr), Video Games (2.5 hr), and Reading (0.7 hr). Directly supported.",
|
||
},
|
||
{
|
||
text: "Adults ages 18–24 spend more time on streaming video than teenagers do.",
|
||
verdict: "supported",
|
||
explanation:
|
||
"Ages 18–24: Streaming = 3.9 hr. Ages 13–17: Streaming = 3.2 hr. 3.9 > 3.2, so this claim is directly supported.",
|
||
},
|
||
{
|
||
text: "Teenagers read less because social media is more entertaining to them.",
|
||
verdict: "neither",
|
||
explanation:
|
||
"The chart shows that teens spend little time reading (0.7 hr), but provides no data about why. Entertainment preferences require separate survey data not shown here.",
|
||
},
|
||
],
|
||
},
|
||
{
|
||
title: "Line — Renewable Energy",
|
||
chart: {
|
||
type: "line",
|
||
title: "Renewable Energy Share of U.S. Electricity Generation (%)",
|
||
yLabel: "% of generation",
|
||
xLabel: "Year",
|
||
unit: "%",
|
||
source: "U.S. Energy Information Administration",
|
||
series: [
|
||
{
|
||
name: "Solar",
|
||
data: [
|
||
{ label: "2010", value: 0.1 },
|
||
{ label: "2013", value: 0.4 },
|
||
{ label: "2016", value: 1.3 },
|
||
{ label: "2019", value: 2.7 },
|
||
{ label: "2022", value: 5.5 },
|
||
],
|
||
},
|
||
{
|
||
name: "Wind",
|
||
data: [
|
||
{ label: "2010", value: 2.3 },
|
||
{ label: "2013", value: 4.1 },
|
||
{ label: "2016", value: 5.6 },
|
||
{ label: "2019", value: 7.3 },
|
||
{ label: "2022", value: 10.2 },
|
||
],
|
||
},
|
||
],
|
||
},
|
||
claims: [
|
||
{
|
||
text: "Wind energy generated a larger share of electricity than solar energy in every year shown.",
|
||
verdict: "supported",
|
||
explanation:
|
||
"In all five years (2010–2022), Wind exceeds Solar: e.g., 2010 (2.3% vs. 0.1%) and 2022 (10.2% vs. 5.5%). This trend is directly visible throughout the graph.",
|
||
},
|
||
{
|
||
text: "Solar energy's share grew by more percentage points than wind energy's share between 2010 and 2022.",
|
||
verdict: "contradicted",
|
||
explanation:
|
||
"Solar: 0.1% → 5.5% = +5.4 points. Wind: 2.3% → 10.2% = +7.9 points. Wind grew by more absolute percentage points, so the claim that Solar grew more is directly contradicted.",
|
||
},
|
||
{
|
||
text: "Renewable energy will replace all fossil fuels within the next 20 years.",
|
||
verdict: "neither",
|
||
explanation:
|
||
"The graph shows growth trends for two renewables through 2022 but provides no data about total energy mix, future rates, or fossil fuel usage. Future predictions require additional data not shown here.",
|
||
},
|
||
],
|
||
},
|
||
];
|
||
|
||
const EBRWGraphicDisplaysLesson: React.FC<LessonProps> = ({ onFinish }) => {
|
||
const [activeSection, setActiveSection] = useState(0);
|
||
const sectionsRef = useRef<(HTMLElement | null)[]>([]);
|
||
|
||
useEffect(() => {
|
||
const observers: IntersectionObserver[] = [];
|
||
sectionsRef.current.forEach((el, idx) => {
|
||
if (!el) return;
|
||
const obs = new IntersectionObserver(
|
||
([entry]) => {
|
||
if (entry.isIntersecting) setActiveSection(idx);
|
||
},
|
||
{ threshold: 0.3 },
|
||
);
|
||
obs.observe(el);
|
||
observers.push(obs);
|
||
});
|
||
return () => observers.forEach((o) => o.disconnect());
|
||
}, []);
|
||
|
||
const scrollToSection = (i: number) => {
|
||
setActiveSection(i);
|
||
sectionsRef.current[i]?.scrollIntoView({ behavior: "smooth" });
|
||
};
|
||
|
||
const SectionMarker = ({
|
||
index,
|
||
title,
|
||
icon: Icon,
|
||
}: {
|
||
index: number;
|
||
title: string;
|
||
icon: React.ElementType;
|
||
}) => {
|
||
const isActive = activeSection === index;
|
||
const isPast = activeSection > index;
|
||
return (
|
||
<button
|
||
onClick={() => scrollToSection(index)}
|
||
className={`flex items-center gap-3 p-3 w-full rounded-lg text-left transition-all ${isActive ? "bg-amber-50" : "hover:bg-slate-50"}`}
|
||
>
|
||
<div
|
||
className={`w-8 h-8 rounded-full flex items-center justify-center shrink-0 ${isActive ? "bg-amber-600 text-white" : isPast ? "bg-amber-400 text-white" : "bg-slate-200 text-slate-500"}`}
|
||
>
|
||
{isPast ? (
|
||
<Check className="w-4 h-4" />
|
||
) : (
|
||
// @ts-ignore
|
||
<Icon className="w-4 h-4" />
|
||
)}
|
||
</div>
|
||
<p
|
||
className={`text-sm font-bold ${isActive ? "text-amber-900" : "text-slate-600"}`}
|
||
>
|
||
{title}
|
||
</p>
|
||
</button>
|
||
);
|
||
};
|
||
|
||
return (
|
||
<div className="flex flex-col lg:flex-row min-h-screen">
|
||
<aside className="w-full lg:w-64 lg:fixed lg:top-14 lg:bottom-0 lg:overflow-y-auto p-4 border-r border-slate-200 bg-slate-50 z-0 hidden lg:block">
|
||
<nav className="space-y-2 pt-6">
|
||
<SectionMarker index={0} title="Reading Graphics" icon={BookOpen} />
|
||
<SectionMarker
|
||
index={1}
|
||
title="Data Claim Lab"
|
||
icon={AlertTriangle}
|
||
/>
|
||
<SectionMarker index={2} title="Practice Quiz" icon={Zap} />
|
||
</nav>
|
||
</aside>
|
||
|
||
<div className="flex-1 lg:ml-64 p-6 md:p-12 max-w-4xl mx-auto">
|
||
{/* SECTION 0: Reading Graphics */}
|
||
<section
|
||
ref={(el) => {
|
||
sectionsRef.current[0] = el;
|
||
}}
|
||
className="min-h-screen flex flex-col justify-center mb-24 pt-20 lg:pt-0"
|
||
>
|
||
<div className="inline-flex items-center gap-2 bg-amber-100 text-amber-700 px-3 py-1 rounded-full text-xs font-bold uppercase tracking-wider mb-4">
|
||
Graphic Displays
|
||
</div>
|
||
<h2 className="text-4xl font-extrabold text-slate-900 mb-2">
|
||
Reading Graphics
|
||
</h2>
|
||
<p className="text-lg text-slate-500 mb-8">
|
||
Every SAT graphic question tests the same skill: does the data
|
||
directly prove the claim? Master these four rules before anything
|
||
else.
|
||
</p>
|
||
|
||
{/* Rule Grid */}
|
||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-8">
|
||
<div className="rounded-2xl p-6 bg-amber-50 border border-amber-200 space-y-2">
|
||
<div className="flex items-center gap-2 mb-1">
|
||
<span className="w-7 h-7 rounded-full bg-amber-600 text-white flex items-center justify-center text-xs font-bold shrink-0">
|
||
1
|
||
</span>
|
||
<p className="text-sm font-bold text-amber-900">
|
||
Read the Title First
|
||
</p>
|
||
</div>
|
||
<p className="text-sm text-slate-700 leading-relaxed">
|
||
The title tells you what variable is being measured, the time
|
||
frame, and the units. Read it before looking at data points.
|
||
</p>
|
||
</div>
|
||
<div className="rounded-2xl p-6 bg-amber-50 border border-amber-200 space-y-2">
|
||
<div className="flex items-center gap-2 mb-1">
|
||
<span className="w-7 h-7 rounded-full bg-amber-600 text-white flex items-center justify-center text-xs font-bold shrink-0">
|
||
2
|
||
</span>
|
||
<p className="text-sm font-bold text-amber-900">
|
||
Identify Axes and Units
|
||
</p>
|
||
</div>
|
||
<p className="text-sm text-slate-700 leading-relaxed">
|
||
X-axis (horizontal) = independent variable (often time or
|
||
category). Y-axis (vertical) = measured value. Always check
|
||
units (%, count, dollars, etc.).
|
||
</p>
|
||
</div>
|
||
<div className="rounded-2xl p-6 bg-amber-50 border border-amber-200 space-y-2">
|
||
<div className="flex items-center gap-2 mb-1">
|
||
<span className="w-7 h-7 rounded-full bg-amber-600 text-white flex items-center justify-center text-xs font-bold shrink-0">
|
||
3
|
||
</span>
|
||
<p className="text-sm font-bold text-amber-900">
|
||
Look for Trends, Not Just Values
|
||
</p>
|
||
</div>
|
||
<p className="text-sm text-slate-700 leading-relaxed">
|
||
SAT questions often ask about overall trends
|
||
(increasing/decreasing) or comparisons between categories, not
|
||
single data points.
|
||
</p>
|
||
</div>
|
||
<div className="rounded-2xl p-6 bg-amber-50 border border-amber-200 space-y-2">
|
||
<div className="flex items-center gap-2 mb-1">
|
||
<span className="w-7 h-7 rounded-full bg-amber-600 text-white flex items-center justify-center text-xs font-bold shrink-0">
|
||
4
|
||
</span>
|
||
<p className="text-sm font-bold text-amber-900">
|
||
The Claim Must Match the Data Exactly
|
||
</p>
|
||
</div>
|
||
<p className="text-sm text-slate-700 leading-relaxed">
|
||
A claim is 'supported' only if the data directly proves it.
|
||
'Contradicted' if the data proves the opposite. 'Neither' if the
|
||
data is irrelevant or insufficient.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Static Annotation Visual */}
|
||
<div className="rounded-2xl p-6 mb-6 bg-amber-50 border border-amber-200 space-y-4">
|
||
<h3 className="text-base font-bold text-amber-900 mb-2">
|
||
How to Evaluate a Claim Against a Graph
|
||
</h3>
|
||
<div className="rounded-xl p-4 bg-amber-100 border border-amber-200">
|
||
<p className="text-xs font-bold text-amber-800 uppercase tracking-wider mb-1">
|
||
Graph Context
|
||
</p>
|
||
<p className="text-sm text-slate-800">
|
||
Graph title: "Annual Carbon Emissions by Sector (2000–2020)"
|
||
</p>
|
||
</div>
|
||
<div className="rounded-xl p-4 bg-green-100 border border-green-200">
|
||
<p className="text-xs font-bold text-green-800 uppercase tracking-wider mb-1">
|
||
Supported Claim
|
||
</p>
|
||
<p className="text-sm text-slate-800">
|
||
"Transportation emissions increased between 2000 and 2020" — if
|
||
the line goes up, this is directly proven.
|
||
</p>
|
||
</div>
|
||
<div className="rounded-xl p-4 bg-orange-100 border border-orange-200">
|
||
<p className="text-xs font-bold text-orange-800 uppercase tracking-wider mb-1">
|
||
Neither-Proven Claim
|
||
</p>
|
||
<p className="text-sm text-slate-800">
|
||
"Electric vehicles caused the transportation increase" — the
|
||
graph shows the trend, not the cause. Causation requires
|
||
additional data.
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
{/* Trap Callout */}
|
||
<div className="rounded-2xl p-5 mb-6 bg-red-50 border border-red-200">
|
||
<p className="text-xs font-bold text-red-700 uppercase tracking-wider mb-2">
|
||
Common Trap
|
||
</p>
|
||
<p className="text-sm text-slate-700 leading-relaxed">
|
||
The biggest graphic display trap: a claim that is{" "}
|
||
<span className="font-bold text-red-800">PLAUSIBLE</span> and
|
||
consistent with real-world knowledge but is{" "}
|
||
<span className="font-bold text-red-800">
|
||
NOT proven by this specific graph
|
||
</span>
|
||
. The graph must be sufficient to prove or disprove the claim on
|
||
its own.
|
||
</p>
|
||
</div>
|
||
|
||
{/* Golden Rule */}
|
||
<div className="rounded-2xl p-5 mb-8 bg-amber-900 text-white">
|
||
<p className="text-xs font-bold text-amber-300 uppercase tracking-wider mb-2">
|
||
Golden Rule
|
||
</p>
|
||
<p className="text-sm leading-relaxed">
|
||
Only use what's on the graphic. Outside knowledge, reasonable
|
||
assumptions, and probable causes are all off-limits. The data
|
||
either proves it, disproves it, or doesn't address it.
|
||
</p>
|
||
</div>
|
||
|
||
<button
|
||
onClick={() => scrollToSection(1)}
|
||
className="mt-4 group flex items-center text-amber-600 font-bold hover:text-amber-800 transition-colors"
|
||
>
|
||
Next: Data Claim Lab{" "}
|
||
<ArrowDown className="ml-2 w-5 h-5 group-hover:translate-y-1 transition-transform" />
|
||
</button>
|
||
</section>
|
||
|
||
{/* SECTION 1: Data Claim Lab */}
|
||
<section
|
||
ref={(el) => {
|
||
sectionsRef.current[1] = el;
|
||
}}
|
||
className="min-h-screen flex flex-col justify-center mb-24"
|
||
>
|
||
<div className="inline-flex items-center gap-2 bg-amber-100 text-amber-700 px-3 py-1 rounded-full text-xs font-bold uppercase tracking-wider mb-4">
|
||
Interactive Practice
|
||
</div>
|
||
<h2 className="text-4xl font-extrabold text-slate-900 mb-2">
|
||
Data Claim Lab
|
||
</h2>
|
||
<p className="text-lg text-slate-500 mb-8">
|
||
Read each dataset, then judge whether each claim is supported,
|
||
contradicted, or neither proven by the data.
|
||
</p>
|
||
|
||
<DataClaimWidget exercises={DATA_EXERCISES} accentColor="amber" />
|
||
|
||
<button
|
||
onClick={() => scrollToSection(2)}
|
||
className="mt-12 group flex items-center text-amber-600 font-bold hover:text-amber-800 transition-colors"
|
||
>
|
||
Next: Practice Quiz{" "}
|
||
<ArrowDown className="ml-2 w-5 h-5 group-hover:translate-y-1 transition-transform" />
|
||
</button>
|
||
</section>
|
||
|
||
{/* SECTION 2: Practice Quiz */}
|
||
<section
|
||
ref={(el) => {
|
||
sectionsRef.current[2] = el;
|
||
}}
|
||
className="min-h-screen flex flex-col justify-center mb-24"
|
||
>
|
||
<h2 className="text-4xl font-extrabold text-slate-900 mb-6">
|
||
Practice Quiz
|
||
</h2>
|
||
{COMMAND_EVIDENCE_EASY.slice(2, 4).map((q) => (
|
||
<PracticeFromDataset key={q.id} question={q} color="teal" />
|
||
))}
|
||
{COMMAND_EVIDENCE_MEDIUM.slice(1, 2).map((q) => (
|
||
<PracticeFromDataset key={q.id} question={q} color="teal" />
|
||
))}
|
||
<div className="mt-8 text-center">
|
||
<button
|
||
onClick={onFinish}
|
||
className="px-6 py-3 bg-amber-900 text-white font-bold rounded-full hover:bg-amber-700 transition-colors"
|
||
>
|
||
Finish Lesson
|
||
</button>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default EBRWGraphicDisplaysLesson;
|