<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Роза показателей</title>
<script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script crossorigin src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.23.2/babel.min.js"></script>
<style>
  * { box-sizing: border-box; margin: 0; padding: 0; }
  body { background: #0d0d1a; }
</style>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const RAW_DATA = {
  N1:  { интер: 3, поток: 1, чист: 0, сеть: 1 },
  N7:  { интер: 0, поток: 1, чист: 0, сеть: 0 },
  N9:  { интер: 1, поток: 3, чист: 1, сеть: 0 },
  N6:  { интер: 2, поток: 3, чист: 2, сеть: 1 },
  N3:  { интер: 1, поток: 1, чист: 3, сеть: 0 },
  N8:  { интер: 0, поток: 2, чист: 2, сеть: 1 },
  N2:  { интер: 1, поток: 1, чист: 2, сеть: 0 },
  N11: { интер: 1, поток: 1, чист: 2, сеть: 1 },
  N5:  { интер: 1, поток: 1, чист: 1, сеть: 2 },
  N10: { интер: 2, поток: 1, чист: 0, сеть: 1 },
};

const CATEGORIES = ["интер", "поток", "чист", "сеть"];
const CAT_LABELS = { интер: "Интер", поток: "Поток", чист: "Чист трод", сеть: "Сеть" };
const CAT_COLORS = { интер: "#ff6b6b", поток: "#ffd93d", чист: "#6bcb77", сеть: "#4d96ff" };
const PARTICIPANTS = Object.keys(RAW_DATA);

function polarToXY(angle, r, cx, cy) {
  const rad = (angle - 90) * (Math.PI / 180);
  return [cx + r * Math.cos(rad), cy + r * Math.sin(rad)];
}

function RadarChart({ highlighted, onSelect }) {
  const size = 340, cx = 170, cy = 170, maxR = 122, maxVal = 3;
  const angleStep = 90;
  const rings = [1, 2, 3];

  const axes = CATEGORIES.map((cat, i) => {
    const [x2, y2] = polarToXY(i * angleStep, maxR, cx, cy);
    return { cat, i, x2, y2 };
  });

  return (
    <svg width={size} height={size} style={{display:"block", cursor:"pointer"}}>
      {rings.map(ring => {
        const pts = CATEGORIES.map((_, i) => polarToXY(i * angleStep, (ring/maxVal)*maxR, cx, cy));
        const d = pts.map((pt,i) => (i===0?`M${pt[0]},${pt[1]}`:`L${pt[0]},${pt[1]}`)).join(" ")+" Z";
        return <path key={ring} d={d} fill="none" stroke="rgba(255,255,255,0.1)" strokeWidth={1}/>;
      })}
      {axes.map(({cat,x2,y2}) => (
        <line key={cat} x1={cx} y1={cy} x2={x2} y2={y2} stroke="rgba(255,255,255,0.15)" strokeWidth={1}/>
      ))}
      {PARTICIPANTS.map(p => {
        const isHl = highlighted === p;
        const dominant = CATEGORIES.reduce((a,b) => RAW_DATA[p][a]>=RAW_DATA[p][b]?a:b);
        const color = CAT_COLORS[dominant];
        const pts = CATEGORIES.map((cat,i) => {
          const r = (RAW_DATA[p][cat]/maxVal)*maxR;
          return polarToXY(i*angleStep, r, cx, cy);
        });
        const d = pts.map((pt,i)=>(i===0?`M${pt[0]},${pt[1]}`:`L${pt[0]},${pt[1]}`)).join(" ")+" Z";
        return (
          <path key={p} d={d}
            fill={color} fillOpacity={isHl?0.55:highlighted?0.04:0.18}
            stroke={color} strokeWidth={isHl?2.5:highlighted?0.5:1}
            strokeOpacity={isHl?1:highlighted?0.25:0.6}
            onClick={()=>onSelect(isHl?null:p)}
            style={{transition:"all 0.25s"}}
          />
        );
      })}
      {highlighted && CATEGORIES.map((cat,i) => {
        const r = (RAW_DATA[highlighted][cat]/maxVal)*maxR;
        const [x,y] = polarToXY(i*angleStep, r, cx, cy);
        return <circle key={i} cx={x} cy={y} r={5} fill={CAT_COLORS[cat]} stroke="#0d0d1a" strokeWidth={1.5}/>;
      })}
      {axes.map(({cat,i}) => {
        const [lx,ly] = polarToXY(i*angleStep, maxR+26, cx, cy);
        return (
          <text key={cat} x={lx} y={ly} textAnchor="middle" dominantBaseline="middle"
            fill={CAT_COLORS[cat]} fontSize={12} fontFamily="'Courier New',monospace" fontWeight="bold">
            {CAT_LABELS[cat]}
          </text>
        );
      })}
      {rings.map(ring => (
        <text key={ring} x={cx+4} y={cy-(ring/maxVal)*maxR+4}
          fill="rgba(255,255,255,0.3)" fontSize={9} fontFamily="monospace">{ring}</text>
      ))}
    </svg>
  );
}

function App() {
  const [highlighted, setHighlighted] = React.useState(null);
  const [view, setView] = React.useState("radar");

  const totals = CATEGORIES.map(cat => ({
    cat, val: PARTICIPANTS.reduce((s,p)=>s+RAW_DATA[p][cat],0)
  }));
  const maxTotal = Math.max(...totals.map(t=>t.val));

  return (
    <div style={{minHeight:"100vh",background:"#0d0d1a",fontFamily:"'Courier New',monospace",
      color:"#e0e0f0",display:"flex",flexDirection:"column",alignItems:"center",padding:"32px 16px"}}>

      <div style={{textAlign:"center",marginBottom:28}}>
        <div style={{fontSize:11,letterSpacing:6,color:"#4d96ff",textTransform:"uppercase",marginBottom:6}}>
          Анализ активности
        </div>
        <h1 style={{margin:0,fontSize:28,fontWeight:900,letterSpacing:2,color:"#fff"}}>
          РОЗА ПОКАЗАТЕЛЕЙ
        </h1>
        <div style={{marginTop:8,fontSize:12,color:"rgba(255,255,255,0.4)"}}>N1 – N11 · 4 категории</div>
      </div>

      <div style={{display:"flex",gap:0,marginBottom:28,border:"1px solid rgba(255,255,255,0.15)",
        borderRadius:8,overflow:"hidden"}}>
        {["radar","bar"].map(v => (
          <button key={v} onClick={()=>setView(v)} style={{
            padding:"8px 24px",background:view===v?"#4d96ff":"transparent",
            border:"none",color:view===v?"#fff":"rgba(255,255,255,0.5)",
            cursor:"pointer",fontFamily:"monospace",fontSize:13,
            fontWeight:view===v?700:400,transition:"all 0.2s"}}>
            {v==="radar"?"🕸 Радар":"📊 Столбцы"}
          </button>
        ))}
      </div>

      <div style={{display:"flex",flexWrap:"wrap",gap:32,justifyContent:"center",
        alignItems:"flex-start",width:"100%",maxWidth:900}}>

        <div style={{background:"rgba(255,255,255,0.03)",borderRadius:20,
          border:"1px solid rgba(255,255,255,0.08)",padding:20,
          display:"flex",flexDirection:"column",alignItems:"center"}}>

          {view==="radar" ? (
            <RadarChart highlighted={highlighted} onSelect={setHighlighted}/>
          ) : (
            <div style={{width:340,padding:"20px 10px"}}>
              {PARTICIPANTS.map(p => {
                const total = CATEGORIES.reduce((s,c)=>s+RAW_DATA[p][c],0);
                const isHl = highlighted===p;
                return (
                  <div key={p} onClick={()=>setHighlighted(isHl?null:p)}
                    style={{display:"flex",alignItems:"center",gap:10,marginBottom:10,
                      cursor:"pointer",opacity:highlighted&&!isHl?0.35:1,transition:"opacity 0.2s"}}>
                    <div style={{width:30,fontSize:11,color:isHl?"#fff":"rgba(255,255,255,0.6)",fontWeight:isHl?700:400}}>{p}</div>
                    <div style={{flex:1,display:"flex",height:18,borderRadius:4,overflow:"hidden"}}>
                      {CATEGORIES.map(cat => {
                        const w = total>0?(RAW_DATA[p][cat]/total)*100:0;
                        return <div key={cat} style={{width:`${w}%`,background:CAT_COLORS[cat],transition:"width 0.3s"}}
                          title={`${CAT_LABELS[cat]}: ${RAW_DATA[p][cat]}`}/>;
                      })}
                    </div>
                    <div style={{width:18,fontSize:11,color:"rgba(255,255,255,0.4)",textAlign:"right"}}>{total}</div>
                  </div>
                );
              })}
            </div>
          )}

          <div style={{display:"flex",gap:14,marginTop:12,flexWrap:"wrap",justifyContent:"center"}}>
            {CATEGORIES.map(cat => (
              <div key={cat} style={{display:"flex",alignItems:"center",gap:5,fontSize:11}}>
                <div style={{width:10,height:10,borderRadius:"50%",background:CAT_COLORS[cat]}}/>
                <span style={{color:"rgba(255,255,255,0.6)"}}>{CAT_LABELS[cat]}</span>
              </div>
            ))}
          </div>
        </div>

        <div style={{display:"flex",flexDirection:"column",gap:6,minWidth:200}}>
          <div style={{fontSize:10,letterSpacing:4,color:"rgba(255,255,255,0.3)",marginBottom:8,textTransform:"uppercase"}}>
            Участники
          </div>
          {PARTICIPANTS.map(p => {
            const total = CATEGORIES.reduce((s,c)=>s+RAW_DATA[p][c],0);
            const dominant = CATEGORIES.reduce((a,b)=>RAW_DATA[p][a]>=RAW_DATA[p][b]?a:b);
            const isHl = highlighted===p;
            const col = CAT_COLORS[dominant];
            return (
              <div key={p} onClick={()=>setHighlighted(isHl?null:p)} style={{
                display:"flex",alignItems:"center",gap:12,padding:"8px 14px",
                borderRadius:10,cursor:"pointer",
                background:isHl?`rgba(${parseInt(col.slice(1,3),16)},${parseInt(col.slice(3,5),16)},${parseInt(col.slice(5,7),16)},0.2)`:"rgba(255,255,255,0.03)",
                border:`1px solid ${isHl?col:"rgba(255,255,255,0.06)"}`,
                transition:"all 0.2s",opacity:highlighted&&!isHl?0.4:1}}>
                <div style={{width:8,height:8,borderRadius:"50%",background:col,
                  boxShadow:isHl?`0 0 8px ${col}`:"none"}}/>
                <span style={{fontWeight:isHl?700:400,fontSize:14,flex:1}}>{p}</span>
                <div style={{display:"flex",gap:3,alignItems:"flex-end",height:28}}>
                  {CATEGORIES.map(cat => (
                    <div key={cat} style={{width:8,height:Math.max((RAW_DATA[p][cat]/3)*28,2),
                      background:CAT_COLORS[cat],borderRadius:2}}
                      title={`${CAT_LABELS[cat]}: ${RAW_DATA[p][cat]}`}/>
                  ))}
                </div>
                <span style={{fontSize:11,color:"rgba(255,255,255,0.35)",minWidth:16,textAlign:"right"}}>{total}</span>
              </div>
            );
          })}

          <div style={{marginTop:16,padding:"12px 14px",borderRadius:10,
            background:"rgba(255,255,255,0.04)",border:"1px solid rgba(255,255,255,0.08)"}}>
            <div style={{fontSize:10,letterSpacing:3,color:"rgba(255,255,255,0.3)",marginBottom:8,textTransform:"uppercase"}}>
              Итого по категориям
            </div>
            {totals.map(({cat,val}) => (
              <div key={cat} style={{display:"flex",alignItems:"center",gap:8,marginBottom:6}}>
                <div style={{width:8,height:8,borderRadius:"50%",background:CAT_COLORS[cat]}}/>
                <span style={{fontSize:12,flex:1,color:"rgba(255,255,255,0.7)"}}>{CAT_LABELS[cat]}</span>
                <div style={{width:80,height:6,background:"rgba(255,255,255,0.08)",borderRadius:3,overflow:"hidden"}}>
                  <div style={{width:`${(val/maxTotal)*100}%`,height:"100%",background:CAT_COLORS[cat],borderRadius:3}}/>
                </div>
                <span style={{fontSize:12,color:CAT_COLORS[cat],fontWeight:700,minWidth:20,textAlign:"right"}}>{val}</span>
              </div>
            ))}
          </div>
        </div>
      </div>

      <div style={{marginTop:32,fontSize:11,color:"rgba(255,255,255,0.2)",textAlign:"center"}}>
        Нажми на участника чтобы выделить · Переключай вид выше
      </div>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App/>);
</script>
</body>
</html>
