2026년 9월 6일 일요일

[바이브 코딩] 공정 청소 룰렛 - 이전 주 당번 자동 제외와 주간 히스토리 아카이빙



당번 뽑기 불만을 원천 없애는 공정 룰렛 — 청소 구역 추첨 & 주간 히스토리 아카이빙

🎡 청소 구역(칠판·복도·창틀·쓰레기통) 배정을 룰렛(roulette)으로 바꿉니다. 이전 주 당번은 자동 제외되고, 뽑힌 횟수가 적은 학생이 유리한 균등 추첨(draw)으로 매주 월요일 아침 자치 시간에 전교생이 보는 앞에서 돌아갑니다.

배정 결과는 아카이빙(archiving, 기록 보관) — '주간 기록 CSV 내보내기'로 당번 히스토리를 로컬 파일에 누적합니다(자동 외부 전송 없음). 교사가 학급 시트에 직접 옮겨 적으면 1년분 공평 보장이 완성됩니다. 실명 칸은 없습니다(번호·닉네임만).

📖 한 줄 정의

심기 모드(데이터 임베딩): API 데이터를 미리 받아 HTML 파일 안 상수로 박아두는 방식(앱 실행 중 외부 통신 0).

학내망 원칙: 학교 배포 웹앱은 개인정보 수집·저장·전송 없음(외부 CDN·API 호출 0, 단일 파일) — 학생은 학내망에서 교사 PC 서버에 접속.

1. 3대 핵심 분석 비교표

무엇이 바뀌었나요? / 영역 초보자를 위한 쉬운 설명 이렇게 한번 써보세요!
공정 규칙 3단 ① 이전 주 당번 자동 제외 ② 뽑힌 횟수가 적은 학생이 유리한 균등 추첨 ③ 전원 제외 시 전체 재등장. 규칙이 코드에 그대로 보입니다. pickPlayer 함수에서 제외·균등 로직 확인하기.
룰렛 애니메이션 CSS 회전(transform rotate)과 랜덤 각도로 돌다가 감속하며 멈춥니다. 도착 칸에서 '웅-딩' 사운드(Web Audio 합성)가 울립니다. 전자칠판에서 큰 회전 버튼(88px)을 눌러 구역별 추첨.
히스토리 아카이빙 '주간 기록 CSV 내보내기' 버튼이 주차·구역·번호·닉네임을 CSV 파일로 저장합니다. 자동 외부 전송은 없습니다 — 학급 시트로 옮겨 적는 것은 교사의 수동 관리입니다. 매주 금요일 내보내기 → 교사가 학급 시트에 붙여넣기.
개인정보 설계 실명 입력·저장 칸이 없습니다 — 번호·닉네임만. 참가자 목록은 파일 상단 상수로 심기되어 학내망 안에서만 완결됩니다. EMBED_PLAYERS 상수에 모둠 닉네임 목록 심기.

2. 핵심 아키텍처 해설

① 구역·참가자 데이터

const ZONES = ["칠판", "복도", "창틀", "쓰레기통"];
const PLAYERS = [
  { no: 1, nick: "코알라" },
  { no: 2, nick: "돌고래" }
];

참가자는 번호와 닉네임만 다룹니다 — 실명은 이 앱의 어디에도 들어가지 않습니다.

② 공정 추첨 로직

function pickPlayer(zoneIndex, history) {
  const last = history.filter(function (h) {
    return h.zone === ZONES[zoneIndex] && h.week === currentWeek - 1;
  });
  let pool = PLAYERS.filter(function (p) {
    return !last.some(function (h) { return h.no === p.no; });
  });
  if (pool.length === 0) pool = PLAYERS.slice();
  return pool[Math.floor(Math.random() * pool.length)];
}

이전 주 당번을 후보에서 빼고, 전원이 제외될 극단적인 경우에는 전체를 다시 후보로 세웁니다. '뽑힌 횟수 적은 학생 우선'은 히스토리의 누적 횟수로 후보를 정렬해 앞쪽에 비중을 주는 방식으로 확장할 수 있습니다.

③ 룰렛 스핀

let angle = 0;

