586 lines
39 KiB
Plaintext
586 lines
39 KiB
Plaintext
<!DOCTYPE html>
|
|
<html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<title>WEVIA Meeting Rooms</title>
|
|
<style>@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@600;800;900&display=swap');
|
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
body{background:#eaeff7;background-image:radial-gradient(#c8d4e4 0.4px,transparent 0.4px),linear-gradient(180deg,#e0e8f4 0%,#eaeff7 100%);background-size:14px 14px,100% 100%;overflow-y:auto;font-family:'Nunito'}
|
|
canvas{display:block;image-rendering:auto}
|
|
#hud{position:fixed;top:0;left:0;right:0;height:22px;background:rgba(255,255,255,0.85);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)/*hudGlass*/;border-bottom:1px solid #c8d8e8;z-index:10;display:flex;align-items:center;padding:0 10px;font-size:.6rem;gap:10px}
|
|
#hud b{color:#e94560}#hud .g{color:#059669;font-weight:800}
|
|
#nav{position:fixed;top:28px;left:0;right:0;display:flex;justify-content:center;gap:5px;padding:4px;z-index:10;background:#e4ecf6dd}
|
|
#nav a{padding:2px 6px;border-radius:4px;font-size:6.5px;font-weight:600;text-decoration:none;background:#fff8;color:#5a6a80;border:1px solid #c8d8e8;transition:all .2s}
|
|
#nav a.ac{background:#059669;color:#fff;border-color:#059669}
|
|
#T{position:fixed;pointer-events:none;display:none;z-index:99;background:#fff;border:3px solid;border-radius:12px;padding:12px 14px;color:#2a2a4a;box-shadow:0 4px 20px #0003;max-width:260px;font-size:.76rem;line-height:1.5}
|
|
#T b{display:block;font-size:.9rem;margin-bottom:2px}#T i{font-style:normal;font-size:.5rem;text-transform:uppercase;letter-spacing:2px;color:#64748b}
|
|
#T .d{font-size:.7rem;margin-top:4px;color:#475569}#T .m{margin-top:6px;padding-top:6px;border-top:1px solid #e4ecf6;font-size:.65rem;color:#475569;line-height:1.6}
|
|
#emer{position:fixed;bottom:14px;right:14px;z-index:20;display:flex;gap:6px}
|
|
#emer button{padding:4px 10px;border-radius:6px;border:1.5px solid;font:700 8px Nunito;cursor:pointer}
|
|
#emer .red{background:#ef4444;color:#fff;border-color:#dc2626}
|
|
#emer .blu{background:#3b82f6;color:#fff;border-color:#2563eb}
|
|
#emer .grn{background:#059669;color:#fff;border-color:#047857}
|
|
#modal{display:none;position:fixed;inset:0;background:#000a;z-index:50;align-items:center;justify-content:center}
|
|
#modal.show{display:flex}
|
|
#modal .box{background:#fff;border-radius:14px;padding:20px;max-width:480px;width:92%;max-height:88vh;overflow-y:auto}
|
|
#modal h2{font-size:1rem;margin-bottom:10px;color:#e94560}
|
|
#modal label{display:block;font-size:.78rem;font-weight:700;margin:8px 0 3px}
|
|
#modal select,#modal textarea{width:100%;padding:7px;border:1px solid #c8d8e8;border-radius:6px;font:400 11px Nunito}
|
|
#modal .chips{display:flex;flex-wrap:wrap;gap:4px;margin:4px 0}
|
|
#modal .chip{padding:2px 8px;border-radius:8px;font-size:.7rem;font-weight:700;border:2px solid #c8d8e8;cursor:pointer}
|
|
#modal .chip.sel{background:#059669;color:#fff;border-color:#059669}
|
|
#modal .btns{display:flex;gap:8px;margin-top:14px}
|
|
#modal .btns button{flex:1;padding:9px;border-radius:8px;border:none;font:700 11px Nunito;cursor:pointer}
|
|
@media(prefers-color-scheme:dark){body{background:#1a1a2e!important;background-image:radial-gradient(#2a2a4a 0.4px,transparent 0.4px)!important}#hud{background:#1a1a2edd!important;border-color:#2a2a4a!important}#hud b{color:#e94560}#nav a{background:#2a2a4a88!important;color:#94a3b8!important;border-color:#3a3a5a!important}#nav a.ac{background:#059669!important;color:#fff!important}#T{background:#2a2a4a!important;color:#e2e8f0!important;border-color:#3a3a5a!important}#modal .box{background:#1e1e3a!important;color:#e2e8f0!important}#agentPanel{background:#1e1e3a!important;color:#e2e8f0!important}#wLeg{background:#1a1a2ecc!important;border-color:#2a2a4a!important;color:#94a3b8!important}}
|
|
@media(max-width:768px){#hud{font-size:.5rem!important}#nav a{font-size:5px!important;padding:1px 3px!important}#emer{bottom:8px!important;right:8px!important}#emer button{font-size:6px!important;padding:2px 6px!important}#agentPanel{width:100%!important}#agSearch{width:60px!important}}
|
|
</style></head><body>
|
|
<div id="hud"><b>WEVIA Meeting Rooms</b><span class="g">● LIVE</span><span id="ht" style="color:#64748b"></span><input id="agSearch" placeholder="Rechercher..." style="margin-left:auto;font:11px Nunito;padding:2px 6px;border:1px solid #c8d8e8;border-radius:4px;width:100px;background:#fff8" oninput="window._sq=this.value.toLowerCase()"><span style="margin-left:auto;font-size:.6rem;color:#64748b" id="hs"></span></div>
|
|
<div id="nav">
|
|
<a href="/enterprise-model.html">Enterprise</a><a href="/wevia-meetings.html">Dashboard</a>
|
|
<a href="/wevia-meeting-rooms.html" class="ac">Rooms</a><a href="/wevia-master.html">Master</a><a href="/architecture.html">Archi</a>
|
|
</div>
|
|
<canvas id="c"></canvas>
|
|
<div id="T"><b></b><i></i><span class="d"></span><span class="m"></span></div>
|
|
<div id="emer">
|
|
<button style="padding:4px 10px;border-radius:6px;border:1.5px solid #6366f1;font:700 8px Nunito;cursor:pointer;background:#6366f1;color:#fff" onclick="var a=document.createElement('a');a.href=C.toDataURL();a.download='meeting.png';a.click()">📷 Export</button>
|
|
<button class="red" onclick="openE()">🚨 Urgence</button>
|
|
<button class="blu" onclick="trigD()">📋 Daily</button>
|
|
<button style="padding:4px 10px;border-radius:6px;border:1.5px solid #64748b;font:700 8px Nunito;cursor:pointer;background:#64748b;color:#fff" onclick="document.documentElement.requestFullscreen()">⛶ Plein ecran</button>
|
|
<button style="padding:4px 10px;border-radius:6px;border:1.5px solid #334155;font:700 8px Nunito;cursor:pointer;background:#334155;color:#fff" onclick="toggleDark()">☽ Dark</button>
|
|
<button class="grn" onclick="trigS()">🏛️ Stratégie</button>
|
|
</div>
|
|
<div id="modal"><div class="box">
|
|
<h2>🚨 Réunion d'Urgence</h2>
|
|
<label>Type</label>
|
|
<select id="et" onchange="autoSel()"><option value="">—</option>
|
|
<option value="infra_down">🏗️ Service DOWN</option><option value="security">🔒 Brèche sécurité</option>
|
|
<option value="regression">💻 Régression</option><option value="business">💼 Urgence business</option>
|
|
<option value="ia_fail">🧠 IA en panne</option><option value="data_loss">💾 Perte données</option></select>
|
|
<label>Description</label><textarea id="ed" rows="2"></textarea>
|
|
<label>Participants</label><div class="chips" id="ec"></div>
|
|
<label>Par</label>
|
|
<select id="eb"><option>👔 Yacine</option><option>🤖 Agent Chef</option><option>🧠 WEVIA</option><option>♟️ Opus</option></select>
|
|
<div class="btns"><button style="background:#ef4444;color:#fff" onclick="launchE()">🚨 LANCER</button>
|
|
<button style="background:#e4ecf6" onclick="closeM()">Annuler</button></div>
|
|
</div></div>
|
|
|
|
<script>
|
|
var isDark=window.matchMedia&&window.matchMedia('(prefers-color-scheme:dark)').matches;
|
|
var _hist=[];function addHist(msg){_hist.unshift({t:new Date().toLocaleTimeString('fr-FR',{hour:'2-digit',minute:'2-digit'}),m:msg});if(_hist.length>5)_hist.pop();}
|
|
const C=document.getElementById('c'),X=C.getContext('2d'),TT=document.getElementById('T');
|
|
let W,H,mx=0,my=0,hov=null,tk=0,emAct=false;
|
|
const TOP=62; // offset below HUD+nav
|
|
function resize(){
|
|
W=innerWidth;
|
|
H=Math.max(1300,innerHeight);
|
|
C.width=W*2;C.height=H*2;
|
|
C.style.width=W+'px';C.style.height=H+'px';
|
|
X.scale(2,2);
|
|
document.body.style.minHeight=H+'px';
|
|
// CENTER rooms dynamically
|
|
var ox=Math.max(40,Math.floor((W-800)/2));
|
|
try{
|
|
RM[0].x=ox;RM[0].w=1040;
|
|
for(var i=1;i<Math.min(4,RM.length);i++)RM[i].x=ox+(i-1)*350;
|
|
for(var i=4;i<Math.min(7,RM.length);i++)RM[i].x=ox+(i-4)*350;
|
|
// Re-place agents
|
|
AA.length=0;
|
|
RM.forEach(function(r,ri){
|
|
var cx=r.x+r.w/2,cy=r.y+r.h*0.38;
|
|
var nn=r.ag.length,tr=Math.min(r.w*0.15,38);
|
|
var margin=36;
|
|
r.tcx=cx;r.tcy=cy;r.tr=tr;
|
|
r.ag.forEach(function(a,ai){
|
|
a.rm=r.id;a.sk=SK[(ri*3+ai)%SK.length];
|
|
var ecx=r.x+r.w/2,ecy=r.y+r.h*0.38,erx=Math.min(r.w/3.5,nn>8?r.w/3:r.w/4+10),ery=Math.min(r.h*0.2,nn>8?r.h*0.22:r.h*0.18);var ang=2*Math.PI*ai/nn-Math.PI/2;a.px=ecx+erx*Math.cos(ang);a.py=ecy+ery*Math.sin(ang);
|
|
a.face=Math.PI;AA.push(a);
|
|
});
|
|
});
|
|
}catch(e){}
|
|
}
|
|
resize();setTimeout(function(){RM.forEach(function(r){if(r.id==='infra')r.kpi='75% disk | 20 Docker';else if(r.id==='dev')r.kpi='NR:153/153';else if(r.id==='sec')r.kpi='0 CVE | 47 bans';else if(r.id==='biz')r.kpi='132K HCPs';else if(r.id==='ia')r.kpi='9 models | 14K vecs';else if(r.id==='strat')r.kpi='53ag | NR:153';else if(r.id==='transit')r.kpi='203 wiki';});},100);addEventListener('resize',resize);
|
|
addHist('53 agents initialized');
|
|
|
|
const SK=['#ffd5b4','#f5c6a5','#e0ac69','#c68642','#8d5524','#ffdbac'];
|
|
const AA=[];
|
|
|
|
var _gw=800,_gap=10;
|
|
function _cx(){return Math.max(40,Math.floor((W-_gw)/2));}
|
|
const RM=[
|
|
{id:'strat',l:'🏛️ STRATEGY',obj:'Consolider terrain + stratégie',dur:'45 min',freq:'Ven 16h',
|
|
concl:'Décisions strat + roadmap',actions:'Objectifs + priorités',prescr:'Obligatoire tous leads',chat:[{who:'👑',t:'Ordre du jour: roadmap Q2 + budget GPU'},{who:'🧠',t:'313 routes actives, 0 regression'},{who:'♟️',t:'Architecture stable. Refonte S88 propose'},{who:'📧',t:'2079 emails sync. Pipeline OK'},{who:'⚔️',t:'Blade 34 caps, sync 60s nominal'}],
|
|
x:40,y:TOP+10,w:800,h:260,cl:'#059669',ag:[
|
|
{n:'WEVIA Master',hc:'#1a0a00',g:'f',re:'👩🏽💼',tool:'🧠',d:'313 routes · 585 skills'},
|
|
{n:'Claude Opus',hc:'#3a2000',g:'m',re:'👨🏿💻',tool:'♟️',d:'Architecte en chef'},
|
|
{n:'WEVIA Life',re:'📧',d:'2079 emails'},
|
|
{n:'Blade IA',re:'⚔️',d:'34 caps'},
|
|
{n:'MiroFish',re:'🐟',d:'Collab IA'},
|
|
{n:'Agent Maître',re:'👑',d:'8 agents · 32 crons'},
|
|
]},
|
|
{id:'infra',l:'🏗️ INFRA',obj:'État infra + heal',dur:'15 min',freq:'09h+14h',
|
|
concl:'Services UP/DOWN',actions:'Restart + fix disk',prescr:'Obligatoire CORTEX',chat:[{who:'🧠',t:'S204 83% disk. S95 OK. S151 OK'},{who:'🔍',t:'Gap: S88 GPU mort. Annuler Hetzner'},{who:'🤖',t:'19 Docker UP. Langfuse restart loop'},{who:'⚡',t:'Auto-heal actif. 0 incident 24h'}],
|
|
x:40,y:TOP+290,w:340,h:380,cl:'#3b82f6',ag:[
|
|
{n:'CORTEX',hc:'#8a4a00',g:'f',re:'👩🏾🔧',tool:'🧠',d:'Lead · */4h'},
|
|
{n:'Gap Detect',gl:1,hc:'#2a1a0a',g:'m',re:'👨🏻🔬',tool:'🔍',d:'*/6h'},
|
|
{n:'Agent Chef',hc:'#6a3a10',g:'f',re:'👩🏽🍳',tool:'🤖',d:'*/10'},
|
|
{n:'Proactive',hc:'#1a0a00',g:'m',re:'👨🏼🚀',tool:'⚡',d:'*/5'},
|
|
{n:'Prometheus',re:'📈',d:'Metrics'},
|
|
{n:'Uptime-Kuma',re:'📟',d:'Monitor 24/7'},
|
|
{n:'Sentinel',re:'🛰️',d:'S95 brain'},
|
|
{n:'KumoMTA',re:'📬',d:'Email :587'},
|
|
{n:'PMTA',re:'📮',d:'Email :25'},
|
|
]},
|
|
{id:'dev',l:'💻 DEV',obj:'Qualité + régressions',dur:'15 min',freq:'09h+14h',
|
|
concl:'NonReg score + bugs',actions:'Fix + Playwright',prescr:'Obligatoire NonReg',chat:[{who:'✅',t:'NonReg 153/153 PASS'},{who:'📸',t:'Playwright 62/64. Video 8.3MB'},{who:'🕵️',t:'0 fuite secrets. Code clean'},{who:'🧬',t:'Enterprise HD: sparklines + trends'}],
|
|
x:310,y:TOP+290,w:340,h:380,cl:'#10b981',ag:[
|
|
{n:'NonReg',hc:'#5a2a00',g:'f',re:'👩🏻⚕️',tool:'✅',d:'153/153 · */15'},
|
|
{n:'L99 Visual',gl:1,hc:'#8a6a30',g:'m',re:'👨🏽🎨',tool:'📸',d:'Playwright'},
|
|
{n:'L99 Dark',hc:'#1a0a00',g:'f',re:'🕵🏾♀️',tool:'🕵️',d:'*/8h'},
|
|
{n:'Evolution',gl:1,hc:'#4a2a10',g:'m',re:'👨🏼🔬',tool:'🧬',d:'*/6h'},
|
|
{n:'WEDROID',re:'🔧',d:'Backend diag'},
|
|
{n:'WEVCODE',re:'💻',d:'Code assist'},
|
|
{n:'EvoMaster',re:'🧪',d:'API fuzz'},
|
|
{n:'Langfuse',re:'📊',d:'LLM monitor'},
|
|
]},
|
|
{id:'sec',l:'🔒 SECURITY',obj:'Menaces + vulnérabilités',dur:'15 min',freq:'09h+14h',
|
|
concl:'0 leaks + bans',actions:'Scan + patch',prescr:'Obligatoire DarkTools',chat:[{who:'🛡️',t:'Nuclei: 0 CVE critique'},{who:'🚫',t:'CrowdSec: 47 IPs banned 24h'},{who:'🔐',t:'SSO Authentik: sessions OK'}],
|
|
x:580,y:TOP+290,w:340,h:380,cl:'#ef4444',ag:[
|
|
{n:'Dark Tools',hc:'#2a0a00',g:'f',re:'👩🏿🔧',tool:'🛡️',d:'Nuclei + Gitleaks'},
|
|
{n:'CrowdSec',re:'🚫',d:'Ban IP'},
|
|
{n:'Authentik',re:'🔐',d:'SSO'},
|
|
{n:'AEGIS',re:'🛡️',d:'Security fw'},
|
|
{n:'Vaultwarden',re:'🔑',d:'Passwords'},
|
|
{n:'Strix',re:'🦉',d:'Nuclei scan'},
|
|
]},
|
|
{id:'biz',l:'💼 BUSINESS',obj:'Pipeline + HCPs',dur:'15 min',freq:'09h+14h',
|
|
concl:'Deals + Ethica coverage',actions:'Relancer + enrichir',prescr:'Obligatoire Paperclip',chat:[{who:'📎',t:'656 agents fleet. 80 actifs'},{who:'🏢',t:'Enterprise model live. 22 depts'},{who:'💊',t:'Ethica: 132K HCPs (DZ+MA+TN)'},{who:'📊',t:'Pipeline B2B: 166 leads qualifies'}],
|
|
x:40,y:TOP+690,w:340,h:380,cl:'#f59e0b',ag:[
|
|
{n:'Paperclip',gl:1,hc:'#7a5a20',g:'m',re:'👨🏻💼',tool:'📎',d:'CEO · 716 agents'},
|
|
{n:'Enterprise',hc:'#3a1a00',g:'f',re:'👩🏼💼',tool:'🏢',d:'10 modules'},
|
|
{n:'Ethica',hc:'#1a1a1a',g:'m',re:'👨🏾⚕️',tool:'💊',d:'126K HCPs'},
|
|
{n:'CRM',re:'📊',d:'Deals'},
|
|
{n:'n8n',re:'🔄',d:'Workflow'},
|
|
{n:'Twenty',re:'👥',d:'CRM Docker'},
|
|
{n:'Activepieces',re:'🧩',d:'Automation'},
|
|
]},
|
|
{id:'ia',l:'🧠 IA',obj:'Modèles + RAG',dur:'15 min',freq:'09h+14h',
|
|
concl:'Ollama UP + Qdrant synced',actions:'Benchmark + fine-tune',prescr:'Obligatoire Consensus',chat:[{who:'🦙',t:'9 modeles Ollama. qwen3:8b default'},{who:'📐',t:'Qdrant 4414 vecs synced'},{who:'🔬',t:'585 skills catalogues. 0 gap'}],
|
|
x:310,y:TOP+690,w:340,h:440,cl:'#8b5cf6',ag:[
|
|
{n:'Ollama',re:'🦙',d:'9 modèles'},
|
|
{n:'Qdrant',re:'📐',d:'14K vectors'},
|
|
{n:'OSS Disc.',re:'🔬',d:'585 skills'},
|
|
{n:'DeerFlow',re:'🦌',d:'LangGraph'},
|
|
{n:'Dify',re:'🔮',d:'LLM ops'},
|
|
{n:'SearXNG',re:'🔎',d:'Meta search'},
|
|
{n:'Supermemory',re:'📚',d:'Knowledge'},
|
|
{n:'Mastra',re:'⚙️',d:'AI framework'},
|
|
{n:'Goose',re:'🪶',d:'AI agent'},
|
|
{n:'SkillSmith',re:'🛠️',d:'Skill gen'},
|
|
{n:'AIOS',re:'🖥️',d:'OS for AI'},
|
|
]},
|
|
{id:'transit',l:'🚶 TRANSIT',obj:'Tâches autonomes',dur:'—',freq:'Continu',
|
|
concl:'Skills + wiki enrichis',actions:'Scan + create + wire',prescr:'Autonome',chat:[{who:'📡',t:'Wiki scan: 203 fichiers indexes'},{who:'🏭',t:'Factory: 3 skills crees cette semaine'},{who:'📋',t:'GitHub: 15 repos surveilles'}],
|
|
x:580,y:TOP+690,w:340,h:380,cl:'#64748b',ag:[
|
|
{n:'Scanner',gl:1,hc:'#6a4020',g:'f',re:'👩🏽🔬',tool:'📡',d:'Wiki */2h'},
|
|
{n:'Factory',re:'🏭',d:'Create */12h'},
|
|
{n:'RND Pipe',hc:'#4a3020',g:'m',re:'👨🏿💻',tool:'📋',d:'GitHub */6h'},
|
|
{n:'BrowserUse',re:'🌐',d:'Web auto'},
|
|
{n:'Mattermost',re:'💬',d:'Team chat'},
|
|
{n:'Plausible',re:'📉',d:'Analytics'},
|
|
]},
|
|
];
|
|
|
|
// Place agents in 2 rows above/below table — ZERO overlap guaranteed
|
|
RM.forEach((r,ri)=>{
|
|
const cx=r.x+r.w/2;
|
|
const cy=r.y+r.h*0.38;
|
|
const nn=r.ag.length;
|
|
const tr=Math.min(r.w*0.15, 38);
|
|
r.tcx=cx;r.tcy=cy;r.tr=tr;
|
|
// Split agents into top row and bottom row
|
|
var margin=36;
|
|
r.ag.forEach((a,ai)=>{
|
|
a.rm=r.id;a.sk=SK[(ri*3+ai)%SK.length];
|
|
var ecx=r.x+r.w/2,ecy=r.y+r.h*0.38,erx=Math.min(r.w/3.5,nn>8?r.w/3:r.w/4+10),ery=Math.min(r.h*0.2,nn>8?r.h*0.22:r.h*0.18);var ang=2*Math.PI*ai/nn-Math.PI/2;a.px=ecx+erx*Math.cos(ang);a.py=ecy+ery*Math.sin(ang);
|
|
a.face=Math.PI;
|
|
AA.push(a);
|
|
});
|
|
});
|
|
|
|
// === DRAW AGENT (clean rebuild) ===
|
|
function dA(a,cl){
|
|
X.save();
|
|
X.translate(a.px,a.py);
|
|
|
|
// Active/passive state
|
|
var _rm=RM.find(function(r){return r.id===a.rm});
|
|
var _isActive=_rm&&_rm._st==='live';
|
|
if(_isActive){X.save();X.shadowColor=cl;X.shadowBlur=14+Math.sin(tk*0.08)*4;X.fillStyle=cl+'15';X.beginPath();X.arc(0,-6,24,0,6.28);X.fill();X.restore();}
|
|
if(!_isActive) X.globalAlpha=0.35;
|
|
if(window._sq&&window._sq.length>0&&a.n.toLowerCase().indexOf(window._sq)<0)X.globalAlpha=0.12;
|
|
|
|
// Hover glow
|
|
if(a===hov){X.shadowColor=cl;X.shadowBlur=22;X.shadowOffsetY=2;X.save();X.strokeStyle=cl+'50';X.lineWidth=0.5;var _hr=16+Math.sin(tk*0.1)*3;X.beginPath();X.arc(0,-13,_hr,0,6.28);X.stroke();X.restore();}/*hoverRing*/
|
|
|
|
// Ground shadow
|
|
X.fillStyle='#00000012';
|
|
X.beginPath();X.ellipse(0,16,11,3,0,0,6.28);X.fill();
|
|
|
|
// Body pill (dept color gradient)
|
|
var bg=X.createLinearGradient(-6,-4,6,4);
|
|
bg.addColorStop(0,cl);bg.addColorStop(1,cl+'88');
|
|
X.fillStyle=bg;
|
|
X.beginPath();X.roundRect(-6,-4,12,11,[5,5,2,2]);X.fill();
|
|
// Body highlight
|
|
X.fillStyle='#ffffff25';
|
|
X.beginPath();X.roundRect(-4,-3,4,7,[2,0,0,2]);X.fill();
|
|
|
|
// Legs (seated)
|
|
X.fillStyle=cl+'88';
|
|
X.beginPath();X.roundRect(-3,5,2.5,5,1);X.fill();
|
|
X.beginPath();X.roundRect(0.5,5,2.5,5,1);X.fill();
|
|
// Shoes
|
|
X.fillStyle='#fff';
|
|
X.beginPath();X.ellipse(-1.5,10,2,0.8,0,0,6.28);X.fill();
|
|
X.beginPath();X.ellipse(2,10,2,0.8,0,0,6.28);X.fill();
|
|
|
|
// Arms (resting)
|
|
X.save();X.globalAlpha=0.08;X.fillStyle='#000';X.beginPath();X.ellipse(0,14,8,2.5,0,0,6.28);X.fill();X.restore();/*agShadow*/X.fillStyle=a.sk||'#e0ac69';
|
|
X.beginPath();X.roundRect(-7,-1,2.5,5,1);X.fill();
|
|
X.beginPath();X.roundRect(4.5,-1,2.5,5,1);X.fill();
|
|
|
|
// HEAD
|
|
var hx=0,hy=-13,hr=12;
|
|
// Head shadow
|
|
X.fillStyle='#0000000a';X.beginPath();X.arc(hx+1,hy+1,hr,0,6.28);X.fill();
|
|
// Head circle (skin tone for humans, white for apps)
|
|
X.fillStyle=a.g?a.sk+'90':'#ffffff50';
|
|
X.beginPath();X.arc(hx,hy,hr,0,6.28);X.fill();
|
|
// Emoji (person or tool)
|
|
X.font='22px sans-serif';X.textAlign='center';X.textBaseline='middle';
|
|
X.fillText(a.re,hx,hy+1);
|
|
if(_isActive){X.fillStyle='#22c55e';X.beginPath();X.arc(hx+10,hy-10,3,0,6.28);X.fill();X.strokeStyle='#fff';X.lineWidth=1;X.beginPath();X.arc(hx+10,hy-10,3,0,6.28);X.stroke();}
|
|
// Tool badge (bottom-right, only for humans with tool)
|
|
if(a.tool){
|
|
X.fillStyle='#fff';X.beginPath();X.arc(hx+hr-2,hy+hr-2,5,0,6.28);X.fill();
|
|
X.font='7px sans-serif';X.fillText(a.tool,hx+hr-2,hy+hr-1);
|
|
}
|
|
// Hover ring
|
|
if(a===hov){X.strokeStyle=cl;X.lineWidth=r._st==='live'?3:1.5;X.beginPath();X.arc(hx,hy,hr+3,0,6.28);X.stroke();}
|
|
var _spk=_isActive&&_rm&&_rm.chat&&_rm.chat.length>0;if(_spk){var _ci=Math.floor(tk*0.015)%_rm.chat.length;if(_rm.ag.indexOf(a)===(_ci%_rm.ag.length)){X.strokeStyle=cl+'90';X.lineWidth=0.7;for(var _w=0;_w<3;_w++){X.beginPath();X.arc(hx+hr+3+_w*3,hy,1.5+_w,5.5,0.8);X.stroke();}}}
|
|
|
|
// Name below
|
|
X.font='600 6.5px Nunito';X.fillStyle='#334155';X.textAlign='center';X.textBaseline='top';
|
|
var _nw=X.measureText(a.n).width;X.fillStyle=window._isDark?'#1e293b80':'#ffffff90';X.beginPath();X.roundRect(-_nw/2-3,13,_nw+6,10,[3]);X.fill();X.fillStyle=window._isDark?'#e2e8f0':'#334155';X.fillText(a.n,0,18);/*namePill2*/
|
|
// Subtitle
|
|
if(a.d){X.font='400 5px Nunito';X.fillStyle='#94a3b8';X.fillText(a.d,0,26);}
|
|
|
|
// Hover detection
|
|
var smx=mx,smy=my+(window.scrollY||0);
|
|
if(Math.abs(smx-a.px)<14&&Math.abs(smy-a.py)<18)hov=a;
|
|
|
|
X.restore(); // CRITICAL: undoes translate + resets globalAlpha
|
|
}
|
|
|
|
// === DRAW TABLE — ellipse in room center ===
|
|
function dTable(r){
|
|
const cx=r.tcx,cy=r.tcy,tr=r.tr;
|
|
const tw=tr*1.2,th=tr*0.55,depth=Math.max(3,tr*0.08);
|
|
// Floor shadow (large, soft)
|
|
X.fillStyle='#00000012';
|
|
X.beginPath();X.ellipse(cx+2,cy+depth+6,tw+8,th+4,0,0,6.28);X.fill();
|
|
// Table side (3D depth)
|
|
X.fillStyle='#8a7560';
|
|
X.beginPath();X.ellipse(cx,cy+depth,tw,th,0,0,Math.PI);X.fill();
|
|
X.fillStyle='#a0906e';
|
|
X.beginPath();
|
|
X.moveTo(cx-tw,cy);X.lineTo(cx-tw,cy+depth);
|
|
X.ellipse(cx,cy+depth,tw,th,0,Math.PI,0);
|
|
X.lineTo(cx+tw,cy);
|
|
X.ellipse(cx,cy,tw,th,0,0,Math.PI,true);
|
|
X.fill();
|
|
// Table top surface (rich wood)
|
|
const g=X.createLinearGradient(cx-tw,cy-th,cx+tw,cy+th);
|
|
g.addColorStop(0,'#b8a88a');g.addColorStop(0.2,'#d4c4a8');g.addColorStop(0.4,'#e8dcc8');
|
|
g.addColorStop(0.6,'#f0e8d8');g.addColorStop(0.8,'#d4c4a8');g.addColorStop(1,'#b8a88a');
|
|
X.fillStyle=g;
|
|
X.beginPath();X.ellipse(cx,cy,tw,th,0,0,6.28);X.fill();
|
|
// Wood grain lines
|
|
X.strokeStyle='#c8b89820';X.lineWidth=0.5;
|
|
for(var gi=-3;gi<=3;gi++){
|
|
X.beginPath();X.ellipse(cx,cy+gi*th*0.15,tw*0.9,th*0.3,0.1*gi,0,6.28);X.stroke();
|
|
}
|
|
// Rim/edge
|
|
X.strokeStyle='#9a856a';X.lineWidth=1.5;
|
|
X.beginPath();X.ellipse(cx,cy,tw,th,0,0,6.28);X.stroke();X.globalAlpha=0.06;X.fillStyle='#8a7560';X.beginPath();X.ellipse(cx,cy+depth+10,tw*0.85,th*0.35,0,0,6.28);X.fill();X.globalAlpha=1;/*tRefl*/
|
|
// Specular highlight (top-left)
|
|
var sg=X.createRadialGradient(cx-tw*0.2,cy-th*0.3,0,cx-tw*0.2,cy-th*0.3,tw*0.4);
|
|
sg.addColorStop(0,'#ffffff40');sg.addColorStop(1,'#ffffff00');
|
|
X.fillStyle=sg;
|
|
X.beginPath();X.ellipse(cx-tw*0.15,cy-th*0.25,tw*0.35,th*0.35,-.2,0,6.28);X.fill();
|
|
// Center item (notepad/docs)
|
|
X.fillStyle='#ffffff90';X.beginPath();X.roundRect(cx-tr*0.12,cy-tr*0.08,tr*0.24,tr*0.18,1.5);X.fill();
|
|
X.strokeStyle='#d0c8b8';X.lineWidth=0.5;X.beginPath();X.roundRect(cx-8,cy-5,16,12,2);X.stroke();
|
|
X.fillStyle='#c0b8a850';
|
|
for(var li=0;li<3;li++){X.fillRect(cx-tr*0.08,cy-tr*0.04+li*tr*0.05,tr*0.16,0.5);}
|
|
}
|
|
|
|
// === DRAW ROOM ===
|
|
function dR(r){
|
|
X.globalAlpha=1;
|
|
// Premium room background
|
|
var rg=X.createLinearGradient(r.x,r.y,r.x,r.y+r.h);
|
|
rg.addColorStop(0,'#f8fafe');rg.addColorStop(0.3,'#f0f4fa');rg.addColorStop(1,'#e8edf6');
|
|
X.save();X.shadowColor='#00000012';X.shadowBlur=20;X.shadowOffsetY=8;/*depthShadow*/X.fillStyle=window._isDark?'#1e1e3a':'#ffffff';X.beginPath();X.roundRect(r.x,r.y,r.w,r.h,12);X.fill();X.restore();
|
|
// Subtle floor gradient
|
|
var fg=X.createLinearGradient(r.x,r.y+r.h*0.6,r.x,r.y+r.h);
|
|
fg.addColorStop(0,'#00000000');fg.addColorStop(1,'#00000008');
|
|
X.fillStyle=fg;X.beginPath();X.roundRect(r.x,r.y+r.h*0.6,r.w,r.h*0.4,[0,0,14,14]);X.fill();X.save();X.globalAlpha=0.04;X.fillStyle=r.cl;for(var _gx=r.x+10;_gx<r.x+r.w;_gx+=16)for(var _gy=r.y+50;_gy<r.y+r.h-30;_gy+=16){X.beginPath();X.arc(_gx,_gy,0.6,0,6.28);X.fill();}X.restore();/*gridDots*/
|
|
// Border
|
|
var _pulse=Math.sin(tk*0.05+r.x)*0.3+0.7;
|
|
X.strokeStyle=r.cl+(Math.round(_pulse*60).toString(16).padStart(2,'0'));X.lineWidth=1.5+Math.sin(tk*0.03)*0.5;X.beginPath();X.roundRect(r.x,r.y,r.w,r.h,14);X.stroke();
|
|
// Left accent bar (thicker)
|
|
if(r._st==='live'){var _lb=3+Math.sin(tk*0.06)*1.5;X.fillStyle=r.cl;X.beginPath();X.roundRect(r.x,r.y+8,_lb,r.h-16,3);X.fill();}else{X.fillStyle=r.cl+'60';X.beginPath();X.roundRect(r.x,r.y+8,3,r.h-16,3);X.fill();}/*liveBar*/
|
|
// Top header band
|
|
var hg=X.createLinearGradient(r.x,r.y,r.x,r.y+32);
|
|
hg.addColorStop(0,r.cl+'15');hg.addColorStop(1,'#00000000');
|
|
X.fillStyle=hg;X.beginPath();X.roundRect(r.x+1,r.y+1,r.w-2,30,[13,13,0,0]);X.fill();
|
|
|
|
// Emergency
|
|
if(emAct&&r.id==='strat'){
|
|
X.save();X.shadowColor='#ef4444';X.shadowBlur=15+Math.sin(tk*.08)*8;
|
|
X.strokeStyle='#ef4444';X.lineWidth=2.5;
|
|
X.beginPath();X.roundRect(r.x,r.y,r.w,r.h,10);X.stroke();X.restore();
|
|
}
|
|
// Label top-left
|
|
X.fillStyle=r.cl;X.font='700 11px Nunito'/*letterSpace*/;X.textAlign='left';
|
|
X.fillText(r.l,r.x+12,r.y+16);
|
|
// Agent count badge (inline with freq)
|
|
X.fillStyle='#94a3b850';X.font='600 5px JetBrains Mono';X.textAlign='right';
|
|
var _acnt=r.ag.length;X.fillStyle=r._st==='live'?'#059669':'#94a3b8';X.font='700 7px Nunito';X.fillText(_acnt+' ag',r.x+r.w-12,r.y+16);X.textAlign='left';
|
|
// Freq + dur top-right
|
|
X.font='500 5.5px Nunito';X.fillStyle='#94a3b8';X.textAlign='right';
|
|
// Status badge — compact, inside room
|
|
var _stL=r._st==='live'?'EN COURS':'PROCHAIN';var _stC=r._st==='live'?'#22c55e':'#94a3b8';
|
|
X.fillStyle=_stC+'18';X.beginPath();X.roundRect(r.x+r.w-62,r.y+5,54,10,3);X.fill();
|
|
X.fillStyle=_stC;X.font='700 5px Nunito';X.textAlign='center';X.fillText(_stL,r.x+r.w-35,r.y+12);
|
|
if(r._st==='live'){X.fillStyle='#22c55e';X.beginPath();X.arc(r.x+r.w-59,r.y+10,1.5+Math.sin(tk*0.1)*0.8,0,6.28);X.fill();}
|
|
X.fillText(r.freq+' · '+r.dur,r.x+r.w-8,r.y+32);
|
|
// Obj below label
|
|
X.font='400 5.5px Nunito';X.fillStyle='#94a3b8';X.textAlign='left';
|
|
X.fillText('Obj: '+r.obj,r.x+8,r.y+24);
|
|
var _m='';if(r.id==='infra')_m='Disk:'+LIVE.disk+'% Docker:'+LIVE.docker;
|
|
else if(r.id==='dev')_m='NR:'+LIVE.nr;
|
|
else if(r.id==='strat')_m='Fleet:656ag '+LIVE.uptime;
|
|
if(_m){X.font='500 4.5px JetBrains Mono,monospace';X.fillStyle='#059669';X.fillText(_m,r.x+10,r.y+36);}
|
|
|
|
if(r.kpi){X.fillStyle=r._st==='live'?'#ecfdf5':'#f8fafc';X.beginPath();X.roundRect(r.x+2,r.y+r.h-22,r.w-4,18,[0,0,10,10]);X.fill();X.font='500 6px JetBrains Mono';X.fillStyle=r._st==='live'?'#059669':'#64748b';X.textAlign='center';X.fillText(r.kpi||'',r.x+r.w/2,r.y+r.h-11);}
|
|
if(r._st==='live'){X.save();var hg=X.createLinearGradient(r.x,r.y,r.x,r.y+40);hg.addColorStop(0,r.cl+'18');hg.addColorStop(1,'#ffffff00');X.fillStyle=hg;X.fillRect(r.x+1,r.y+1,r.w-2,40);X.restore();}/*headerGrad*/if(r._st==='live'){X.save();X.globalAlpha=0.06;var cg=X.createRadialGradient(r.x,r.y,0,r.x,r.y,80);cg.addColorStop(0,r.cl);cg.addColorStop(1,'#ffffff00');X.fillStyle=cg;X.fillRect(r.x,r.y,80,80);var cg2=X.createRadialGradient(r.x+r.w,r.y,0,r.x+r.w,r.y,80);cg2.addColorStop(0,r.cl);cg2.addColorStop(1,'#ffffff00');X.fillStyle=cg2;X.fillRect(r.x+r.w-80,r.y,80,80);X.restore();}/*cornerGlow*/
|
|
// Table
|
|
dTable(r);
|
|
}
|
|
|
|
// === CONNECTIONS ===
|
|
function dC(){
|
|
X.setLineDash([]);
|
|
const s=RM[0];
|
|
for(let i=1;i<RM.length;i++){
|
|
const r=RM[i];
|
|
var x1=s.x+s.w/2,y1=s.y+s.h,x2=r.x+r.w/2,y2=r.y;
|
|
var my=(y1+y2)/2;
|
|
X.strokeStyle=r.cl+'25';X.lineWidth=1.5;
|
|
X.beginPath();X.moveTo(x1,y1);X.quadraticCurveTo(x1,my,x2,y2);X.stroke();
|
|
// Arrow
|
|
X.fillStyle=r.cl+'40';X.beginPath();X.moveTo(x2-4,y2);X.lineTo(x2,y2-6);X.lineTo(x2+4,y2);X.fill();
|
|
X.stroke();
|
|
}
|
|
X.setLineDash([]);
|
|
}
|
|
|
|
// === MAIN ===
|
|
|
|
// === DRAW CHAT TRANSCRIPT below table ===
|
|
function drawChat(r){
|
|
if(!r.chat||!r.chat.length)return;
|
|
var cx=r.x+10,cy=r.y+r.h*0.68;
|
|
var lh=13,maxW=r.w-16;
|
|
// Header
|
|
X.font='700 6px Nunito';X.fillStyle=r.cl+'80';X.textAlign='left';
|
|
X.fillText('TRANSCRIPT · '+new Date().toLocaleDateString('fr-FR',{day:'2-digit',month:'short'}),cx,cy-4);
|
|
cy+=4;
|
|
// Chat messages
|
|
r.chat.forEach(function(m,i){
|
|
var y=cy+i*lh;
|
|
if(y>r.y+r.h-8)return;
|
|
// Emoji
|
|
X.font='9px sans-serif';X.textAlign='left';/*trnColor*/
|
|
X.fillText(m.who,cx,y+1);
|
|
// Message bubble
|
|
X.fillStyle=i%2===0?'#ffffff':'#f4f7fb';
|
|
var tw=Math.min(X.measureText(m.t).width+10,maxW-18);
|
|
X.beginPath();X.roundRect(cx+12,y-7,tw,12,4);X.fill();
|
|
X.strokeStyle='#e2e8f020';X.lineWidth=0.5;X.beginPath();X.roundRect(cx+12,y-7,tw,12,4);X.stroke();
|
|
// Text
|
|
X.font='500 6px Nunito';X.fillStyle='#334155';
|
|
X.fillText(m.t.substring(0,Math.floor(maxW/3.5)),cx+16,y+1);
|
|
});
|
|
}
|
|
|
|
|
|
function drawBubble(r){
|
|
if(!r.chat||!r.chat.length||r._st!=='live')return;
|
|
var ci=Math.floor(tk*0.015)%r.chat.length;
|
|
var msg=r.chat[ci];
|
|
var speaker=r.ag[ci%r.ag.length];
|
|
if(!speaker)return;
|
|
var bx=speaker.px,by=speaker.py-38;
|
|
var txt=msg.t||'';
|
|
if(txt.length>40)txt=txt.substring(0,38)+'...';
|
|
X.save();
|
|
X.font='500 6.5px Nunito';
|
|
var tw=X.measureText(txt).width+12;
|
|
var bw=Math.min(tw,160),bh=16;
|
|
var bLeft=bx-bw/2,bTop=by-bh;
|
|
X.fillStyle='#ffffffee';
|
|
X.strokeStyle=r.cl+'60';
|
|
X.lineWidth=0.8;
|
|
X.beginPath();X.roundRect(bLeft,bTop,bw,bh,[6]);X.fill();X.stroke();
|
|
X.beginPath();X.moveTo(bx-3,by);X.lineTo(bx,by+5);X.lineTo(bx+3,by);X.closePath();X.fillStyle='#ffffffee';X.fill();
|
|
X.strokeStyle=r.cl+'60';X.stroke();
|
|
X.fillStyle='#334155';X.textAlign='center';X.textBaseline='middle';
|
|
X.fillText(txt,bLeft+bw/2,bTop+bh/2);
|
|
X.fillStyle=r.cl;X.font='bold 7px Nunito';
|
|
X.fillText(msg.who,bLeft+8,bTop+bh/2);
|
|
X.restore();
|
|
}
|
|
function drawAmbient(){RM.forEach(function(r){if(r._st!=='live')return;X.save();X.globalAlpha=0.15;for(var i=0;i<6;i++){var px=r.x+20+Math.sin(tk*0.02+i*1.1)*(r.w*0.4)+r.w*0.3;var py=r.y+30+Math.cos(tk*0.015+i*0.8)*(r.h*0.2)+r.h*0.3;X.fillStyle=r.cl;X.beginPath();X.arc(px,py,1.5+Math.sin(tk*0.05+i)*0.5,0,6.28);X.fill();}X.restore();});}
|
|
function drawLinks(){X.save();X.setLineDash([4,4]);X.lineWidth=0.6;X.globalAlpha=0.25;for(var i=1;i<RM.length;i++){var s=RM[0],d=RM[i];var sx=s.x+s.w/2,sy=s.y+s.h,dx=d.x+d.w/2,dy=d.y;X.strokeStyle=d.cl;X.beginPath();X.moveTo(sx,sy);X.bezierCurveTo(sx,sy+30,dx,dy-30,dx,dy);X.stroke();var _tp=(tk*0.008)%1;var _bx=Math.pow(1-_tp,3)*sx+3*Math.pow(1-_tp,2)*_tp*sx+3*(1-_tp)*_tp*_tp*dx+Math.pow(_tp,3)*dx;var _by=Math.pow(1-_tp,3)*sy+3*Math.pow(1-_tp,2)*_tp*(sy+30)+3*(1-_tp)*_tp*_tp*(dy-30)+Math.pow(_tp,3)*dy;X.fillStyle=d.cl;X.beginPath();X.arc(_bx,_by,2.5,0,6.28);X.fill();}X.setLineDash([]);X.restore();}/*bezPulse*/
|
|
function drawMinimap(){var mw=160,mh=90,mx=8,my=(window.scrollY||0)+innerHeight-mh-40;var sx=mw/W,sy=mh/H;X.save();X.globalAlpha=0.8;X.fillStyle=window._isDark?'#1e293bdd':'#ffffffdd';X.strokeStyle=window._isDark?'#475569':'#cbd5e1';X.lineWidth=0.8;X.beginPath();X.roundRect(mx,my,mw,mh,[6]);X.fill();X.stroke();RM.forEach(function(r){X.fillStyle=r._st==='live'?r.cl+'80':r.cl+'30';X.fillRect(mx+r.x*sx,my+r.y*sy,r.w*sx,r.h*sy);X.strokeStyle=r._st==='live'?'#22c55e':r.cl+'50';X.lineWidth=r._st==='live'?1.5:0.4;X.strokeRect(mx+r.x*sx,my+r.y*sy,r.w*sx,r.h*sy);r.ag.forEach(function(a){X.fillStyle=r._st==='live'?'#059669':'#94a3b8';X.beginPath();X.arc(mx+a.px*sx,my+a.py*sy,1.2,0,6.28);X.fill();});});var vy=window.scrollY||0;X.strokeStyle='#ef4444';X.lineWidth=1;X.setLineDash([2,2]);X.strokeRect(mx,my+vy*sy,mw,innerHeight*sy);X.setLineDash([]);X.font='500 5px Nunito';X.fillStyle=window._isDark?'#94a3b8':'#64748b';X.textAlign='left';X.fillText('MINIMAP',mx+4,my+mh-4);X.restore();}
|
|
var _hist=[];function addHist(msg){_hist.unshift({t:new Date().toLocaleTimeString('fr-FR',{hour:'2-digit',minute:'2-digit'}),m:msg});if(_hist.length>5)_hist.pop();}
|
|
function drawHistory(){if(!_hist||!_hist.length)return;var hw=150,hh=70,hx=W-hw-10,hy=(window.scrollY||0)+innerHeight-hh-40;X.save();X.globalAlpha=0.75;X.fillStyle=window._isDark?'#1e293bdd':'#ffffffdd';X.strokeStyle=window._isDark?'#475569':'#cbd5e1';X.lineWidth=0.8;X.beginPath();X.roundRect(hx,hy,hw,hh,[6]);X.fill();X.stroke();X.font='600 5px Nunito';X.fillStyle='#059669';X.textAlign='left';X.fillText('HISTORY',hx+4,hy+10);X.font='400 5px Nunito';X.fillStyle=window._isDark?'#94a3b8':'#64748b';for(var i=0;i<Math.min(_hist.length,4);i++){X.fillText(_hist[i].t+' '+_hist[i].m,hx+4,hy+20+i*12);}X.restore();}
|
|
function draw(){
|
|
tk++;X.clearRect(0,0,W,H);hov=null;
|
|
// Room status based on current hour
|
|
var h=new Date().getHours(),m=new Date().getMinutes();
|
|
RM.forEach(function(r){
|
|
if(r.freq==='Ven 16h') r._st=(new Date().getDay()===5&&h>=16&&h<17)?'live':'next';
|
|
else if(r.freq==='Continu') r._st='live';
|
|
else r._st=(h>=9&&h<10)||(h>=14&&h<15)?'live':'next';
|
|
if(r.freq==='Continu') r._st='live';
|
|
});
|
|
dC();
|
|
drawAmbient();drawLinks();drawMinimap();drawHistory();
|
|
RM.forEach(r=>{dR(r);r.ag.forEach(a=>dA(a,r.cl));drawChat(r);drawBubble(r);});
|
|
// Tooltip
|
|
if(hov){
|
|
const rm=RM.find(r=>r.id===hov.rm);
|
|
TT.style.display='block';
|
|
const sy=window.scrollY||0;
|
|
TT.style.left=Math.min(mx+14,W-270)+'px';
|
|
TT.style.top=Math.max(10,my-140)+'px';
|
|
TT.style.borderColor=rm?rm.cl:'#059669';
|
|
TT.querySelector('b').textContent=hov.re+' '+hov.n;
|
|
TT.querySelector('i').textContent=rm?rm.l:'';
|
|
TT.querySelector('.d').textContent=hov.d;
|
|
TT.querySelector('.m').innerHTML=rm?'<b>Status:</b> '+(rm._st==='live'?'EN COURS':'Prochain')+'<br>'+
|
|
'📎 <b>Obj:</b> '+rm.obj+'<br>⏱ <b>Durée:</b> '+rm.dur+' ('+rm.freq+')'+
|
|
'<br>📋 <b>Sortie:</b> '+rm.concl+'<br>⚡ <b>Actions:</b> '+rm.actions+
|
|
'<br>📌 '+rm.prescr:'';
|
|
}else TT.style.display='none';
|
|
document.getElementById('ht').textContent=new Date().toLocaleTimeString('fr-FR');if(tk%60===0&&document.getElementById('hs'))document.getElementById('hs').style.color=tk%120<60?'#64748b':'#22c55e';if(tk%60===0&&document.getElementById('hs'))document.getElementById('hs').style.color=tk%120<60?'#64748b':'#22c55e';
|
|
var _liveRms=RM.filter(function(r){return r._st==='live'}).length;document.getElementById('hs').textContent='Agents: '+AA.length+' | Rooms: '+RM.length+' | En cours: '+_liveRms;
|
|
requestAnimationFrame(draw);
|
|
}
|
|
|
|
C.addEventListener('mousemove',e=>{mx=e.clientX;my=e.clientY});
|
|
C.addEventListener('click',()=>{if(hov)window.open('/wevia-master.html#'+encodeURIComponent(hov.n),'_blank');});
|
|
|
|
// EMERGENCY
|
|
const EM={infra_down:['CORTEX','Agent Chef','Proactive','Gap Detect','WEVIA Master'],
|
|
security:['Dark Tools','CrowdSec','Authentik','CORTEX','Claude Opus'],
|
|
regression:['NonReg','L99 Visual','L99 Dark','Evolution','WEVIA Master'],
|
|
business:['Paperclip','Enterprise','Ethica','WEVIA Life','Claude Opus'],
|
|
ia_fail:['Ollama','Qdrant','OSS Disc.','CORTEX','WEVIA Master'],
|
|
data_loss:['CORTEX','Agent Chef','Qdrant','Dark Tools','Claude Opus']};
|
|
function openE(){document.getElementById('modal').classList.add('show');autoSel()}
|
|
function closeM(){document.getElementById('modal').classList.remove('show')}
|
|
function autoSel(){
|
|
const t=document.getElementById('et').value,auto=EM[t]||[];
|
|
document.getElementById('ec').innerHTML=AA.map(a=>`<span class="chip ${auto.includes(a.n)?'sel':''}" onclick="this.classList.toggle('sel')">${a.re} ${a.n}</span>`).join('');
|
|
}
|
|
function launchE(){
|
|
const t=document.getElementById('et').value,sel=[...document.querySelectorAll('#ec .chip.sel')].map(c=>c.textContent.trim());
|
|
if(!t||!sel.length)return alert('Choisir type + participants');
|
|
emAct=true;closeM();setTimeout(()=>{emAct=false},60000);
|
|
fetch('/api/wevia-json-api.php',{method:'POST',headers:{'Content-Type':'application/json'},
|
|
body:JSON.stringify({message:'🚨 URGENCE '+t+' — '+sel.join(', ')})}).catch(function(e){console.warn('meeting:',e)});
|
|
}
|
|
function trigD(){fetch('/api/wevia-meeting.php?action=daily').catch(()=>{});alert('📋 Daily lancé')}
|
|
function trigS(){fetch('/api/wevia-meeting.php?action=weekly').catch(()=>{});alert('🏛️ Stratégie lancée')}
|
|
|
|
|
|
// === REAL-TIME DATA POLLING ===
|
|
var LIVE={nr:'—',disk:'—',docker:'—',ethica:'—',uptime:'—'};
|
|
async function fetchLive(){checkNotif();RM.forEach(function(r){if(r.id==='infra')r.kpi=LIVE.disk+'% disk | '+LIVE.docker+' Docker';else if(r.id==='dev')r.kpi='NR:'+LIVE.nr+' | L99:62/64';else if(r.id==='sec')r.kpi='0 CVE | 47 bans';else if(r.id==='biz')r.kpi='132K HCPs | 166 leads';else if(r.id==='ia')r.kpi='9 models | 14K vecs';else if(r.id==='strat')r.kpi='53ag | NR:'+LIVE.nr;else if(r.id==='transit')r.kpi='203 wiki | 15 repos';});
|
|
try{
|
|
var r=await fetch('/api/nonreg-api.php?cat=all');var d=await r.json();
|
|
LIVE.nr=d.pass+'/'+d.total;
|
|
}catch(e){}
|
|
try{
|
|
var r2=await fetch('/api/infra-monitor-api.php');var d2=await r2.json();
|
|
LIVE.disk=(d2.disk||{}).percent||'—';
|
|
LIVE.docker=(d2.docker||{}).count||'—';
|
|
}catch(e){}
|
|
try{
|
|
var r3=await fetch('/api/enterprise-status.php');var d3=await r3.json();
|
|
LIVE.uptime=d3.status||'—';
|
|
}catch(e){}
|
|
// Update room transcripts with live data
|
|
if(RM[1]&&RM[1].chat)RM[1].chat[0]={who:'\U0001f9e0',t:'S204 '+LIVE.disk+'% disk. Docker '+LIVE.docker};
|
|
if(RM[2]&&RM[2].chat)RM[2].chat[0]={who:'\u2705',t:'NonReg '+LIVE.nr+' PASS'};
|
|
// Update header
|
|
var ls=document.getElementById('hs');
|
|
if(ls)ls.textContent='Agents: '+AA.length+' | Rooms: '+RM.length+' | NR: '+LIVE.nr+' | '+LIVE.uptime;
|
|
}
|
|
fetchLive();resize();
|
|
|
|
|
|
|
|
// === REAL-TIME DATA POLLING ===
|
|
var LIVE={nr:'—',disk:'—',docker:'—',ethica:'—',uptime:'—'};
|
|
async function fetchLive(){
|
|
try{
|
|
var r=await fetch('/api/nonreg-api.php?cat=all');var d=await r.json();
|
|
LIVE.nr=d.pass+'/'+d.total;
|
|
}catch(e){}
|
|
try{
|
|
var r2=await fetch('/api/infra-monitor-api.php');var d2=await r2.json();
|
|
LIVE.disk=(d2.disk||{}).percent||'—';
|
|
LIVE.docker=(d2.docker||{}).count||'—';
|
|
}catch(e){}
|
|
try{
|
|
var r3=await fetch('/api/enterprise-status.php');var d3=await r3.json();
|
|
LIVE.uptime=d3.status||'—';
|
|
}catch(e){}
|
|
// Update room transcripts with live data
|
|
if(RM[1]&&RM[1].chat)RM[1].chat[0]={who:'\U0001f9e0',t:'S204 '+LIVE.disk+'% disk. Docker '+LIVE.docker};
|
|
if(RM[2]&&RM[2].chat)RM[2].chat[0]={who:'\u2705',t:'NonReg '+LIVE.nr+' PASS'};
|
|
// Update header
|
|
var ls=document.getElementById('hs');
|
|
if(ls)ls.textContent='Agents: '+AA.length+' | Rooms: '+RM.length+' | NR: '+LIVE.nr+' | '+LIVE.uptime;
|
|
}
|
|
fetchLive();
|
|
setInterval(fetchLive,30000);
|
|
|
|
draw();
|
|
|
|
C.addEventListener('click',function(){window._aClick=true;});
|
|
function showAP(a,cl){var rm=RM.find(function(r){return r.id===a.rm;});var h='<h3 style="color:'+cl+'">'+a.re+' '+a.n+'</h3><p style="color:#64748b;font-size:11px">'+(a.d||'')+'</p><hr style="border:0;border-top:1px solid #e2e8f0;margin:8px 0"><b>Room:</b> '+(rm?rm.l:'?')+'<br><b>Status:</b> '+(rm&&rm._st==='live'?'EN COURS':'PROCHAIN')+'<br>';if(rm&&rm.kpi)h+='<b>KPI:</b> '+rm.kpi+'<br>';h+='<hr style="border:0;border-top:1px solid #e2e8f0;margin:8px 0"><b>Transcript:</b><br>';if(rm&&rm.chat)rm.chat.forEach(function(m){h+='<div style="padding:2px 0;font-size:11px"><b>'+m.who+'</b> '+m.t+'</div>';});document.getElementById('apC').innerHTML=h;document.getElementById('agentPanel').style.display='block';}
|
|
var _lastLive='';function checkNotif(){var live=RM.filter(function(r){return r._st==='live';}).map(function(r){return r.id;}).join(',');if(_lastLive&&live!==_lastLive){var badge=document.createElement('div');badge.className='notifBadge';badge.style.cssText='position:fixed;top:28px;right:10px;background:#059669;color:#fff;padding:4px 10px;border-radius:6px;font:700 10px Nunito;z-index:99;animation:fadeIn .3s';badge.textContent='Room changed: '+live;document.body.appendChild(badge);setTimeout(function(){badge.remove();},4000);}_lastLive=live;}
|
|
|
|
var _dark=false;function toggleDark(){_dark=!_dark;document.body.style.background=_dark?'#0f172a':'#eaeff7';document.body.style.backgroundImage=_dark?'none':'radial-gradient(#c8d4e4 0.4px,transparent 0.4px)';document.getElementById('hud').style.background=_dark?'#1e293bdd':'#fffd';document.getElementById('hud').style.color=_dark?'#e2e8f0':'#1a1a2e';window._isDark=_dark;}
|
|
|
|
var _lastLive='';function checkNotif(){var live=RM.filter(function(r){return r._st==='live';}).map(function(r){return r.id;}).join(',');if(live!==_lastLive&&_lastLive!==''){try{var ac=new AudioContext();var o=ac.createOscillator();var g=ac.createGain();o.connect(g);g.connect(ac.destination);o.frequency.value=800;g.gain.value=0.05;o.start();o.stop(ac.currentTime+0.1);}catch(e){}_lastLive=live;}else{_lastLive=live;}}
|
|
var _hist=[];function addHist(msg){_hist.unshift({t:new Date().toLocaleTimeString('fr-FR',{hour:'2-digit',minute:'2-digit'}),m:msg});if(_hist.length>5)_hist.pop();}
|
|
</script><div id="wLeg" style="position:fixed;bottom:6px;left:50%;transform:translateX(-50%);display:flex;gap:8px;padding:3px 12px;background:#ffffffcc;backdrop-filter:blur(4px);border-radius:6px;border:1px solid #e2e8f0;font:600 7px Nunito,sans-serif;color:#64748b;z-index:90;white-space:nowrap"><span style="color:#059669">Strategy</span><span style="color:#3b82f6">Infra</span><span style="color:#10b981">Dev</span><span style="color:#ef4444">Secu</span><span style="color:#f59e0b">Biz</span><span style="color:#8b5cf6">IA</span><span style="color:#64748b">Transit</span><span style="color:#22c55e;font-size:8px">● LIVE</span></div>
|
|
<div id="agentPanel" style="display:none;position:fixed;right:0;top:0;bottom:0;width:300px;background:#fff;box-shadow:-4px 0 20px #0002;z-index:80;padding:16px;overflow-y:auto;border-left:3px solid #059669;font:13px Nunito"><button onclick="this.parentElement.style.display='none'" style="float:right;border:none;background:none;font-size:18px;cursor:pointer">✕</button><div id="apC"></div></div>
|
|
</body></html>
|