186 lines
17 KiB
HTML
Executable File
186 lines
17 KiB
HTML
Executable File
<?php include_once("/opt/wevads-arsenal/public/api/wevads-metrics.php"); ?>
|
||
<?php
|
||
@$_db=new PDO("pgsql:host=localhost;dbname=adx_system","admin","admin123");$_db->exec("SET search_path TO admin");
|
||
$_total=(int)$_db->query("SELECT COUNT(*) FROM brain_send_configs")->fetchColumn();
|
||
$_tested=(int)$_db->query("SELECT COUNT(*) FROM brain_send_configs WHERE total_sent>0")->fetchColumn();
|
||
$_avgInbox=$_db->query("SELECT ROUND(AVG(NULLIF(inbox_rate,0))::numeric,1) FROM brain_send_configs WHERE total_sent>0")->fetchColumn() ?: 0;
|
||
$_totalSent=(int)$_db->query("SELECT COALESCE(SUM(total_sent),0) FROM brain_send_configs")->fetchColumn();
|
||
$_totalInbox=(int)$_db->query("SELECT COALESCE(SUM(total_inbox),0) FROM brain_send_configs")->fetchColumn();
|
||
// Get unique methods and ISPs
|
||
$_methodList=$_db->query("SELECT DISTINCT send_method FROM brain_send_configs WHERE send_method IS NOT NULL ORDER BY send_method")->fetchAll(PDO::FETCH_COLUMN);
|
||
$_ispList=$_db->query("SELECT DISTINCT isp_target FROM brain_send_configs WHERE isp_target IS NOT NULL AND isp_target!='' ORDER BY isp_target")->fetchAll(PDO::FETCH_COLUMN);
|
||
// Matrix data: method x isp -> avg inbox rate
|
||
$_matrix=$_db->query("SELECT send_method, isp_target, ROUND(AVG(NULLIF(inbox_rate,0))::numeric,1) as avg_inbox, COUNT(*) as cnt, SUM(total_sent) as total_sent FROM brain_send_configs WHERE isp_target IS NOT NULL AND isp_target!='' GROUP BY send_method, isp_target ORDER BY send_method, isp_target")->fetchAll(PDO::FETCH_ASSOC);
|
||
// Build matrix lookup
|
||
$_matrixMap=[];
|
||
foreach($_matrix as $m) $_matrixMap[$m['send_method']][$m['isp_target']]=['inbox'=>$m['avg_inbox'],'cnt'=>$m['cnt'],'sent'=>$m['total_sent']];
|
||
// Best combos
|
||
$_bestCombos=$_db->query("SELECT send_method, isp_target, inbox_rate, total_sent, from_domain, status FROM brain_send_configs WHERE total_sent>0 AND inbox_rate>0 ORDER BY inbox_rate DESC LIMIT 10")->fetchAll(PDO::FETCH_ASSOC);
|
||
// Worst combos
|
||
$_worstCombos=$_db->query("SELECT send_method, isp_target, inbox_rate, total_sent, from_domain FROM brain_send_configs WHERE total_sent>0 AND inbox_rate>0 ORDER BY inbox_rate ASC LIMIT 5")->fetchAll(PDO::FETCH_ASSOC);
|
||
?>
|
||
<!DOCTYPE html><html lang="fr"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>WEVADS - Dark Matrix</title>
|
||
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
|
||
<style>
|
||
:root{--bg:#060a14;--s:#0c1220;--s2:#111827;--b:#1e293b;--t:#e2e8f0;--d:#64748b;--cy:#22d3ee;--gn:#34d399;--am:#fbbf24;--rd:#f87171;--pu:#a78bfa;--bl:#60a5fa;--pk:#f472b6}
|
||
*{margin:0;padding:0;box-sizing:border-box}body{background:var(--bg);color:var(--t);font-family:'DM Sans',sans-serif;font-size:12px}
|
||
.mono{font-family:'JetBrains Mono',monospace}
|
||
.hdr{background:var(--s);border-bottom:1px solid var(--b);padding:14px 20px;display:flex;justify-content:space-between;align-items:center}
|
||
.hdr h1{font-size:18px;font-weight:700;margin-left:80px}.hdr h1 span{background:linear-gradient(135deg,var(--gn),var(--cy));-webkit-background-clip:text;-webkit-text-fill-color:transparent}
|
||
.wrap{padding:16px 20px;max-width:1500px;margin:0 auto}
|
||
.stats{display:grid;grid-template-columns:repeat(6,1fr);gap:10px;margin-bottom:16px}
|
||
.sc{background:var(--s);border:1px solid var(--b);border-radius:10px;padding:14px;text-align:center;cursor:pointer;transition:all .2s}
|
||
.sc:hover{transform:translateY(-2px);box-shadow:0 8px 24px rgba(0,0,0,.3);border-color:var(--cy)}
|
||
.sc .n{font-family:'JetBrains Mono',monospace;font-size:22px;font-weight:700}.sc .l{font-size:9px;text-transform:uppercase;color:var(--d);margin-top:4px}.sc .delta{font-size:9px;margin-top:3px}
|
||
.g2{display:grid;grid-template-columns:1fr 1fr;gap:12px}.cd{background:var(--s);border:1px solid var(--b);border-radius:10px;padding:14px}
|
||
table{width:100%;border-collapse:collapse;font-size:11px}th{text-align:left;color:var(--d);text-transform:uppercase;font-size:9px;padding:6px 8px;border-bottom:1px solid var(--b)}td{padding:6px 8px;border-bottom:1px solid rgba(30,41,59,.3)}
|
||
.badge{font-size:8px;padding:2px 6px;border-radius:3px;font-weight:600}.badge-gn{background:rgba(52,211,153,.15);color:var(--gn)}.badge-rd{background:rgba(248,113,113,.15);color:var(--rd)}.badge-am{background:rgba(251,191,36,.15);color:var(--am)}.badge-cy{background:rgba(34,211,238,.15);color:var(--cy)}
|
||
.btn{padding:8px 16px;border-radius:6px;border:1px solid var(--b);background:var(--s2);color:var(--t);cursor:pointer;font-size:10px;font-weight:600;transition:all .2s;text-decoration:none}.btn:hover{border-color:var(--cy);transform:translateY(-1px)}
|
||
.tabs{display:flex;gap:2px;margin-bottom:14px;border-bottom:1px solid var(--b)}.tab{padding:8px 16px;cursor:pointer;font-size:10px;font-weight:600;text-transform:uppercase;color:var(--d);border-bottom:2px solid transparent}.tab:hover{color:var(--t)}.tab.active{color:var(--cy);border-color:var(--cy)}
|
||
.panel{display:none}.panel.active{display:block}
|
||
.modal{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.75);z-index:9999;justify-content:center;align-items:center}.modal-box{background:var(--s);border:1px solid var(--b);border-radius:12px;padding:20px;max-width:950px;width:94%;max-height:82vh;overflow-y:auto}
|
||
.cell{width:54px;height:38px;border-radius:6px;display:flex;align-items:center;justify-content:center;font-family:'JetBrains Mono',monospace;font-size:10px;font-weight:700;cursor:pointer;transition:all .2s;border:1px solid transparent}
|
||
.cell:hover{transform:scale(1.15);z-index:1;border-color:var(--cy)}
|
||
.matrix-grid{display:grid;gap:3px;overflow-x:auto}
|
||
.legend{display:flex;gap:16px;justify-content:center;margin-top:10px;font-size:10px;color:var(--d)}
|
||
.legend span{display:flex;align-items:center;gap:4px}.legend .dot{width:12px;height:12px;border-radius:3px}
|
||
@media(max-width:900px){.stats{grid-template-columns:repeat(3,1fr)}.g2{grid-template-columns:1fr}}
|
||
</style>
|
||
<link rel="stylesheet" href="wevads-global.css?v1770777318">
|
||
</head><body>
|
||
<div class="hdr"><div><h1>🧪 <span>Dark Matrix</span></h1><div style="color:var(--d);font-size:11px;margin-top:4px">ISP × Send Method delivery matrix — heatmap — combo analysis</div></div><div style="display:flex;gap:8px;align-items:center"><span class="badge badge-cy">● MATRIX</span><a href="menu.html" class="btn">Menu</a><a href="operations-overview.html" class="btn">← Overview</a></div></div>
|
||
<div class="wrap">
|
||
<div class="stats">
|
||
<div class="sc" onclick="drill('total')"><div class="n" style="color:var(--cy)"><?=$_total?></div><div class="l">Total Configs ▼</div><div class="delta"><?=count($_methodList)?> methods × <?=count($_ispList)?> ISPs</div></div>
|
||
<div class="sc" onclick="drill('tested')"><div class="n" style="color:var(--gn)"><?=$_tested?></div><div class="l">Tested ▼</div><div class="delta"><?=$_total-$_tested?> untested</div></div>
|
||
<div class="sc" onclick="drill('inbox')"><div class="n" style="color:var(--am)"><?=$_avgInbox?>%</div><div class="l">Avg Inbox ▼</div><div class="delta">across tested</div></div>
|
||
<div class="sc" onclick="drill('sent')"><div class="n" style="color:var(--bl)"><?=number_format($_totalSent)?></div><div class="l">Total Sent ▼</div><div class="delta"><?=number_format($_totalInbox)?> inbox</div></div>
|
||
<div class="sc" onclick="drill('best')"><div class="n" style="color:var(--gn)"><?=count($_bestCombos)?></div><div class="l">Best Combos ▼</div><div class="delta">top performers</div></div>
|
||
<div class="sc" onclick="drill('gaps')"><div class="n" style="color:var(--rd)"><?=count($_worstCombos)?></div><div class="l">Weak Spots ▼</div><div class="delta">needs work</div></div>
|
||
</div>
|
||
<div class="tabs">
|
||
<div class="tab active" onclick="showTab('matrix')">🧪 Heatmap</div>
|
||
<div class="tab" onclick="showTab('best')">🏆 Best Combos</div>
|
||
<div class="tab" onclick="showTab('worst')">⚠️ Worst</div>
|
||
<div class="tab" onclick="showTab('gaps')">🕳️ Gap Analysis</div>
|
||
</div>
|
||
<!-- HEATMAP -->
|
||
<div class="panel active" id="tab-matrix">
|
||
<div class="cd">
|
||
<h3 style="font-size:13px;margin-bottom:12px;color:var(--cy)">🧪 ISP × Method Inbox Rate Matrix</h3>
|
||
<div style="overflow-x:auto">
|
||
<table>
|
||
<thead><tr><th style="min-width:100px">Method \ ISP</th>
|
||
<?php foreach($_ispList as $isp):?><th style="text-align:center;min-width:60px;font-size:8px"><?=htmlspecialchars($isp)?></th><?php endforeach;?>
|
||
</tr></thead>
|
||
<tbody>
|
||
<?php foreach($_methodList as $method): ?>
|
||
<tr><td style="font-weight:600;white-space:nowrap"><?=htmlspecialchars($method)?></td>
|
||
<?php foreach($_ispList as $isp):
|
||
$cell=$_matrixMap[$method][$isp]??null;
|
||
if($cell){
|
||
$v=$cell['inbox'];
|
||
if($v>=70){$bg='rgba(52,211,153,.25)';$col='#34d399';}
|
||
elseif($v>=40){$bg='rgba(251,191,36,.25)';$col='#fbbf24';}
|
||
else{$bg='rgba(248,113,113,.25)';$col='#f87171';}
|
||
echo "<td style=\"text-align:center;background:$bg;color:$col;font-family:'JetBrains Mono',monospace;font-weight:700;font-size:11px;cursor:pointer\" title=\"{$method} → {$isp}: {$v}% inbox ({$cell['cnt']} configs, ".number_format($cell['sent'])." sent)\" onclick=\"drillCell('{$method}','{$isp}')\">{$v}%</td>";
|
||
} else {
|
||
echo "<td style=\"text-align:center;color:var(--d);font-size:10px\">—</td>";
|
||
}
|
||
endforeach; ?>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div class="legend">
|
||
<span><div class="dot" style="background:rgba(52,211,153,.4)"></div> >70% (Good)</span>
|
||
<span><div class="dot" style="background:rgba(251,191,36,.4)"></div> 40-70% (Medium)</span>
|
||
<span><div class="dot" style="background:rgba(248,113,113,.4)"></div> <40% (Poor)</span>
|
||
<span><div class="dot" style="background:var(--s2)"></div> — (Untested)</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- BEST COMBOS -->
|
||
<div class="panel" id="tab-best">
|
||
<div class="cd">
|
||
<h3 style="font-size:13px;margin-bottom:10px;color:var(--gn)">🏆 Best Method × ISP Combinations</h3>
|
||
<table><thead><tr><th>#</th><th>Method</th><th>ISP</th><th>Domain</th><th>Inbox</th><th>Sent</th><th>Status</th></tr></thead><tbody>
|
||
<?php foreach($_bestCombos as $i=>$c): $col=$c['inbox_rate']>80?'var(--gn)':($c['inbox_rate']>50?'var(--am)':'var(--rd)'); ?>
|
||
<tr><td style="font-weight:700;color:var(--am)">#<?=$i+1?></td><td style="font-weight:600"><?=htmlspecialchars($c['send_method'])?></td><td><?=htmlspecialchars($c['isp_target']??'—')?></td><td style="font-size:10px;color:var(--d)"><?=htmlspecialchars($c['from_domain']??'—')?></td><td class="mono" style="color:<?=$col?>;font-weight:700"><?=$c['inbox_rate']?>%</td><td class="mono"><?=number_format($c['total_sent'])?></td><td><span class="badge badge-<?=$c['status']==='winner'?'gn':($c['status']==='testing'?'am':'cy')?>"><?=strtoupper($c['status']??'?')?></span></td></tr>
|
||
<?php endforeach; ?>
|
||
</tbody></table>
|
||
</div>
|
||
</div>
|
||
<!-- WORST -->
|
||
<div class="panel" id="tab-worst">
|
||
<div class="cd">
|
||
<h3 style="font-size:13px;margin-bottom:10px;color:var(--rd)">⚠️ Worst Performers</h3>
|
||
<table><thead><tr><th>Method</th><th>ISP</th><th>Domain</th><th>Inbox</th><th>Sent</th></tr></thead><tbody>
|
||
<?php foreach($_worstCombos as $w): ?>
|
||
<tr><td style="font-weight:600"><?=htmlspecialchars($w['send_method'])?></td><td><?=htmlspecialchars($w['isp_target']??'—')?></td><td style="font-size:10px"><?=htmlspecialchars($w['from_domain']??'—')?></td><td class="mono" style="color:var(--rd);font-weight:700"><?=$w['inbox_rate']?>%</td><td class="mono"><?=number_format($w['total_sent'])?></td></tr>
|
||
<?php endforeach; if(empty($_worstCombos)):?><tr><td colspan="5" style="text-align:center;color:var(--d);padding:20px">No bad performers</td></tr><?php endif;?>
|
||
</tbody></table>
|
||
</div>
|
||
</div>
|
||
<!-- GAP ANALYSIS -->
|
||
<div class="panel" id="tab-gaps">
|
||
<div class="cd">
|
||
<h3 style="font-size:13px;margin-bottom:10px;color:var(--pu)">🕳️ Untested Combinations</h3>
|
||
<p style="color:var(--d);margin-bottom:12px">These method × ISP combinations have no test data yet. Consider prioritizing tests for high-value ISPs.</p>
|
||
<div style="display:flex;flex-wrap:wrap;gap:6px">
|
||
<?php
|
||
$tested_combos=[];foreach($_matrix as $m)$tested_combos[$m['send_method'].'→'.$m['isp_target']]=true;
|
||
$gaps=0;
|
||
foreach($_methodList as $method){foreach($_ispList as $isp){
|
||
if(!isset($tested_combos[$method.'→'.$isp])){
|
||
echo '<span style="background:var(--s2);border:1px solid var(--b);border-radius:6px;padding:4px 8px;font-size:10px;color:var(--d)">'.htmlspecialchars($method).' → '.htmlspecialchars($isp).'</span>';
|
||
$gaps++;
|
||
}
|
||
}}
|
||
if($gaps===0) echo '<div style="color:var(--gn)">All combinations tested ✅</div>';
|
||
?>
|
||
</div>
|
||
<div style="margin-top:12px;color:var(--d);font-size:11px"><strong><?=$gaps?></strong> untested combinations out of <?=count($_methodList)*count($_ispList)?> possible</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="modal" id="drillModal" onclick="if(event.target===this)this.style.display='none'"><div class="modal-box"><div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:14px"><h3 id="drillTitle" style="font-size:14px;color:var(--cy)"></h3><button onclick="document.getElementById('drillModal').style.display='none'" style="background:none;border:none;color:var(--rd);font-size:18px;cursor:pointer">✕</button></div><div id="drillContent" style="font-size:11px"></div></div></div>
|
||
<script>
|
||
function showTab(id){document.querySelectorAll('.tab').forEach(function(t){t.classList.remove('active')});document.querySelectorAll('.panel').forEach(function(p){p.classList.remove('active')});document.getElementById('tab-'+id).classList.add('active');event.target.classList.add('active')}
|
||
function drillCell(method,isp){
|
||
var m=document.getElementById('drillModal'),tt=document.getElementById('drillTitle'),ct=document.getElementById('drillContent');
|
||
m.style.display='flex';
|
||
tt.textContent='⚙️ '+method+' → '+isp;
|
||
ct.innerHTML='<div class="cd" style="text-align:center;margin-bottom:12px"><div style="font-size:14px;color:var(--d)">Config detail for <strong style="color:var(--cy)">'+method+'</strong> targeting <strong style="color:var(--am)">'+isp+'</strong></div><div style="margin-top:12px;color:var(--d)">Click the heatmap cell tooltip for full performance data including inbox rate, total sent, and configuration count.</div></div>';
|
||
}
|
||
async function drill(type){
|
||
var m=document.getElementById('drillModal'),tt=document.getElementById('drillTitle'),ct=document.getElementById('drillContent');
|
||
m.style.display='flex';ct.innerHTML='<div style="text-align:center;padding:40px;color:var(--d)">Loading...</div>';
|
||
var html='';
|
||
var titles={total:'🧪 All Configs',tested:'✅ Tested Configs',inbox:'📊 Inbox Analysis',sent:'📤 Send Volume',best:'🏆 Best Combos',gaps:'🕳️ Weak Spots'};
|
||
tt.textContent=titles[type]||type;
|
||
html+='<div style="display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin-bottom:14px">';
|
||
html+='<div class="cd" style="text-align:center"><div style="font-size:18px;font-weight:700;color:var(--cy)"><?=$_total?></div><div class="l">Configs</div></div>';
|
||
html+='<div class="cd" style="text-align:center"><div style="font-size:18px;font-weight:700;color:var(--gn)"><?=$_tested?></div><div class="l">Tested</div></div>';
|
||
html+='<div class="cd" style="text-align:center"><div style="font-size:18px;font-weight:700;color:var(--am)"><?=$_avgInbox?>%</div><div class="l">Avg Inbox</div></div>';
|
||
html+='<div class="cd" style="text-align:center"><div style="font-size:18px;font-weight:700;color:var(--bl)"><?=number_format($_totalSent)?></div><div class="l">Total Sent</div></div></div>';
|
||
if(type==='best'){
|
||
html+='<table><thead><tr><th>Method</th><th>ISP</th><th>Inbox</th><th>Sent</th></tr></thead><tbody>';
|
||
<?php foreach($_bestCombos as $c):$col=$c['inbox_rate']>70?'var(--gn)':'var(--am)';?>html+='<tr><td style="font-weight:600"><?=addslashes($c['send_method'])?></td><td><?=addslashes($c['isp_target']??'-')?></td><td class="mono" style="color:<?=$col?>"><?=$c['inbox_rate']?>%</td><td class="mono"><?=number_format($c['total_sent'])?></td></tr>';<?php endforeach;?>
|
||
html+='</tbody></table>';
|
||
} else if(type==='gaps'){
|
||
html+='<table><thead><tr><th>Method</th><th>ISP</th><th>Inbox</th><th>Sent</th></tr></thead><tbody>';
|
||
<?php foreach($_worstCombos as $w):?>html+='<tr><td style="font-weight:600"><?=addslashes($w['send_method'])?></td><td><?=addslashes($w['isp_target']??'-')?></td><td class="mono" style="color:var(--rd)"><?=$w['inbox_rate']?>%</td><td class="mono"><?=number_format($w['total_sent'])?></td></tr>';<?php endforeach;?>
|
||
html+='</tbody></table>';
|
||
} else {
|
||
html+='<div class="cd" style="color:var(--d)">Matrix covers <strong><?=count($_methodList)?></strong> send methods × <strong><?=count($_ispList)?></strong> ISPs = <strong><?=count($_methodList)*count($_ispList)?></strong> possible combinations. <?=count($_matrix)?> have data.</div>';
|
||
}
|
||
ct.innerHTML=html;
|
||
}
|
||
</script>
|
||
<script src="arsenal-common.js?v1770778169"></script>
|
||
<?php include("/opt/wevads-arsenal/public/universal-drill.html"); ?>
|
||
</body></html>
|