YEON PLANNING · 직관수학 (초6)

여러 가지 그래프 — 4단계 문제은행

영상으로 배우고 → 직접 풀고 → 답 제출 → 해설. 원·띠는 비율, 막대는 개수, 꺾은선은 흐름 — 전체가 얼마인지부터 봐요.

✍️ 연플래닝 오리지널 — 「아하! 보이는 직관수학」 자체 제작. 모든 문제·정답 손검산 완료. 답안을 제출해야 해설·정답이 열립니다(먼저 스스로 풀어 보세요).

💬 더 필요한 게 있나요?

난이도 조절(더 쉽게 / 더 어렵게) · 다른 유형 · 특정 개념 집중 · 문항 수 등 무엇이든 적어 주세요. 선생님이 확인합니다. (공개 아님)
✏️ 손으로 풀어보세요
`; return s; } // ── 원그래프 / 띠그래프 ── function pchart(cfg){ const {kind='원', labels=[], vals=[], note='', W=260, H=240} = cfg; const COL=['#2D5A68','#C0503D','#7B4FA8','#5B9279','#D99A4E','#8A8F98']; const tot=vals.reduce((a,b)=>a+b,0); let s=``; if(kind==='원'){ const cx=W/2, cy=104, R=68; let acc=-90; vals.forEach((v,i)=>{ const sw=v/tot*360, a1=acc*Math.PI/180, a2=(acc+sw)*Math.PI/180, big=sw>180?1:0; s+=``; const am=(acc+sw/2)*Math.PI/180; if(sw>=26) s+=`${Math.round(v/tot*100)}%`; acc+=sw; }); s+=``; } else { const x0=22, y0=72, BW=W-44, BH=44; let acc=0; vals.forEach((v,i)=>{ const w=v/tot*BW; s+=``; if(w>=30) s+=`${Math.round(v/tot*100)}%`; acc+=w; }); s+=``; for(let p=0;p<=100;p+=10){ const x=x0+BW*p/100; s+=``; if(p%20===0) s+=`${p}`; } } // 띠그래프: 눈금 숫자(y=y0+BH+17=133)와 겹치지 않게 범례를 아래로 내린다 const ly=kind==='원'?190:158; labels.forEach((L,i)=>{ const col=i%2, row=Math.floor(i/2), lx=26+col*118, y=ly+row*19; s+=``; s+=`${L}`; }); if(note) s+=`${note}`; s+=``; return s; } const P=[ { tier:'기초', type:'self', kind:'choice', q:'전체를 으로 그려 각 부분이 차지하는 비율을 부채꼴로 나타낸 그래프는?', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'좋아하는 운동'}), choices:['원그래프','띠그래프','막대그래프','꺾은선그래프'], answer:'원그래프', hint:'원그래프의 부채꼴 크기가 곧 비율이에요.', sol:{ ans:'원그래프', fig:null, steps:['전체를 원 하나로 보고 부채꼴로 나눈 그래프.','= 원그래프.','전체 중 몇 %인지가 한눈에 보여요!']}}, { tier:'기초', type:'self', kind:'choice', q:'전체를 가로 띠로 그려 비율을 나타낸 그래프는?', fig:pchart({kind:'띠', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'좋아하는 운동'}), choices:['띠그래프','원그래프','막대그래프','꺾은선그래프'], answer:'띠그래프', hint:'원그래프의 부채꼴 크기가 곧 비율이에요.', sol:{ ans:'띠그래프', fig:null, steps:['전체를 긴 띠 하나로 보고 나눈 그래프.','= 띠그래프.','여러 해를 위아래로 나란히 놓고 비교하기 좋아요!']}}, { tier:'기초', type:'self', kind:'num', q:'원그래프에서 축구가 차지하는 비율은 몇 %% 일까요?', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'좋아하는 운동'}), answer:40, hint:'원그래프의 부채꼴 크기가 곧 비율이에요.', sol:{ ans:'40', fig:null, steps:['축구 부채꼴에 40%라고 적혀 있어요.','가장 큰 부채꼴이에요.','원그래프는 부채꼴 크기가 곧 비율이에요!']}}, { tier:'기초', type:'self', kind:'num', q:'원그래프에서 수영은 몇 %% 일까요?', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'좋아하는 운동'}), answer:15, hint:'원그래프의 부채꼴 크기가 곧 비율이에요.', sol:{ ans:'15', fig:null, steps:['수영 부채꼴은 15%.','가장 작은 부채꼴이에요.','작은 부채꼴 = 작은 비율!']}}, { tier:'기초', type:'self', kind:'num', q:'원그래프의 모든 부분을 더하면 몇 %% 일까요?', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'좋아하는 운동'}), answer:100, hint:'원그래프의 부채꼴 크기가 곧 비율이에요.', sol:{ ans:'100', fig:null, steps:['40 + 25 + 20 + 15 = 100%.','원 전체가 100%예요.','합이 100%가 아니면 뭔가 빠진 거예요 — 꼭 확인하세요!']}}, { tier:'기초', type:'self', kind:'choice', q:'가장 많은 학생이 좋아하는 운동은?', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'좋아하는 운동'}), choices:['축구','농구','야구','수영'], answer:'축구', hint:'원그래프의 부채꼴 크기가 곧 비율이에요.', sol:{ ans:'축구', fig:null, steps:['부채꼴이 가장 것을 찾아요.','축구 40% — 가장 커요.','축구예요!']}}, { tier:'기초', type:'self', kind:'choice', q:'가장 적은 학생이 좋아하는 운동은?', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'좋아하는 운동'}), choices:['축구','농구','야구','수영'], answer:'수영', hint:'원그래프의 부채꼴 크기가 곧 비율이에요.', sol:{ ans:'수영', fig:null, steps:['부채꼴이 가장 작은 것.','수영 15% — 가장 작아요.','수영이에요!']}}, { tier:'기초', type:'self', kind:'num', q:'원그래프에서 절반을 차지하는 부채꼴은 몇 %% 일까요?', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'좋아하는 운동'}), answer:50, hint:'원그래프의 부채꼴 크기가 곧 비율이에요.', sol:{ ans:'50', fig:null, steps:['원 전체 = 100%.','절반 = 100 ÷ 2 = 50%.','절반이면 180° 부채꼴이에요!']}}, { tier:'기초', type:'self', kind:'choice', q:'띠그래프와 원그래프의 공통점은?', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'좋아하는 운동'}), choices:['비율을 나타낸다','시간 변화를 본다','개수를 센다','알 수 없다'], answer:'비율을 나타낸다', hint:'원그래프의 부채꼴 크기가 곧 비율이에요.', sol:{ ans:'비율을 나타낸다', fig:null, steps:['둘 다 전체를 100%로 보고 나눠요.','둘 다 비율(전체 중 몇 %)을 보여줘요.','모양만 다를 뿐 하는 일은 같아요!']}}, { tier:'기초', type:'self', kind:'num', q:'원그래프에서 축구수영보다 몇 배 많을까요? (야구와 비교)', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'좋아하는 운동'}), answer:2, hint:'원그래프의 부채꼴 크기가 곧 비율이에요.', sol:{ ans:'2', fig:null, steps:['축구 40%, 수영 15%… 40 ÷ 15 는 딱 안 떨어지네요.','대신 농구 25%와 수영 15%를 보면… 아니, 축구 40%와 야구 20%를 비교해요!','40 ÷ 20 = 2배. 축구는 야구의 2배예요!']}}, { tier:'중급', type:'self', kind:'num', q:'전체 200명 중 축구를 좋아하는 학생은 몇 명일까요? (축구 = 40%)', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'전체 200명일 때'}), answer:80, hint:'전체 × 비율!', sol:{ ans:'80명', fig:null, steps:['축구 = 40% = 40/100.','200 × 40 ÷ 100 = 80명.','비율에서 실제 수를 구할 땐 전체를 곱해요!']}}, { tier:'중급', type:'self', kind:'num', q:'전체 400명 중 축구를 좋아하는 학생은 몇 명일까요? (축구 = 40%)', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'전체 400명일 때'}), answer:160, hint:'전체 × 비율!', sol:{ ans:'160명', fig:null, steps:['축구 = 40% = 40/100.','400 × 40 ÷ 100 = 160명.','비율에서 실제 수를 구할 땐 전체를 곱해요!']}}, { tier:'중급', type:'self', kind:'num', q:'전체 200명 중 농구를 좋아하는 학생은 몇 명일까요? (농구 = 25%)', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'전체 200명일 때'}), answer:50, hint:'전체 × 비율!', sol:{ ans:'50명', fig:null, steps:['농구 = 25% = 25/100.','200 × 25 ÷ 100 = 50명.','비율에서 실제 수를 구할 땐 전체를 곱해요!']}}, { tier:'중급', type:'self', kind:'num', q:'전체 400명 중 농구를 좋아하는 학생은 몇 명일까요? (농구 = 25%)', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'전체 400명일 때'}), answer:100, hint:'전체 × 비율!', sol:{ ans:'100명', fig:null, steps:['농구 = 25% = 25/100.','400 × 25 ÷ 100 = 100명.','비율에서 실제 수를 구할 땐 전체를 곱해요!']}}, { tier:'중급', type:'self', kind:'num', q:'전체 200명 중 야구를 좋아하는 학생은 몇 명일까요? (야구 = 20%)', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'전체 200명일 때'}), answer:40, hint:'전체 × 비율!', sol:{ ans:'40명', fig:null, steps:['야구 = 20% = 20/100.','200 × 20 ÷ 100 = 40명.','비율에서 실제 수를 구할 땐 전체를 곱해요!']}}, { tier:'중급', type:'self', kind:'num', q:'전체 400명 중 야구를 좋아하는 학생은 몇 명일까요? (야구 = 20%)', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'전체 400명일 때'}), answer:80, hint:'전체 × 비율!', sol:{ ans:'80명', fig:null, steps:['야구 = 20% = 20/100.','400 × 20 ÷ 100 = 80명.','비율에서 실제 수를 구할 땐 전체를 곱해요!']}}, { tier:'중급', type:'self', kind:'num', q:'전체 200명 중 수영를 좋아하는 학생은 몇 명일까요? (수영 = 15%)', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'전체 200명일 때'}), answer:30, hint:'전체 × 비율!', sol:{ ans:'30명', fig:null, steps:['수영 = 15% = 15/100.','200 × 15 ÷ 100 = 30명.','비율에서 실제 수를 구할 땐 전체를 곱해요!']}}, { tier:'중급', type:'self', kind:'num', q:'전체 400명 중 수영를 좋아하는 학생은 몇 명일까요? (수영 = 15%)', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'전체 400명일 때'}), answer:60, hint:'전체 × 비율!', sol:{ ans:'60명', fig:null, steps:['수영 = 15% = 15/100.','400 × 15 ÷ 100 = 60명.','비율에서 실제 수를 구할 땐 전체를 곱해요!']}}, { tier:'중급', type:'self', kind:'num', q:'전체 200명일 때 축구와 농구를 좋아하는 학생을 합하면 몇 명일까요?', fig:null, answer:130, hint:'40% + 25% = 65%. 200의 65%는?', sol:{ ans:'[「축구 40% + 농구 25% = 65%.」, 「200 × 65 ÷ 100 = 130명.」, 「(축구 80명 + 농구 50명 = 130명 — 같은 답이죠!)」]', fig:null, steps:['p','c','h','a','r','t','(','{','k','i','n','d',':','’','원','’',',',' ','l','a','b','e','l','s',':','[','’','축','구','’',',','’','농','구','’',',','’','야','구','’',',','’','수','영','’',']',',',' ','v','a','l','s',':','[','4','0',',','2','5',',','2','0',',','1','5',']',',',' ','n','o','t','e',':','’','축','구',' ','+',' ','농','구','는','?','’','}',')']}}, { tier:'중급', type:'self', kind:'num', q:'전체 200명일 때 야구를 좋아하는 학생은 수영보다 몇 명 많을까요?', fig:null, answer:10, hint:'20% − 15% = 5%. 200의 5%는?', sol:{ ans:'[「야구 20%, 수영 15% → 차이 5%.」, 「200 × 5 ÷ 100 = 10명.」, 「(야구 40명 − 수영 30명 = 10명 ✓)」]', fig:null, steps:['p','c','h','a','r','t','(','{','k','i','n','d',':','’','원','’',',',' ','l','a','b','e','l','s',':','[','’','축','구','’',',','’','농','구','’',',','’','야','구','’',',','’','수','영','’',']',',',' ','v','a','l','s',':','[','4','0',',','2','5',',','2','0',',','1','5',']',',',' ','n','o','t','e',':','’','야','구','와',' ','수','영','의',' ','차','는','?','’','}',')']}}, { tier:'상위', type:'self', kind:'num', q:'원그래프에서 40%% 인 부채꼴의 중심각은 몇 도일까요?', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'좋아하는 운동'}), answer:144, hint:'원 한 바퀴 = 360°. 그중 40%는?', sol:{ ans:'144', fig:null, steps:['원 한 바퀴 = 360°.','40% = 360 × 40 ÷ 100.','= 144°. 비율만큼 각도를 나눠 가져요!']}}, { tier:'상위', type:'self', kind:'num', q:'25%% 인 부채꼴의 중심각은 몇 도일까요?', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'좋아하는 운동'}), answer:90, hint:'360의 25%는?', sol:{ ans:'90', fig:null, steps:['360 × 25 ÷ 100 = 90°.','25% = 4분의 1 → 360 ÷ 4 = 90°.','딱 직각이에요!']}}, { tier:'상위', type:'self', kind:'num', q:'50%% 인 부채꼴의 중심각은?', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'좋아하는 운동'}), answer:180, hint:'절반이면?', sol:{ ans:'180', fig:null, steps:['360 × 50 ÷ 100 = 180°.','절반 = 평각.','반원이 되죠!']}}, { tier:'상위', type:'self', kind:'num', q:'중심각이 72° 인 부채꼴은 몇 %% 일까요?', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'좋아하는 운동'}), answer:20, hint:'72 ÷ 360 × 100 = ?', sol:{ ans:'20', fig:null, steps:['72 ÷ 360 = 0.2.','0.2 × 100 = 20%.','각도에서 거꾸로 비율을 구할 수도 있어요!']}}, { tier:'상위', type:'self', kind:'num', q:'띠그래프에서 전체 길이가 20 cm 일 때 40%% 인 부분의 길이는?', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'좋아하는 운동'}), answer:8, hint:'20의 40%는?', sol:{ ans:'8', fig:null, steps:['전체 띠 = 20 cm = 100%.','20 × 40 ÷ 100 = 8 cm.','띠그래프는 길이가 비율이에요! (원그래프는 각도)']}}, { tier:'상위', type:'self', kind:'choice', q:'여러 해의 비율 변화를 비교하기에 좋은 그래프는?', fig:null, choices:['띠그래프','원그래프','막대그래프','꺾은선그래프'], answer:'띠그래프', hint:'원그래프 5개를 나란히 놓는 것과 띠 5개를 위아래로 놓는 것 — 어느 쪽이 비교하기 쉬울까요?', sol:{ ans:'띠그래프', fig:null, steps:['원그래프는 한 해의 비율을 보기엔 좋아요.','하지만 여러 해를 비교하려면 원을 여러 개 그려야 해서 눈이 어지러워요.','띠그래프는 위아래로 나란히 놓아 같은 자리끼리 비교하기 쉬워요!']}}, { tier:'상위', type:'self', kind:'choice', q:'전체 개수를 한눈에 비교하기 좋은 그래프는?', fig:null, choices:['막대그래프','원그래프','띠그래프','꺾은선그래프'], answer:'막대그래프', hint:'원그래프는 비율만 보여줘요. 실제 개수는?', sol:{ ans:'막대그래프', fig:null, steps:['원그래프·띠그래프는 비율(전체 중 몇 %)만 보여줘요.','실제 개수의 많고 적음은 막대그래프가 잘 보여줘요.','무엇을 보고 싶은지에 따라 그래프를 골라요!']}}, { tier:'상위', type:'self', kind:'choice', q:'시간에 따른 변화를 보기 좋은 그래프는?', fig:null, choices:['꺾은선그래프','막대그래프','원그래프','띠그래프'], answer:'꺾은선그래프', hint:'기온이 어떻게 변해 왔는지 — 어느 그래프일까요?', sol:{ ans:'꺾은선그래프', fig:null, steps:['막대그래프 = 많고 적음 비교.','원·띠그래프 = 비율.','꺾은선그래프 = 시간에 따른 변화의 흐름! 목적에 맞는 그래프를 골라야 해요.']}}, { tier:'상위', type:'self', kind:'choice', q:'A학교(1000명)의 축구 팬 40%% 와 B학교(200명)의 축구 팬 50%% 중 사람 수가 많은 곳은?', fig:null, choices:['A학교','B학교','같다','알 수 없다'], answer:'A학교', hint:'퍼센트만 보면 B가 크지만, 전체가 다르죠! 실제 사람 수를 구해 보세요.', sol:{ ans:'A학교', fig:null, steps:['A학교: 1000 × 0.4 = 400명.','B학교: 200 × 0.5 = 100명.','비율은 B가 높지만 사람 수는 A가 4배! ⚠️ 퍼센트만 보면 속아요 — 전체가 얼마인지 꼭 봐야 해요.']}}, { tier:'상위', type:'self', kind:'choice', q:'원그래프의 부채꼴이 커 보인다고 사람 수도 많을까요?', fig:pchart({kind:'원', labels:['축구','농구','야구','수영'], vals:[40,25,20,15], note:'좋아하는 운동'}), choices:['그렇다','아니다','전체를 알아야 안다','알 수 없다'], answer:'아니다', hint:'전체가 몇 명인지 모르면요?', sol:{ ans:'아니다', fig:null, steps:['부채꼴 크기 = 비율(전체 중 몇 %).','전체가 10명이면 50%라도 5명뿐이에요.','전체가 얼마인지 모르면 실제 수는 알 수 없어요! 비율과 실제 수는 다른 이야기예요.']}}, { tier:'최상위', type:'self', kind:'choice', q:'전체 200명 중 축구 팬이 40%% → 이듬해 전체 400명 중 35%% 가 되었습니다. 축구 팬 는?', fig:null, choices:['늘었다','줄었다','그대로다','알 수 없다'], answer:'늘었다', hint:'비율은 줄었지만 전체가 2배가 됐어요! 실제 수를 계산해 보세요.', sol:{ ans:'늘었다', fig:null, steps:['작년: 200 × 0.4 = 80명.','올해: 400 × 0.35 = 140명.','비율은 40% → 35%로 줄었는데 사람은 80 → 140명으로 늘었어요! 전체가 커졌으니까요.']}}, { tier:'최상위', type:'self', kind:'choice', q:'원그래프에서 항목을 합쳐서 그리면 무엇을 잃을까요?', fig:null, choices:['자세한 내용','전체 개수','정확한 비율','아무것도'], answer:'자세한 내용', hint:'「기타 30%」로 묶으면 그 안에 뭐가 있는지 알 수 있나요?', sol:{ ans:'자세한 내용', fig:null, steps:['여러 작은 항목을 「기타」로 묶으면 그래프는 깔끔해져요.','하지만 그 안에 무엇이 얼마나 있는지 알 수 없어요.','⚠️ 그래프는 보여주는 만큼 감추기도 해요 — 무엇이 묶였는지 봐야 해요!']}}, { tier:'최상위', type:'self', kind:'choice', q:'설문에 10명만 답했는데 「80%가 찬성!」이라고 하면 믿을 만할까요?', fig:null, choices:['그렇다','아니다','80%면 믿는다','알 수 없다'], answer:'아니다', hint:'10명 중 8명이에요. 전교생 1000명의 뜻일까요?', sol:{ ans:'아니다', fig:null, steps:['10명 중 8명 = 80% — 계산은 맞아요.','하지만 10명은 너무 적어요.','몇 명에게 물었는지(전체)를 봐야 해요! 퍼센트가 커도 바탕이 작으면 믿기 어려워요.']}}, { tier:'최상위', type:'self', kind:'choice', q:'원그래프의 부채꼴을 입체(3D)로 그리면 어떤 문제가 생길까요?', fig:null, choices:['앞쪽이 커 보인다','뒤쪽이 커 보인다','똑같다','알 수 없다'], answer:'앞쪽이 커 보인다', hint:'비스듬히 누운 원그래프에서 앞쪽 조각은 어떻게 보일까요?', sol:{ ans:'앞쪽이 커 보인다', fig:null, steps:['3D로 비스듬히 그리면 앞쪽 조각이 두껍게 보여요.','실제 비율은 같은데 앞쪽이 더 커 보여요.','⚠️ 그래서 정확한 비교엔 평면 원그래프가 나아요! 예뻐 보이는 게 정확한 건 아니에요.']}}, { tier:'최상위', type:'self', kind:'choice', q:'띠그래프에서 각 부분의 길이가 뜻하는 것은?', fig:null, choices:['비율','개수','시간','알 수 없다'], answer:'비율', hint:'띠 전체가 100%면 그 안의 길이는?', sol:{ ans:'비율', fig:null, steps:['띠 전체 = 100%.','각 부분의 길이가 그 항목의 비율.','원그래프는 각도로, 띠그래프는 길이로 — 표현만 다르고 뜻은 같아요!']}}, { tier:'최상위', type:'self', kind:'choice', q:'40%%, 25%%, 20%%, 15%% 를 띠그래프 20 cm 에 그리면 각 길이는 순서대로?', fig:null, choices:['8, 5, 4, 3','4, 5, 8, 3','10, 5, 3, 2','8, 4, 5, 3'], answer:'8, 5, 4, 3', hint:'20 cm 의 40%, 25%, 20%, 15% 를 각각 구하세요.', sol:{ ans:'8, 5, 4, 3', fig:null, steps:['20 × 0.4 = 8, 20 × 0.25 = 5, 20 × 0.2 = 4, 20 × 0.15 = 3 (cm).','합: 8 + 5 + 4 + 3 = 20 cm ✓ (전체와 딱 맞아요)','8, 5, 4, 3 cm! 합이 전체 길이와 맞는지 꼭 확인하세요.']}}, { tier:'최상위', type:'self', kind:'choice', q:'원그래프를 그릴 때 가장 큰 항목부터 그리는 이유는?', fig:null, choices:['보기 쉬워서','계산이 쉬워서','규칙이라서','알 수 없다'], answer:'보기 쉬워서', hint:'크기 순서 없이 뒤죽박죽이면 어떨까요?', sol:{ ans:'보기 쉬워서', fig:null, steps:['큰 것부터 차례로 그리면 순서가 한눈에 보여요.','뒤죽박죽이면 어느 게 큰지 눈으로 비교해야 해요.','보기 쉬우라고 정한 약속이에요! (수학적으로 꼭 그래야 하는 건 아니에요)']}}, { tier:'최상위', type:'self', kind:'choice', q:'그래프를 볼 때 가장 먼저 확인해야 할 것은?', fig:null, choices:['전체가 얼마인가','색깔','제목 길이','알 수 없다'], answer:'전체가 얼마인가', hint:'40%라고 할 때 무엇을 모르면 뜻이 없을까요?', sol:{ ans:'전체가 얼마인가', fig:null, steps:['「40%」만으로는 몇 명인지 알 수 없어요.','전체가 10명이면 4명, 1000명이면 400명 — 천지 차이.','그래프를 볼 땐 전체(기준량)가 얼마인가를 먼저 봐야 해요!']}}, { tier:'최상위', type:'self', kind:'choice', q:'같은 자료를 원그래프와 막대그래프로 그리면 결과가 다를까요?', fig:null, choices:['그렇다','아니다','80%면 믿는다','알 수 없다'], answer:'아니다', hint:'표현 방법만 다른 거예요. 자료는 같죠?', sol:{ ans:'아니다', fig:null, steps:['같은 자료를 다르게 표현한 것뿐이에요.','자료가 같으니 사실도 같아요.','다만 무엇이 잘 보이느냐가 달라요 — 원은 비율, 막대는 개수가 잘 보여요!']}}, { tier:'최상위', type:'self', kind:'choice', q:'그래프가 거짓말을 할 수 있는 이유는?', fig:null, choices:['눈금·기준을 바꿀 수 있어서','숫자가 틀려서','색이 많아서','알 수 없다'], answer:'눈금·기준을 바꿀 수 있어서', hint:'세로축을 0이 아니라 중간부터 그리면 어땠나요?', sol:{ ans:'눈금·기준을 바꿀 수 있어서', fig:null, steps:['세로축을 0이 아닌 곳에서 시작하면 차이가 과장돼 보여요.','3D 원그래프는 앞쪽이 커 보이고, 전체를 안 밝히면 퍼센트가 부풀려져요.','자료는 사실이어도 그리는 방법으로 인상을 바꿀 수 있어요 — 그래서 눈금·기준을 꼭 확인해야 해요!']}}, ]; const TIERS=['기초','중급','상위','최상위']; const TIER_DESC={기초:'영상만 봐도 바로 풀려요 — 배운 걸 그대로 적용.',중급:'한 번 더 생각 — 거꾸로·변형. 영상 안에 답이 있어요.',상위:'아래 학년 개념(선수 단원)을 함께 써야 풀려요.',최상위:'여러 개념·역발상·함정까지. 최고 난도.'}; let curTier='기초'; function tierProblems(t){ return P.map((p,i)=>({p,i})).filter(o=>o.p.tier===t); } function renderTabs(){ const tb=document.getElementById('tabs'); tb.innerHTML=''; TIERS.forEach(t=>{ const n=tierProblems(t).length; const b=document.createElement('button'); b.className='tab'+(t===curTier?' on':''); b.textContent=`${t} (${n})`; b.onclick=()=>{curTier=t; renderTabs(); renderList();}; tb.appendChild(b); }); document.getElementById('tierNote').textContent=TIER_DESC[curTier]; } function esc(x){return String(x).replace(/&/g,'&').replace(//g,'>');} function renderList(){ const L=document.getElementById('list'); L.innerHTML=''; const items=tierProblems(curTier); if(!items.length){ L.innerHTML='
이 난도는 곧 채워집니다 — 파일럿은 기초·중급·상위 예시.
'; return; } items.forEach(({p,i},k)=>{ const badge = p.type==='video' ? '🎬 영상해설' : '✍ 텍스트해설'; const pre = p.prereq ? `🔗 ${p.prereq.name}` : ''; const c=document.createElement('div'); c.className='card'; c.id='card'+i; let ansUI = p.kind==='choice' ? `
`+p.choices.map(o=>``).join('')+`
` : `
← 내 답을 쓰고 제출
`; c.innerHTML=`
${curTier} · 문제 ${k+1} ${badge} ${pre}
${mfx(p.q)}
${p.fig?`
${p.fig}
`:''} ${ansUI}
🔒 답을 제출해야 해설·정답이 열려요.
💡 힌트 — ${p.hint}
`; L.appendChild(c); }); } const picked={}; // 분수 답 입력 지원: '3/4', '1 1/2', '0.75' 모두 인식 function parseAns(v){ v=String(v).trim().replace(/\s+/g,' '); let m=/^(-?\d+)\s+(\d+)\/(\d+)$/.exec(v); if(m){ const s=(+m[1])<0?-1:1; return s*(Math.abs(+m[1])+(+m[2])/(+m[3])); } m=/^(-?\d+)\/(-?\d+)$/.exec(v); if(m) return (+m[1])/(+m[2]); return parseFloat(v.replace(/[^0-9.\-]/g,'')); } function pick(i,val,el){ picked[i]=val; document.querySelectorAll('#ch'+i+' button').forEach(b=>b.classList.remove('sel')); el.classList.add('sel'); } function mfx(t){ if(!window.mathToHTML) return t; // HTML 태그( 등)는 그대로 두고, 태그 사이 텍스트만 교과서식 수식으로 변환 return String(t).split(/(<[^>]+>)/).map(s=> s.charAt(0)==='<' ? s : mathToHTML(s)).join(''); } function submit(i){ const p=P[i]; let mine; if(p.kind==='choice'){ mine=picked[i]; if(mine==null){ alert('보기 중 하나를 먼저 고르세요.'); return; } } else { const v=document.getElementById('in'+i).value.trim(); if(v===''){ alert('답을 먼저 입력하세요.'); return; } mine=parseAns(v); if(isNaN(mine)){ alert('숫자나 분수(예: 3/4)로 입력해 주세요.'); return; } } const correct = p.kind==='choice' ? (mine===p.answer) : (Math.abs(mine-p.answer)<1e-6); const vd=document.getElementById('vd'+i); vd.classList.remove('hide'); document.getElementById('lock'+i).classList.add('hide'); document.getElementById('show'+i).classList.remove('hide'); // 제출했으니 해설 열람 가능 if(correct){ vd.className='verdict ok'; vd.innerHTML='✅ 정답이에요! 잘했어요.'; reveal(i); } else{ vd.className='verdict no'; vd.innerHTML='❌ 아쉬워요. 힌트를 보고 다시 풀어 볼까요? (해설도 열렸어요)'; document.getElementById('hint'+i).classList.remove('hide'); } } function reveal(i){ const p=P[i], sol=document.getElementById('sol'+i); sol.classList.remove('hide'); let steps=p.sol.steps.map(s=>`
• ${mfx(s)}
`).join(''); let pre=p.prereq?`
🔗 이 문제는 ${p.prereq.name} 개념이 필요해요 — 그 단원 보러 가기 →
`:''; let vsol = p.type==='video' ? `🎬 이 문제 영상 해설 보기 (짧게)` : ''; sol.innerHTML=`