function spin() {
  const target = angle + 1440 + Math.random() * 360;
  const timer = setInterval(function () {
    angle += 18;
    wheel.style.transform = "rotate(" + angle + "deg)";
    if (angle >= target) {
      clearInterval(timer);
      sound("ding");
    }
  }, 30);
}

④ 주간 기록 아카이빙

function archiveRow(zoneIndex, player) {
  return currentWeek + "," + ZONES[zoneIndex] + "," + player.no + "," + player.nick;
}
// CSV 내보내기 버튼으로 주간 기록을 로컬 파일로 저장 — 외부 전송 없음

⑤ 운영 체크리스트

  • 결락자(부재로 못 뽑힌 학생)는 다음 주 히스토리에서 자동으로 유리해집니다.
  • 학급 시트 관리는 교사 수동 — 앱은 자동 외부 전송을 하지 않습니다(학내망 원칙).
  • 새 모둠 닉네임이 생기면 EMBED_PLAYERS 상수를 갱신(심기 루틴)합니다.

3. 따라하기 3단계

  1. 제미나이 전용 에러 제로 프롬프트를 복사해 Gemini에 붙여넣습니다.
  2. AI가 던지는 역질문 3가지(구역 수, 당번 인원, CSV 서식)에 답하면 단일 HTML 코드가 완성됩니다.
  3. 코드를 roulette.html로 저장 후 더블클릭 — 월요일 아침 자치 시간에 전자칠판에서 구역별 추첨을 돌립니다.

제미나이 전용 에러 제로 프롬프트

[🚨 에러 방지 기본 안전장치]
1. 결과물은 외부 라이브러리·폰트·이미지 없이 단일 HTML 파일로 완성한다 — 더블클릭 즉시 실행(서버·설치·회원가입·외부 클라우드 금지).
2. 참가자 목록은 번호·닉네임만 다룬다(실명 입력·저장 금지) — 파일 상단 EMBED_PLAYERS 상수로 심기(학내망 배포용 외부 통신 0).
3. 공정 규칙: 이전 주 당번 자동 제외, 뽑힌 횟수가 적은 학생이 유리한 균등 추첨, 전원 제외 시 전체 재등장.
4. 룰렛 회전은 CSS transform(rotate)과 랜덤 각도 — 도착 사운드는 Web Audio API 합성('웅-딩').
5. 주간 기록(주차,구역,번호,닉네임)은 CSV 내보내기로 로컬 파일 저장 — 자동 외부 전송 없음(학급 시트 옮겨 적기는 교사 수동).
6. 전자칠판 대형 터치 대응: 회전 버튼 88px 이상, 결과 표기 큰 글씨.
7. // TODO, /* 생략 */ 금지 — 끝까지 완성한다.

[❓ 역질문 유도]
코드를 바로 만들지 말고, 아래 3가지를 먼저 질문한 뒤 내 답변으로 설계를 확정한다.
Q1. 청소 구역은 몇 개로 할까? (기본 4: 칠판·복도·창틀·쓰레기통)
Q2. 한 구역 당번은 몇 명? (2인 1조 권장)
Q3. 히스토리 CSV 서식은? (주차,구역,번호,닉네임 기본)

🎯 에디터 한줄평

'뽑기 불만'이 '공정 규칙 논의'로 바뀌는 것이 이 앱의 진짜 목표입니다. 규칙이 코드로 눈에 보이는 순간, 학생들은 불만 대신 제안을 하기 시작합니다 — "제외 기준을 2주로 늘리면 어때요?". 이력이 코드 안에서 쌓이는 것은 '공평은 믿음이 아니라 기록'이라는 자치 교육의 정수입니다. 전자칠판 앞에서 울리는 웅-딩 사운드 하나가 월요일 아침을 아이들 절반의 관심사로 만듭니다.

📚 기술·교육 참고 링크

  • MDN — CSS transform : 룰렛 회전 애니메이션의 원리
  • MDN — Web Audio API : '웅-딩' 도착 사운드 합성
  • 교육과정 연계: 창의적 체험활동(학급자치·역할 분담), 모둠 활동과 학급 회의 안건으로 확장