{"id":6172,"date":"2025-10-28T17:49:11","date_gmt":"2025-10-28T10:49:11","guid":{"rendered":"https:\/\/spon.com.vn\/?page_id=6172"},"modified":"2025-10-28T18:48:13","modified_gmt":"2025-10-28T11:48:13","slug":"cong-cu-mo-phong-phong-hop-hoi-nghi-spon","status":"publish","type":"page","link":"https:\/\/spon.com.vn\/?page_id=6172","title":{"rendered":"C\u00f4ng c\u1ee5 m\u00f4 ph\u1ecfng ph\u00f2ng h\u1ecdp h\u1ed9i ngh\u1ecb SPON"},"content":{"rendered":"\t<section class=\"section\" id=\"section_53302000\">\n\t\t<div class=\"bg section-bg fill bg-fill  bg-loaded\" >\n\n\t\t\t\n\t\t\t\n\t\t\t\n\n\t\t<\/div>\n\n\t\t<div class=\"section-content relative\">\n\t\t\t\n<a class=\"button primary expand\"  >\n    <span>C\u00d4NG C\u1ee4 M\u00d4 PH\u1eceNG PH\u00d2NG H\u1eccP H\u1ed8I NGH\u1eca SPON<\/span>\n  <\/a>\n\n\t\t<\/div>\n\n\t\t\n<style>\n#section_53302000 {\n  padding-top: 30px;\n  padding-bottom: 30px;\n}\n<\/style>\n\t<\/section>\n\t\n<div class=\"spon-conference-container\">\n<div class=\"container\">\n  <div class=\"sidebar\">\n    <h2>Ph\u00f2ng H\u1ed9i Ngh\u1ecb SPON<\/h2>\n    <label>Chi\u1ec1u d\u00e0i (m):<\/label><input type=\"number\" id=\"len\" value=\"12\">\n    <label>Chi\u1ec1u r\u1ed9ng (m):<\/label><input type=\"number\" id=\"wid\" value=\"8\">\n    <label>S\u1ed1 gh\u1ebf \u0111\u1ea1i bi\u1ec3u:<\/label><input type=\"number\" id=\"chairs\" value=\"10\">\n    <label>S\u1ed1 micro Ch\u1ee7 t\u1ecbch (\u22646):<\/label><input type=\"number\" id=\"chair\" value=\"1\" min=\"1\" max=\"6\">\n    <label>Lo\u1ea1i b\u00e0n:<\/label>\n    <select id=\"table\">\n      <option value=\"rectangle\">B\u00e0n ch\u1eef nh\u1eadt<\/option>\n      <option value=\"circle\">B\u00e0n tr\u00f2n<\/option>\n    <\/select>\n    <label>Lo\u1ea1i loa:<\/label>\n    <select id=\"spktype\" onchange=\"updatePower()\">\n      <option value=\"wall\">Loa h\u1ed9p SPON<\/option>\n      <option value=\"ceiling\">Loa \u00e2m tr\u1ea7n SPON<\/option>\n    <\/select>\n    <label>C\u00f4ng su\u1ea5t loa (W):<\/label><select id=\"power\"><\/select>\n    <button onclick=\"drawRoom()\">V\u1ebd s\u01a1 \u0111\u1ed3<\/button>\n    <button onclick=\"exportDoc()\">Xu\u1ea5t b\u00e1o c\u00e1o DOC<\/button>\n  <\/div>\n  <!-- Gi\u1eef nguy\u00ean \u0111\u00fang v\u1ecb tr\u00ed ph\u1ea7n SVG, ch\u1ec9 th\u00eam preserveAspectRatio -->\n  <svg id=\"room\" viewBox=\"0 0 1200 980\" preserveAspectRatio=\"xMidYMid meet\"><\/svg>\n<\/div>\n<div class=\"report\" id=\"report\"><\/div>\n\n<script>\n  \/* --- Gi\u1eef nguy\u00ean to\u00e0n b\u1ed9 JS g\u1ed1c, KH\u00d4NG \u0111\u1ed5i t\u00ean bi\u1ebfn\/h\u00e0m --- *\/\n  const svgNS='http:\/\/www.w3.org\/2000\/svg';\n  const svg=document.getElementById('room');\n  let clipId=0; let summary={};\n\n  function el(n,a){const e=document.createElementNS(svgNS,n);for(const k in a)e.setAttribute(k,a[k]);return e}\n  function clear(){while(svg.firstChild)svg.removeChild(svg.firstChild)}\n  function $(i){return document.getElementById(i)}\n\n  \/\/ ===== Power options nh\u01b0 b\u1ea3n c\u0169\n  function updatePower(){\n    const t=$('spktype').value;\n    const s=$('power'); s.innerHTML='';\n    (t==='wall'?[15,30,60,100]:[6,10,15,30]).forEach(p=>{\n      const o=document.createElement('option'); o.value=p; o.textContent=p+'W'; s.appendChild(o);\n    });\n  }\n  updatePower();\n\n  function drawRoom(){\n    clear();\n    const defs=getDefs();\n\n    \/\/ Gradient cho s\u00f3ng tr\u00f2n (gi\u1eef cho loa \u00e2m tr\u1ea7n, camera)\n    const grad=el('radialGradient',{id:'waveGradient'});\n    grad.appendChild(el('stop',{offset:'0%','stop-color':'#007ACC','stop-opacity':'0.4'}));\n    grad.appendChild(el('stop',{offset:'100%','stop-color':'#007ACC','stop-opacity':'0'}));\n    defs.appendChild(grad);\n\n    const L=+$('len').value, W=+$('wid').value, ch=+$('chairs').value, cm=Math.min(+$('chair').value,6);\n    const tbl=$('table').value, tp=$('spktype').value, pw=+$('power').value;\n\n    \/\/ Khung ph\u00f2ng\n    svg.appendChild(el('rect',{x:50,y:50,width:1100,height:600,fill:'none',stroke:'#007ACC','stroke-width':4,rx:10}));\n\n    \/\/ B\u00e0n & micro\n    if(tbl==='rectangle'){\n      svg.appendChild(el('rect',{x:300,y:250,width:600,height:200,fill:'#eaf2ff',stroke:'#004c99','stroke-width':2,rx:10}));\n      drawRect(ch,cm);\n    }else{\n      svg.appendChild(el('circle',{cx:600,cy:350,r:150,fill:'#eaf2ff',stroke:'#004c99','stroke-width':2}));\n      drawCircle(ch,cm,600,350,150);\n    }\n\n    \/\/ Loa & hi\u1ec7u \u1ee9ng\n    const spkCount = (tp==='ceiling') ? drawCeiling(pw,L,W) : drawWall(pw,L,W);\n\n    \/\/ Camera + wedge\n    drawCamera();\n\n    \/\/ S\u01a1 \u0111\u1ed3 k\u1ebft n\u1ed1i d\u01b0\u1edbi c\u00f9ng\n    drawConnectionDiagram(ch,cm,spkCount,tp);\n\n    \/\/ B\u00e1o c\u00e1o\n    summary={L,W,area:L*W,table:tbl,type:tp,power:pw,speakerCount:spkCount,chairMic:cm,chairs:ch};\n    report();\n  }\n\n  \/\/ ========================== GH\u1ebe & MICRO =============================\n  function drawRect(ch,cm){\n    const top=Math.ceil(ch\/2),bot=ch-top,gt=600\/(top+1),gb=600\/(bot+1);\n    for(let i=0;i<top;i++){drawChair(300+gt*(i+1),210);drawMic(300+gt*(i+1),250);}\n    for(let i=0;i<bot;i++){drawChair(300+gb*(i+1),490);drawMic(300+gb*(i+1),450);}\n    if(cm===1){drawChair(270,350);drawMic(320,350);}\n    else{const st=270,sp=160\/(cm-1||1);for(let i=0;i<cm;i++){drawChair(270,st+sp*i);drawMic(320,st+sp*i);}}\n  }\n\n  function drawCircle(ch,cm,cx,cy,r){\n    const total=ch+cm;if(total<=0)return;\n    const radius=r+60;const step=(2*Math.PI)\/total;const start=-Math.PI\/2;\n    for(let i=0;i<total;i++){\n      const a=start+i*step;\n      const x=cx+Math.cos(a)*radius;const y=cy+Math.sin(a)*radius;\n      drawChair(x,y);\n      const xm=cx+Math.cos(a)*(r-10),ym=cy+Math.sin(a)*(r-10);\n      drawMic(xm,ym);\n    }\n  }\n\n  \/\/ ============= ICON SVG ===================\n  function drawChair(x,y){\n    const g=el('g',{transform:`translate(${x-15},${y-20})`});\n    g.appendChild(el('rect',{x:0,y:10,width:30,height:25,rx:5,fill:'#007ACC'}));\n    g.appendChild(el('rect',{x:5,y:0,width:20,height:10,rx:3,fill:'#99ccff'}));\n    svg.appendChild(g);\n  }\n  function drawMic(x,y){\n    const g=el('g',{transform:`translate(${x-10},${y-25})`});\n    g.appendChild(el('rect',{x:6,y:20,width:8,height:10,fill:'#333'}));\n    g.appendChild(el('line',{x1:10,y1:20,x2:10,y2:5,stroke:'#111','stroke-width':2}));\n    g.appendChild(el('circle',{cx:10,cy:4,r:3,fill:'#222'}));\n    svg.appendChild(g);\n  }\n\n  \/\/ ========================== LOA ============================\n  function drawSpeaker(x,y,id){\n    const g=el('g',{transform:`translate(${x-12},${y-12})`});\n    g.appendChild(el('rect',{x:0,y:0,width:24,height:24,rx:4,fill:'#ffa500',stroke:'#cc7a00','stroke-width':1.5}));\n    g.appendChild(el('circle',{cx:12,cy:12,r:4,fill:'#fff'}));\n    svg.appendChild(g);\n    const t=el('text',{x,y:y-15,class:'label'});t.textContent=id;svg.appendChild(t);\n  }\n  function getSpacingCeiling(p){if(p<=6)return 4;if(p<=10)return 6;if(p<=15)return 8;return 10;}\n  function drawCeiling(p,L,W){\n    const spacing=getSpacingCeiling(p);\n    const cols=Math.max(1,Math.ceil(L\/spacing));\n    const rows=Math.max(1,Math.ceil(W\/spacing));\n    const dx=1000\/(cols+1),dy=500\/(rows+1);\n    let c=0;\n    for(let i=1;i<=cols;i++){\n      for(let j=1;j<=rows;j++){\n        const x=150+i*dx,y=100+j*dy;\n        drawSpeaker(x,y,'S'+(++c));\n        pulse(x,y,35+p*1.8); \/\/ s\u00f3ng tr\u00f2n nh\u1eb9 cho loa \u00e2m tr\u1ea7n\n      }\n    }\n    return c;\n  }\n\n  \/\/ ===================== LOA H\u1ed8P (S\u00f3ng 180\u00b0 h\u01b0\u1edbng v\u1ec1 b\u00e0n) ======================\n  function drawWall(p,L,W){\n    const cxTable = 600, cyTable = 350; \/\/ t\u00e2m b\u00e0n h\u1ecdp \u1edf gi\u1eefa ph\u00f2ng\n    const long = L >= 2 * W;\n    const area = L * W;\n    const est = Math.ceil(area \/ getCov('wall', p));\n    const side = Math.ceil(est \/ 2);\n    let c = 0, id = 1;\n    const len = 120 + p * 2; \/\/ t\u1ea7m lan s\u00f3ng\n\n    if (long) {\n      const dx = 1000 \/ (side + 1);\n      for (let i = 1; i <= side; i++) {\n        const x = 100 + i * dx;\n        const yTop = 120, yBot = 580;\n        drawSpeaker(x, yTop, 'S' + id++);\n        drawDirectionalWave180ToTable(x, yTop, cxTable, cyTable, len);\n        drawSpeaker(x, yBot, 'S' + id++);\n        drawDirectionalWave180ToTable(x, yBot, cxTable, cyTable, len);\n        c += 2;\n      }\n    } else {\n      const dy = 500 \/ (side + 1);\n      for (let i = 1; i <= side; i++) {\n        const y = 100 + i * dy;\n        drawSpeaker(120, y, 'S' + id++);\n        drawDirectionalWave180ToTable(120, y, cxTable, cyTable, len);\n        drawSpeaker(1080, y, 'S' + id++);\n        drawDirectionalWave180ToTable(1080, y, cxTable, cyTable, len);\n        c += 2;\n      }\n    }\n    return c;\n  }\n\n  \/\/ \ud83c\udfa7 S\u00f3ng g\u1ee3n tr\u00f2n 180\u00b0 H\u01af\u1edaNG V\u1ec0 B\u00c0N: \u0111\u1eadm g\u1ea7n loa -> m\u1edd d\u1ea7n -> bi\u1ebfn m\u1ea5t\n  function drawDirectionalWave180ToTable(x, y, tx, ty, maxLen){\n    const defs = getDefs();\n\n    \/\/ G\u00f3c h\u01b0\u1edbng t\u1eeb loa t\u1edbi t\u00e2m b\u00e0n\n    const dir = Math.atan2(ty - y, tx - x);\n\n    \/\/ Gradient ri\u00eang cho m\u1ed7i c\u1ee5m s\u00f3ng\n    const gradId = 'grad' + (++clipId);\n    const grad = el('radialGradient', { id: gradId, cx: '50%', cy: '50%', r: '50%' });\n    grad.appendChild(el('stop', { offset: '0%', 'stop-color': '#007ACC', 'stop-opacity': 1 }));\n    grad.appendChild(el('stop', { offset: '55%', 'stop-color': '#007ACC', 'stop-opacity': 0.5 }));\n    grad.appendChild(el('stop', { offset: '100%', 'stop-color': '#007ACC', 'stop-opacity': 0.05 }));\n    defs.appendChild(grad);\n\n    \/\/ T\u00e2m c\u00e1c cung s\u00f3ng d\u1ecbch nh\u1eb9 theo h\u01b0\u1edbng ph\u00e1t \u0111\u1ec3 nh\u00ecn t\u1ef1 nhi\u00ean\n    const cx = x + Math.cos(dir) * 14;\n    const cy = y + Math.sin(dir) * 14;\n\n    \/\/ V\u1ebd 4 cung tr\u00f2n 180\u00b0 ph\u00eda tr\u01b0\u1edbc, lan d\u1ea7n v\u00e0 m\u1edd d\u1ea7n\n    for(let k=0;k<4;k++){\n      const r0 = 20 + k * 20;\n      const p = el('path', {\n        d: describeArc(cx, cy, r0, dir - Math.PI\/2, dir + Math.PI\/2),\n        stroke: `url(#${gradId})`,\n        'stroke-width': 8,\n        'stroke-linecap': 'round',\n        fill: 'none',\n        opacity: 0.6\n      });\n      \/\/ L\u01b0u tham s\u1ed1 \u0111\u1ec3 animate \u0111\u00fang h\u01b0\u1edbng\n      p.dataset.cx = cx; p.dataset.cy = cy; p.dataset.dir = dir; p.dataset.r0 = r0; p.dataset.max = maxLen;\n      svg.appendChild(p);\n      animateFadeWaveDir(p);\n    }\n  }\n\n  \/\/ Cung tr\u00f2n 180\u00b0 theo h\u01b0\u1edbng dir\n  function describeArc(x,y,r,start,end){\n    const s = polar(x,y,r,end), e = polar(x,y,r,start);\n    const largeFlag = (end - start) > Math.PI ? 1 : 0;\n    return `M${s.x},${s.y} A${r},${r} 0 ${largeFlag},0 ${e.x},${e.y}`;\n  }\n  function polar(cx,cy,r,a){return {x:cx+r*Math.cos(a), y:cy+r*Math.sin(a)};}\n\n  \/\/ Hi\u1ec7u \u1ee9ng: t\u0103ng b\u00e1n k\u00ednh + gi\u1ea3m opacity; khi qu\u00e1 t\u1ea7m th\u00ec reset (s\u00f3ng bi\u1ebfn m\u1ea5t)\n  function animateFadeWaveDir(elm){\n    let r = parseFloat(elm.dataset.r0), op = 0.6;\n    const cx = parseFloat(elm.dataset.cx), cy = parseFloat(elm.dataset.cy);\n    const dir = parseFloat(elm.dataset.dir), maxR = parseFloat(elm.dataset.max);\n    const start = () => {\n      const tick = () => {\n        r += 2; op -= 0.01;\n        if (r > maxR || op <= 0){\n          r = parseFloat(elm.dataset.r0); op = 0.6; \/\/ reset v\u00f2ng s\u00f3ng\n        }\n        const d = describeArc(cx, cy, r, dir - Math.PI\/2, dir + Math.PI\/2);\n        elm.setAttribute('d', d);\n        elm.setAttribute('opacity', op);\n      };\n      setInterval(tick, 35);\n    };\n    \/\/ tr\u1ec5 nh\u1ecf \u0111\u1ec3 c\u00e1c g\u1ee3n l\u1ec7ch pha\n    setTimeout(start, Math.random()*250);\n  }\n\n  \/\/ ======================= CAMERA + QU\u00c9T ==========================\n  function drawCamera(){\n    const x=1080,y=350;\n    const g=el('g',{});\n    g.appendChild(el('circle',{cx:x,cy:y,r:14,fill:'#000'}));\n    g.appendChild(el('circle',{cx:x,cy:y,r:6,fill:'#00aaff'}));\n    svg.appendChild(g);\n    const t=el('text',{x:x,y:y+30,class:'device-label'});t.textContent=\"Camera PTZ\";svg.appendChild(t);\n\n    \/\/ Wedge scan gi\u1ed1ng b\u1ea3n c\u0169\n    const cp='cam'+(++clipId),defs=getDefs();\n    const p=el('clipPath',{id:cp});\n    p.appendChild(el('path',{d:`M${x},${y} L${x-120},${y-90} L${x-120},${y+90} Z`}));\n    defs.appendChild(p);\n    const cx=x-60,cy=y,maxR=120;\n    for(let k=0;k<3;k++){const c=el('circle',{cx,cy,r:0,class:'wave'});\n      c.setAttribute('clip-path',`url(#${cp})`);svg.appendChild(c);pulseE(c,maxR,k*220);}\n  }\n\n  \/\/ ======================== HI\u1ec6U \u1ee8NG CHUNG ========================\n  function getDefs(){let d=svg.querySelector('defs');if(!d){d=el('defs',{});svg.appendChild(d);}return d;}\n  function pulse(x,y,r){const c=el('circle',{cx:x,cy:y,r:0,class:'wave'});svg.appendChild(c);pulseE(c,r,0);}\n  function pulseE(c,m,del){let r=0;setTimeout(()=>{setInterval(()=>{r+=2;if(r>m)r=0;c.setAttribute('r',r);},35);},del);}\n  function getCov(t,p){if(t==='ceiling'){if(p<=6)return 25;if(p<=10)return 35;if(p<=15)return 50;return 70;}else{if(p<=15)return 40;if(p<=30)return 60;if(p<=60)return 80;return 120;}}\n\n  \/\/ =================== S\u01a0 \u0110\u1ed2 K\u1ebeT N\u1ed0I (gi\u1eef nguy\u00ean bi\u1ec3u t\u01b0\u1ee3ng & d\u00e2y t\u0129nh) ===================\n  function drawConnectionDiagram(ch,cm,sc,tp){\n    const baseY=700, centerX=600;\n\n    \/\/ Ph\u00e2n c\u00e1ch + ti\u00eau \u0111\u1ec1\n    svg.appendChild(el('line',{x1:60,y1:660,x2:1140,y2:660,stroke:'#e5eef8','stroke-width':2}));\n    const title=el('text',{x:600,y:680,'text-anchor':'middle',fill:'#004c99','font-size':'14','font-weight':'bold'});\n    title.textContent='S\u01a1 \u0111\u1ed3 k\u1ebft n\u1ed1i h\u1ec7 th\u1ed1ng'; svg.appendChild(title);\n\n    const devices=[\n      {x:centerX-400,y:baseY,label:`${ch+cm}x Micro`,icon:drawIconMic},\n      {x:centerX-200,y:baseY+70,label:'LCM-6010',icon:drawIconCtrl},\n      {x:centerX,y:baseY+70,label:'SAP-F88E',icon:drawIconProc},\n      {x:centerX+200,y:baseY+70,label:'Amply',icon:drawIconAmp},\n      {x:centerX+400,y:baseY,label:`${sc}x Loa SPON`,icon:drawIconSpeaker}\n    ];\n\n    \/\/ D\u00e2y n\u1ed1i cong m\u1ec1m, t\u0129nh\n    const pathG=el('g',{});\n    for(let i=0;i<devices.length-1;i++){\n      const d1=devices[i],d2=devices[i+1];\n      const mx=(d1.x+d2.x)\/2;\n      const p=`M${d1.x},${d1.y} C${mx},${d1.y-40} ${mx},${d2.y-40} ${d2.x},${d2.y}`;\n      pathG.appendChild(el('path',{d:p,stroke:'#007ACC','stroke-width':2,fill:'none'}));\n    }\n    svg.appendChild(pathG);\n\n    \/\/ Camera PTZ \u2192 LCM-6010 (\u0111\u01b0\u1eddng n\u00e9t \u0111\u1ee9t)\n    const camX=1080, camY=350;\n    const ctrlX=centerX-200, ctrlY=baseY+70;\n    const mx=(camX+ctrlX)\/2;\n    const pathCam=`M${camX},${camY} C${mx},${camY+100} ${mx},${ctrlY-100} ${ctrlX},${ctrlY}`;\n    pathG.appendChild(el('path',{\n      d:pathCam, stroke:'#007ACC','stroke-width':1.8, fill:'none', 'stroke-dasharray':'5,4'\n    }));\n    const lbl=el('text',{\n      x:(camX+ctrlX)\/2, y:(camY+ctrlY)\/2-10, 'text-anchor':'middle', fill:'#004c99','font-size':'10'\n    });\n    lbl.textContent='\u0110i\u1ec1u khi\u1ec3n PTZ'; svg.appendChild(lbl);\n\n    \/\/ V\u1ebd icon + nh\u00e3n\n    devices.forEach(d=>{\n      d.icon(d.x,d.y);\n      const t=el('text',{x:d.x,y:d.y+45,class:'device-label'}); t.textContent=d.label; svg.appendChild(t);\n    });\n  }\n\n  \/\/ ======= ICON VECTOR (gi\u1eef ki\u1ec3u c\u0169) ========\n  function drawIconMic(x,y){\n    const g=el('g',{transform:`translate(${x-12},${y-20})`});\n    g.appendChild(el('rect',{x:8,y:12,width:8,height:12,rx:3,fill:'#444'}));\n    g.appendChild(el('line',{x1:12,y1:12,x2:12,y2:4,stroke:'#111','stroke-width':2}));\n    g.appendChild(el('circle',{cx:12,cy:3,r:3,fill:'#222'}));\n    svg.appendChild(g);\n  }\n  function drawIconCtrl(x,y){\n    const g=el('g',{transform:`translate(${x-24},${y-16})`});\n    g.appendChild(el('rect',{x:0,y:0,width:48,height:32,rx:4,fill:'#004c99'}));\n    g.appendChild(el('circle',{cx:12,cy:16,r:3,fill:'#fff'}));\n    g.appendChild(el('circle',{cx:24,cy:16,r:3,fill:'#fff'}));\n    g.appendChild(el('circle',{cx:36,cy:16,r:3,fill:'#fff'}));\n    svg.appendChild(g);\n  }\n  function drawIconProc(x,y){\n    const g=el('g',{transform:`translate(${x-22},${y-14})`});\n    g.appendChild(el('rect',{x:0,y:0,width:44,height:28,rx:4,fill:'#2288cc'}));\n    g.appendChild(el('rect',{x:8,y:6,width:4,height:16,fill:'#fff'}));\n    g.appendChild(el('rect',{x:18,y:6,width:4,height:16,fill:'#fff'}));\n    g.appendChild(el('rect',{x:28,y:6,width:4,height:16,fill:'#fff'}));\n    svg.appendChild(g);\n  }\n  function drawIconAmp(x,y){\n    const g=el('g',{transform:`translate(${x-22},${y-14})`});\n    g.appendChild(el('rect',{x:0,y:0,width:44,height:28,rx:3,fill:'#999'}));\n    g.appendChild(el('circle',{cx:12,cy:14,r:5,fill:'#333'}));\n    g.appendChild(el('circle',{cx:32,cy:14,r:5,fill:'#333'}));\n    svg.appendChild(g);\n  }\n  function drawIconSpeaker(x,y){\n    const g=el('g',{transform:`translate(${x-16},${y-16})`});\n    g.appendChild(el('rect',{x:0,y:0,width:32,height:32,rx:6,fill:'#ff9933'}));\n    g.appendChild(el('circle',{cx:16,cy:16,r:6,fill:'#fff'}));\n    svg.appendChild(g);\n  }\n\n  \/\/ ======================= B\u00c1O C\u00c1O =========================\n  function report(){\n    const {L,W,table,type,power,speakerCount,chairMic,chairs}=summary;\n    const total=power*speakerCount;\n    document.getElementById('report').innerHTML=`<h3>\ud83d\udccb D\u1ef1 to\u00e1n thi\u1ebft b\u1ecb & th\u00f4ng tin h\u1ec7 th\u1ed1ng<\/h3>\n    <p><b>Ph\u00f2ng:<\/b> ${L}\u00d7${W} m \u2014 <b>B\u00e0n:<\/b> ${table}<\/p>\n    <p><b>Loa:<\/b> ${speakerCount} c\u00e1i (${type==='wall'?'Loa h\u1ed9p SPON':'Loa \u00e2m tr\u1ea7n SPON'}) \u2014 ${power} W\/loa \u2192 <b>T\u1ed5ng ${total} W<\/b><\/p>\n    <table><tr><th>Thi\u1ebft b\u1ecb<\/th><th>M\u00f4 t\u1ea3<\/th><th>S\u1ed1 l\u01b0\u1ee3ng<\/th><\/tr>\n    <tr><td>${type==='wall'?'Loa h\u1ed9p SPON':'Loa \u00e2m tr\u1ea7n SPON'}<\/td><td>Ph\u00e2n b\u1ed1 theo s\u01a1 \u0111\u1ed3<\/td><td>${speakerCount}<\/td><\/tr>\n    <tr><td>Micro Ch\u1ee7 t\u1ecbch & \u0110\u1ea1i bi\u1ec3u<\/td><td>LCM-6013<\/td><td>${chairMic+chairs}<\/td><\/tr>\n    <tr><td>Trung t\u00e2m \u0111i\u1ec1u khi\u1ec3n<\/td><td>LCM-6010<\/td><td>1<\/td><\/tr>\n    <tr><td>B\u1ed9 x\u1eed l\u00fd ch\u1ed1ng h\u00fa<\/td><td>SAP-F88E<\/td><td>1<\/td><\/tr>\n    <tr><td>Camera PTZ<\/td><td>G\u00f3c qu\u00e9t 90\u00b0 (b\u00ean ph\u1ea3i ph\u00f2ng)<\/td><td>1<\/td><\/tr>\n    <tr><td>B\u1ed9 khu\u1ebfch \u0111\u1ea1i<\/td><td>Ph\u00f9 h\u1ee3p t\u1ed5ng ${total} W<\/td><td>1<\/td><\/tr><\/table>`;\n  }\n\n  \/\/ =================== XU\u1ea4T WORD =====================\n  function svgToPng(cb){\n    const clone=svg.cloneNode(true);\n    const s=document.createElement('style');\n    s.textContent='.wave{fill:url(#waveGradient)}.label{font-size:10px;fill:#333;text-anchor:middle}.device-label{font-size:12px;fill:#222;text-anchor:middle;font-weight:bold}';\n    clone.insertBefore(s,clone.firstChild);\n    const xml=new XMLSerializer().serializeToString(clone);\n    const b=new Blob([xml],{type:'image\/svg+xml'});\n    const u=URL.createObjectURL(b);\n    const img=new Image();\n    img.onload=()=>{\n      const c=document.createElement('canvas');\n      c.width=1200; c.height=980; \/\/ \u0111\u1ee7 chi\u1ec1u cao ch\u1ee9a s\u01a1 \u0111\u1ed3 k\u1ebft n\u1ed1i\n      const ctx=c.getContext('2d');\n      ctx.fillStyle='#fff'; ctx.fillRect(0,0,1200,980);\n      ctx.drawImage(img,0,0);\n      URL.revokeObjectURL(u);\n      cb(c.toDataURL('image\/png'));\n    };\n    img.src=u;\n  }\n\n  function exportDoc(){\n    svgToPng(png=>{\n      const rep=document.getElementById('report').innerHTML;\n      const html=`<!DOCTYPE html><html><head><meta charset='utf-8'><\/head><body data-rsssl=1>\n      <h2>B\u00c1O C\u00c1O PH\u00d2NG H\u1ed8I NGH\u1eca SPON<\/h2>\n      <img src='${png}' style='width:900px;border:1px solid #ddd'>\n      <div>${rep}<\/div>\n<\/div>\n    \n","protected":false},"excerpt":{"rendered":"","protected":false},"author":3,"featured_media":6173,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v17.0 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>C\u00f4ng c\u1ee5 m\u00f4 ph\u1ecfng ph\u00f2ng h\u1ecdp h\u1ed9i ngh\u1ecb SPON - NH\u00c0 NH\u1eacP KH\u1ea8U \u00c2M THANH SPON<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/spon.com.vn\/?page_id=6172\" \/>\n<meta property=\"og:locale\" content=\"vi_VN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"C\u00f4ng c\u1ee5 m\u00f4 ph\u1ecfng ph\u00f2ng h\u1ecdp h\u1ed9i ngh\u1ecb SPON - NH\u00c0 NH\u1eacP KH\u1ea8U \u00c2M THANH SPON\" \/>\n<meta property=\"og:url\" content=\"https:\/\/spon.com.vn\/?page_id=6172\" \/>\n<meta property=\"og:site_name\" content=\"NH\u00c0 NH\u1eacP KH\u1ea8U \u00c2M THANH SPON\" \/>\n<meta property=\"article:modified_time\" content=\"2025-10-28T11:48:13+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/spon.com.vn\/wp-content\/uploads\/2025\/10\/mo-phong.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1391\" \/>\n\t<meta property=\"og:image:height\" content=\"908\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https:\/\/spon.com.vn\/#organization\",\"name\":\"Thi\\u00ean \\u00c2n JSC - Uy T\\u00edn T\\u1ea1o Th\\u01b0\\u01a1ng Hi\\u1ec7u\",\"url\":\"https:\/\/spon.com.vn\/\",\"sameAs\":[],\"logo\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/spon.com.vn\/#logo\",\"inLanguage\":\"vi\",\"url\":\"https:\/\/spon.com.vn.com\/wp-content\/uploads\/2021\/09\/logo-web-thienan-new-1.png\",\"contentUrl\":\"https:\/\/spon.com.vn.com\/wp-content\/uploads\/2021\/09\/logo-web-thienan-new-1.png\",\"width\":200,\"height\":202,\"caption\":\"Thi\\u00ean \\u00c2n JSC - Uy T\\u00edn T\\u1ea1o Th\\u01b0\\u01a1ng Hi\\u1ec7u\"},\"image\":{\"@id\":\"https:\/\/spon.com.vn\/#logo\"}},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/spon.com.vn\/#website\",\"url\":\"https:\/\/spon.com.vn\/\",\"name\":\"NH\\u00c0 NH\\u1eacP KH\\u1ea8U \\u00c2M THANH SPON\",\"description\":\"S\\u1ea2N PH\\u1ea8M CH\\u00c1T L\\u01af\\u1ee2NG CAO\",\"publisher\":{\"@id\":\"https:\/\/spon.com.vn\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/spon.com.vn\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"vi\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/spon.com.vn\/?page_id=6172#primaryimage\",\"inLanguage\":\"vi\",\"url\":\"https:\/\/spon.com.vn\/wp-content\/uploads\/2025\/10\/mo-phong.png\",\"contentUrl\":\"https:\/\/spon.com.vn\/wp-content\/uploads\/2025\/10\/mo-phong.png\",\"width\":1391,\"height\":908},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/spon.com.vn\/?page_id=6172#webpage\",\"url\":\"https:\/\/spon.com.vn\/?page_id=6172\",\"name\":\"C\\u00f4ng c\\u1ee5 m\\u00f4 ph\\u1ecfng ph\\u00f2ng h\\u1ecdp h\\u1ed9i ngh\\u1ecb SPON - NH\\u00c0 NH\\u1eacP KH\\u1ea8U \\u00c2M THANH SPON\",\"isPartOf\":{\"@id\":\"https:\/\/spon.com.vn\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/spon.com.vn\/?page_id=6172#primaryimage\"},\"datePublished\":\"2025-10-28T10:49:11+00:00\",\"dateModified\":\"2025-10-28T11:48:13+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/spon.com.vn\/?page_id=6172#breadcrumb\"},\"inLanguage\":\"vi\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/spon.com.vn\/?page_id=6172\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/spon.com.vn\/?page_id=6172#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Trang ch\\u1ee7\",\"item\":\"https:\/\/spon.com.vn\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"C\\u00f4ng c\\u1ee5 m\\u00f4 ph\\u1ecfng ph\\u00f2ng h\\u1ecdp h\\u1ed9i ngh\\u1ecb SPON\"}]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"C\u00f4ng c\u1ee5 m\u00f4 ph\u1ecfng ph\u00f2ng h\u1ecdp h\u1ed9i ngh\u1ecb SPON - NH\u00c0 NH\u1eacP KH\u1ea8U \u00c2M THANH SPON","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/spon.com.vn\/?page_id=6172","og_locale":"vi_VN","og_type":"article","og_title":"C\u00f4ng c\u1ee5 m\u00f4 ph\u1ecfng ph\u00f2ng h\u1ecdp h\u1ed9i ngh\u1ecb SPON - NH\u00c0 NH\u1eacP KH\u1ea8U \u00c2M THANH SPON","og_url":"https:\/\/spon.com.vn\/?page_id=6172","og_site_name":"NH\u00c0 NH\u1eacP KH\u1ea8U \u00c2M THANH SPON","article_modified_time":"2025-10-28T11:48:13+00:00","og_image":[{"width":1391,"height":908,"url":"https:\/\/spon.com.vn\/wp-content\/uploads\/2025\/10\/mo-phong.png","path":"\/home\/yeusu618\/public_html\/wp-content\/uploads\/2025\/10\/mo-phong.png","size":"full","id":"6173","alt":"","pixels":1263028,"type":"image\/png"}],"twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Organization","@id":"https:\/\/spon.com.vn\/#organization","name":"Thi\u00ean \u00c2n JSC - Uy T\u00edn T\u1ea1o Th\u01b0\u01a1ng Hi\u1ec7u","url":"https:\/\/spon.com.vn\/","sameAs":[],"logo":{"@type":"ImageObject","@id":"https:\/\/spon.com.vn\/#logo","inLanguage":"vi","url":"https:\/\/spon.com.vn.com\/wp-content\/uploads\/2021\/09\/logo-web-thienan-new-1.png","contentUrl":"https:\/\/spon.com.vn.com\/wp-content\/uploads\/2021\/09\/logo-web-thienan-new-1.png","width":200,"height":202,"caption":"Thi\u00ean \u00c2n JSC - Uy T\u00edn T\u1ea1o Th\u01b0\u01a1ng Hi\u1ec7u"},"image":{"@id":"https:\/\/spon.com.vn\/#logo"}},{"@type":"WebSite","@id":"https:\/\/spon.com.vn\/#website","url":"https:\/\/spon.com.vn\/","name":"NH\u00c0 NH\u1eacP KH\u1ea8U \u00c2M THANH SPON","description":"S\u1ea2N PH\u1ea8M CH\u00c1T L\u01af\u1ee2NG CAO","publisher":{"@id":"https:\/\/spon.com.vn\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/spon.com.vn\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"vi"},{"@type":"ImageObject","@id":"https:\/\/spon.com.vn\/?page_id=6172#primaryimage","inLanguage":"vi","url":"https:\/\/spon.com.vn\/wp-content\/uploads\/2025\/10\/mo-phong.png","contentUrl":"https:\/\/spon.com.vn\/wp-content\/uploads\/2025\/10\/mo-phong.png","width":1391,"height":908},{"@type":"WebPage","@id":"https:\/\/spon.com.vn\/?page_id=6172#webpage","url":"https:\/\/spon.com.vn\/?page_id=6172","name":"C\u00f4ng c\u1ee5 m\u00f4 ph\u1ecfng ph\u00f2ng h\u1ecdp h\u1ed9i ngh\u1ecb SPON - NH\u00c0 NH\u1eacP KH\u1ea8U \u00c2M THANH SPON","isPartOf":{"@id":"https:\/\/spon.com.vn\/#website"},"primaryImageOfPage":{"@id":"https:\/\/spon.com.vn\/?page_id=6172#primaryimage"},"datePublished":"2025-10-28T10:49:11+00:00","dateModified":"2025-10-28T11:48:13+00:00","breadcrumb":{"@id":"https:\/\/spon.com.vn\/?page_id=6172#breadcrumb"},"inLanguage":"vi","potentialAction":[{"@type":"ReadAction","target":["https:\/\/spon.com.vn\/?page_id=6172"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/spon.com.vn\/?page_id=6172#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Trang ch\u1ee7","item":"https:\/\/spon.com.vn\/"},{"@type":"ListItem","position":2,"name":"C\u00f4ng c\u1ee5 m\u00f4 ph\u1ecfng ph\u00f2ng h\u1ecdp h\u1ed9i ngh\u1ecb SPON"}]}]}},"_links":{"self":[{"href":"https:\/\/spon.com.vn\/index.php?rest_route=\/wp\/v2\/pages\/6172"}],"collection":[{"href":"https:\/\/spon.com.vn\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/spon.com.vn\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/spon.com.vn\/index.php?rest_route=\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/spon.com.vn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6172"}],"version-history":[{"count":11,"href":"https:\/\/spon.com.vn\/index.php?rest_route=\/wp\/v2\/pages\/6172\/revisions"}],"predecessor-version":[{"id":6191,"href":"https:\/\/spon.com.vn\/index.php?rest_route=\/wp\/v2\/pages\/6172\/revisions\/6191"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/spon.com.vn\/index.php?rest_route=\/wp\/v2\/media\/6173"}],"wp:attachment":[{"href":"https:\/\/spon.com.vn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6172"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}