/* ============================================================ pandanow.jsx — トップの「パンダNOW!」 いまパンダが何してるかを、曜日×時間帯のスケジュールで自動切替。 短いループアニメ(gif風)+「〇〇してる」の現状テキストだけ。 window.PixelPanda を利用。window.PandaNow を公開。 ============================================================ */ /* ポップなロゴ「パンダNOW!」(1文字ずつ色・回転) */ const PN_LOGO = [ { c: "パ", col: "#ff6b6b", rot: -7 }, { c: "ン", col: "#ffd24a", rot: 5 }, { c: "ダ", col: "#4cc3d9", rot: -4 }, { c: "N", col: "#7ee0a0", rot: 6 }, { c: "O", col: "#ff8fb1", rot: -5 }, { c: "W", col: "#ffb14a", rot: 4 }, { c: "!", col: "#ff6b6b", rot: -3 }, ]; function PNPopLogo() { return ( {PN_LOGO.map((g, i) => ( {g.c} ))} ); } /* ドットの電源マーク(ポップ) */ const POWER_ROWS = [ "....k....", "..k.k.k..", ".k..k..k.", ".k..k..k.", ".k.....k.", ".k.....k.", "..k...k..", "...kkk...", ]; const PN_ACT = { sleep: { label: "寝てる" }, asagohan: { label: "子どもと朝ごはん" }, claude: { label: "Claudeと戯れてる" }, hirumeshi:{ label: "ごはん食べてる" }, super: { label: "スーパーで買い物" }, yugohan: { label: "子どもと夕ごはん" }, slot: { label: "スロット打ってる" }, nomi: { label: "飲みに行ってる" }, }; /* --- 曜日×時間で「いまの活動」を決める --- */ function pnActivityFor(d) { const day = d.getDay(); // 0=日 .. 6=土 const h = d.getHours(); const weekend = (day === 0 || day === 6); if (h < 6 || h >= 23) return "sleep"; if (h < 8) return "asagohan"; if (weekend) { if (h < 11) return "super"; if (h < 13) return "hirumeshi"; if (h < 17) return "slot"; if (h < 19) return "yugohan"; return "nomi"; // 19–23 } else { if (h < 12) return "claude"; if (h < 13) return "hirumeshi"; if (h < 17) return "claude"; if (h < 18) return "super"; if (h < 20) return "yugohan"; if (day === 5) return "nomi"; // 金曜の夜は飲み return "claude"; // 平日の夜は戯れ } } /* --- パンダ本体(スケール付き) --- */ function PNPanda({ pose = "stand", scale = 0.62 }) { const C = window.PixelPanda; return (
{C ? : null}
); } /* --- 各シーン(短いループ) --- */ function PNScene({ act }) { switch (act) { case "sleep": return (
Z z z
); case "asagohan": case "yugohan": return (
); case "claude": return (
); case "hirumeshi": return (
); case "super": return (
); case "slot": return (
7▲●7◆7
●7◆7▲●
◆7●7▲7
); case "nomi": return (
); default: return
; } } /* --- 本体 --- */ function PandaNow() { const ACTS = Object.keys(PN_ACT); // スケジュール順 const [now, setNow] = React.useState(() => new Date()); const [on, setOn] = React.useState(false); // テレビON/OFF const [idx, setIdx] = React.useState(0); // いま表示中の活動 const [turning, setTurning] = React.useState(false); const [live, setLive] = React.useState(false); // 本物のパンダ チャンネル const PN_LIVE_ID = "V7MUP69nLqA"; // iPanda 24/7 ライブ(差し替え可) const toLive = () => { setLive(true); setTurning(true); setTimeout(() => setTurning(false), 650); }; const toDots = () => { setLive(false); setTurning(true); setTimeout(() => setTurning(false), 650); }; React.useEffect(() => { const id = setInterval(() => setNow(new Date()), 30000); return () => clearInterval(id); }, []); const schedAct = pnActivityFor(now); const powerOn = () => { setIdx(ACTS.indexOf(schedAct)); setTurning(true); setOn(true); setTimeout(() => setTurning(false), 650); }; const powerOff = () => { setOn(false); setLive(false); }; const go = (d) => setIdx((i) => (i + d + ACTS.length) % ACTS.length); const act = ACTS[idx]; const label = PN_ACT[act].label; const isNow = act === schedAct; const hh = String(now.getHours()).padStart(2, "0"); const mm = String(now.getMinutes()).padStart(2, "0"); return (
PANDA NOW!
{!on ? ( ) : (
OFF LIVE {hh}:{mm}
{turning && }
)}
405-TV
); } window.PandaNow = PandaNow; window.PNScene = PNScene; window.PN_ACT = PN_ACT;