📝 해설

${pre}${p.sol.fig?`
${p.sol.fig}
`:''}${steps}
정답: ${mfx(p.sol.ans)}
${vsol}` +`
🙋 이 해설이 어렵거나 더 자세히 알고 싶으면 말씀해주세요 — 상세 해설지를 새로 만들어 보내드릴게요.
` +``; } /* ───────── "이 해설도 어려워요" 체크 → 하단 요청 코너로 모으기 ───────── */ const hardSet=new Set(); function toggleHard(i,on){ on?hardSet.add(i):hardSet.delete(i); syncHard(); } function syncHard(){ const box=document.getElementById('hardList'); if(!box) return; if(!hardSet.size){ box.style.display='none'; box.textContent=''; return; } const names=[...hardSet].sort((a,b)=>a-b).map(i=>{ const list=tierProblems(P[i].tier); const k=list.findIndex(o=>o.i===i); return `${P[i].tier} ${k+1}번`; }); box.style.display='block'; box.innerHTML='🙋 해설이 어렵다고 표시한 문제: '+names.join(', ')+' — 보내기를 누르면 함께 전달돼요.'; } /* ───────── 추가요청 보내기 (선생님 확인용 · 이 기기에 저장) ───────── */ function reqKey(){ return 'pbreq:'+location.pathname; } function loadReq(){ try{ return JSON.parse(localStorage.getItem(reqKey())||'[]'); }catch(e){ return []; } } function nowStr(){ const d=new Date(), p=n=>(n<10?'0':'')+n; return d.getFullYear()+'-'+p(d.getMonth()+1)+'-'+p(d.getDate())+' '+p(d.getHours())+':'+p(d.getMinutes()); } function sendReq(){ const ta=document.getElementById('reqText'), note=document.getElementById('reqNote'); const text=(ta.value||'').trim(); const hard=[...hardSet].sort((a,b)=>a-b).map(i=>{ const list=tierProblems(P[i].tier); const k=list.findIndex(o=>o.i===i); return `${P[i].tier} ${k+1}번`; }); if(!text && !hard.length){ note.style.color='#C0503D'; note.textContent='요청 내용을 적거나, 어려운 해설을 체크해 주세요.'; return; } const arr=loadReq(); arr.push({ date:nowStr(), text, hard, unit:'초6 여러 가지 그래프' }); try{ localStorage.setItem(reqKey(), JSON.stringify(arr)); }catch(e){} ta.value=''; hardSet.clear(); syncHard(); document.querySelectorAll('.retag input').forEach(c=>c.checked=false); note.style.color='#2c8a55'; note.textContent='✅ 보냈어요! 선생님이 확인합니다. (이 기기에 저장됨)'; renderReq(); } function renderReq(){ const box=document.getElementById('reqMine'); if(!box) return; const arr=loadReq(); box.innerHTML=''; if(!arr.length) return; box.innerHTML='
📒 내가 보낸 요청 ('+arr.length+')
' + arr.slice().reverse().map(it=>`
${it.hard&&it.hard.length?'🙋 어려운 해설: '+it.hard.join(', ')+'
':''}${(it.text||'').replace(/(내용 없음)'}
${it.date}
`).join(''); } /* ───────── 인쇄 2모드 — 절약 인쇄(2단·컬러 유지) ───────── */ function ecoPrint(){ document.body.classList.add('eco-print'); window.addEventListener('afterprint', function h(){ document.body.classList.remove('eco-print'); window.removeEventListener('afterprint',h); }); window.print(); } /* ───────── DrawBoard (문항별 손으로 풀기 — 화면 가득 전체화면) ───────── */ const canvas=document.getElementById('drawCanvas'), ctx=canvas.getContext('2d'); const drawOverlay=document.getElementById('drawOverlay'), drawWrap=document.getElementById('drawCanvasWrap'); let drawOn=false, tool='pen', dsize=6, dcolor='#1f2a2a', drawing=false, last=null, currentDrawQ=null; const drawings={}; // i -> dataURL (문항별 손풀이) const photos={}; // i -> dataURL (문항별 사진) function sizeCanvas(restore){ const rect=drawWrap.getBoundingClientRect(), dpr=window.devicePixelRatio||1; canvas.width=Math.round(rect.width*dpr); canvas.height=Math.round(rect.height*dpr); canvas.style.width=rect.width+'px'; canvas.style.height=rect.height+'px'; ctx.setTransform(dpr,0,0,dpr,0,0); ctx.clearRect(0,0,rect.width,rect.height); if(restore){ const img=new Image(); img.onload=()=>ctx.drawImage(img,0,0,rect.width,rect.height); img.src=restore; } } window.addEventListener('resize',()=>{ if(drawOn) sizeCanvas(drawings[currentDrawQ]); }); window.openDraw=function(i){ drawOn=true; currentDrawQ=i; const plain=String(P[i].q).replace(/<[^>]*>/g,''); document.getElementById('drawQref').textContent=P[i].tier+' · '+plain.slice(0,30)+'…'; drawOverlay.classList.add('on'); sizeCanvas(drawings[i]); const el2=document.documentElement, req=el2.requestFullscreen||el2.webkitRequestFullscreen||el2.msRequestFullscreen; if(req){ try{ req.call(el2).catch(()=>{}); }catch(e){} } }; window.closeDraw=function(){ if(currentDrawQ!=null){ const hasInk=(()=>{ const d=ctx.getImageData(0,0,canvas.width,canvas.height).data; for(let k=3;k0) return true; return false; })(); if(hasInk){ drawings[currentDrawQ]=canvas.toDataURL('image/png'); renderThumbs(currentDrawQ); } } drawOn=false; currentDrawQ=null; drawOverlay.classList.remove('on'); if(document.fullscreenElement||document.webkitFullscreenElement){ (document.exitFullscreen||document.webkitExitFullscreen).call(document).catch(()=>{}); } }; window.submitFromDraw=function(){ const i=currentDrawQ; closeDraw(); if(i!=null) submit(i); }; document.addEventListener('fullscreenchange',()=>{ if(!document.fullscreenElement && drawOn) closeDraw(); }); window.setTool=t=>{ tool=t; document.getElementById('toolPen').classList.toggle('on',t==='pen'); document.getElementById('toolErase').classList.toggle('on',t==='erase'); }; window.setSize=s=>{ dsize=s; ['szS','szM','szL'].forEach(id=>document.getElementById(id).classList.remove('on')); document.getElementById(s===3?'szS':s===12?'szL':'szM').classList.add('on'); }; window.setColor=c=>{ dcolor=c; }; window.clearDraw=()=>{ if(confirm('그린 것을 모두 지울까요?')) ctx.clearRect(0,0,canvas.width,canvas.height); }; function dpos(e){ const r=canvas.getBoundingClientRect(), t=e.touches?e.touches[0]:e; return [t.clientX-r.left, t.clientY-r.top]; } function dstart(e){ if(!drawOn) return; e.preventDefault(); drawing=true; last=dpos(e); } function dmove(e){ if(!drawOn||!drawing) return; e.preventDefault(); const p=dpos(e); ctx.lineCap='round'; ctx.lineJoin='round'; if(tool==='erase'){ ctx.globalCompositeOperation='destination-out'; ctx.lineWidth=dsize*4; } else{ ctx.globalCompositeOperation='source-over'; ctx.strokeStyle=dcolor; ctx.lineWidth=dsize; } ctx.beginPath(); ctx.moveTo(last[0],last[1]); ctx.lineTo(p[0],p[1]); ctx.stroke(); last=p; } function dend(){ drawing=false; } canvas.addEventListener('mousedown',dstart); canvas.addEventListener('mousemove',dmove); window.addEventListener('mouseup',dend); canvas.addEventListener('touchstart',dstart,{passive:false}); canvas.addEventListener('touchmove',dmove,{passive:false}); canvas.addEventListener('touchend',dend,{passive:false}); /* ───────── 사진으로 올리기 (문항별) ───────── */ window.onPhoto=function(i,inputEl){ const file=inputEl.files&&inputEl.files[0]; if(!file) return; const reader=new FileReader(); reader.onload=ev=>{ const img=new Image(); img.onload=()=>{ const maxW=900, sc=Math.min(1,maxW/img.width), w=Math.round(img.width*sc), h=Math.round(img.height*sc); const cv=document.createElement('canvas'); cv.width=w; cv.height=h; cv.getContext('2d').drawImage(img,0,0,w,h); photos[i]=cv.toDataURL('image/jpeg',0.6); renderThumbs(i); }; img.src=ev.target.result; }; reader.readAsDataURL(file); inputEl.value=''; }; window.removePhoto=function(i){ delete photos[i]; renderThumbs(i); }; window.removeDrawing=function(i){ delete drawings[i]; renderThumbs(i); }; function renderThumbs(i){ const box=document.getElementById('thumbs'+i); if(!box) return; let h=''; if(drawings[i]) h+=`
손풀이
`; if(photos[i]) h+=`
사진
`; box.innerHTML=h; const db=document.getElementById('drawBtn'+i), pb=document.getElementById('photoBtn'+i); if(db) db.classList.toggle('has', !!drawings[i]); if(pb) pb.classList.toggle('has', !!photos[i]); } // 탭을 바꿔 다시 그려도 그 문항의 손풀이·사진 썸네일이 되살아나게 const _renderList=renderList; renderList=function(){ _renderList(); tierProblems(curTier).forEach(({p,i})=>renderThumbs(i)); }; renderTabs(); renderList(); renderReq();