CoolFace
Apppublic

Kalletlamadhav/sql-optimization-env

sourceHugging Faceupdated 6mo agoView on Hugging Face
0likes
index.html409 linesDownload Raw Back to static
1<!DOCTYPE html>2<html lang="en">3<head>4  <meta charset="utf-8" />5  <meta name="viewport" content="width=device-width, initial-scale=1" />6  <title>SQL Optimization Env — Domain Dashboard</title>7  <style>8    :root {9      --bg: #0f1419;10      --panel: #1a2332;11      --border: #2d3a4d;12      --text: #e7ecf3;13      --muted: #8b9cb3;14      --accent: #3d8bfd;15      --gst: #3d8bfd;16      --pds: #f5a623;17      --ok: #3ecf8e;18    }19    * { box-sizing: border-box; }20    body {21      margin: 0;22      font-family: "Segoe UI", system-ui, sans-serif;23      background: var(--bg);24      color: var(--text);25      line-height: 1.5;26    }27    a { color: var(--accent); }28    header {29      padding: 1.25rem 1.5rem;30      border-bottom: 1px solid var(--border);31      display: flex;32      flex-wrap: wrap;33      align-items: center;34      gap: 1rem;35      justify-content: space-between;36    }37    header h1 { margin: 0; font-size: 1.25rem; font-weight: 600; }38    .health-bar {39      display: flex;40      flex-wrap: wrap;41      gap: 0.75rem 1.25rem;42      font-size: 0.875rem;43      color: var(--muted);44    }45    .health-bar strong { color: var(--text); }46    .pill {47      display: inline-block;48      padding: 0.15rem 0.5rem;49      border-radius: 999px;50      background: var(--panel);51      border: 1px solid var(--border);52      font-size: 0.75rem;53      margin-right: 0.35rem;54    }55    .pill.ok { border-color: var(--ok); color: var(--ok); }56    main { padding: 1.25rem 1.5rem 2.5rem; max-width: 1200px; margin: 0 auto; }57    h2 { font-size: 1rem; margin: 2rem 0 0.75rem; color: var(--muted); font-weight: 600; }58    .cards {59      display: grid;60      grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));61      gap: 1rem;62    }63    .card {64      background: var(--panel);65      border: 1px solid var(--border);66      border-radius: 10px;67      padding: 1rem 1.1rem;68      display: flex;69      flex-direction: column;70      gap: 0.5rem;71    }72    .card h3 { margin: 0; font-size: 1.05rem; }73    .card .scale { font-size: 0.8rem; color: var(--muted); }74    .counts { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-top: 0.25rem; }75    .counts span {76      font-size: 0.72rem;77      background: #0f1419;78      padding: 0.2rem 0.45rem;79      border-radius: 6px;80      border: 1px solid var(--border);81    }82    .samples { margin: 0.35rem 0 0; padding-left: 1.1rem; font-size: 0.78rem; color: var(--muted); }83    .samples li { margin: 0.25rem 0; }84    details.ddl {85      margin-top: 0.5rem;86      border-top: 1px solid var(--border);87      padding-top: 0.5rem;88    }89    details.ddl summary {90      cursor: pointer;91      font-size: 0.8rem;92      color: var(--accent);93    }94    details.ddl pre {95      margin: 0.5rem 0 0;96      max-height: 220px;97      overflow: auto;98      font-size: 0.65rem;99      background: #0f1419;100      padding: 0.6rem;101      border-radius: 6px;102      border: 1px solid var(--border);103      white-space: pre-wrap;104    }105    .map-wrap {106      background: var(--panel);107      border: 1px solid var(--border);108      border-radius: 10px;109      padding: 1rem;110    }111    .map-controls {112      display: flex;113      flex-wrap: wrap;114      gap: 0.5rem;115      align-items: center;116      margin-bottom: 0.75rem;117      font-size: 0.85rem;118    }119    .map-controls label { margin-right: 0.35rem; color: var(--muted); }120    .map-controls button {121      background: #0f1419;122      border: 1px solid var(--border);123      color: var(--text);124      padding: 0.35rem 0.65rem;125      border-radius: 6px;126      cursor: pointer;127      font-size: 0.8rem;128    }129    .map-controls button.active {130      border-color: var(--accent);131      color: var(--accent);132    }133    .map-legend {134      font-size: 0.75rem;135      color: var(--muted);136      margin-top: 0.5rem;137    }138    .err { color: #f87171; font-size: 0.85rem; }139    footer {140      margin-top: 2rem;141      padding: 1rem 1.5rem;142      border-top: 1px solid var(--border);143      font-size: 0.8rem;144      color: var(--muted);145      text-align: center;146    }147  </style>148</head>149<body>150  <header>151    <h1>SQL Optimization Environment</h1>152    <div class="health-bar" id="health-bar">153      <span>Loading <code>/health</code>…</span>154    </div>155  </header>156  <main>157    <p style="color:var(--muted);font-size:0.9rem;margin:0 0 1rem;">158      Indian public-data domains for query optimization tasks.159      API: <a href="/docs">OpenAPI docs</a> · <a href="/health"><code>/health</code></a> ·160      <a href="/domains"><code>/domains</code></a>161    </p>162    <div id="domain-error" class="err" hidden></div>163    <h2>Domains</h2>164    <div class="cards" id="domain-cards"></div>165 166    <h2>India map — data density (GST vs PDS)</h2>167    <div class="map-wrap">168      <div class="map-controls">169        <span><label>Layer</label></span>170        <button type="button" data-layer="gst" class="active">GST invoices</button>171        <button type="button" data-layer="pds">PDS cards</button>172        <button type="button" data-layer="both">Combined</button>173      </div>174      <svg id="india-map" viewBox="0 0 200 160" width="100%" style="max-height:420px;display:block;">175        <rect width="200" height="160" fill="#0f1419" rx="4" />176        <path id="india-outline" fill="#152030" stroke="#2d3a4d" stroke-width="0.4"177          d="M28 38 L172 32 L178 48 L184 95 L168 128 L142 142 L96 148 L44 138 L22 98 Z" />178        <g id="bubbles"></g>179        <g id="labels"></g>180      </svg>181      <p class="map-legend">Bubble area scales with row counts for the selected layer (state_code). Positions are stylized, not survey-accurate.</p>182    </div>183    <h2>🚀 Try Live Optimization</h2>184 185<div class="card">186  <button onclick="resetEnv()">🔄 Reset Task</button>187  <pre id="task-output"></pre>188 189  <h3>✏️ Optimized Query</h3>190  <textarea id="query-input" style="width:100%;height:120px;"></textarea>191 192  <input id="pattern-input" placeholder="Pattern (e.g. SELECT_STAR)" style="width:100%;margin-top:8px;" />193 194  <textarea id="explanation-input" placeholder="Explain your optimization..." style="width:100%;height:80px;margin-top:8px;"></textarea>195 196  <button onclick="runStep()">▶ Run Step</button>197 198  <h3>📊 Reward</h3>199  <pre id="reward-output"></pre>200 201  <h3>📈 Execution Plan</h3>202  <pre id="plan-output"></pre>203 204  <h3>🎯 Curriculum</h3>205  <pre id="state-output"></pre>206</div>207  </main>208  <footer>OpenEnv SQL optimization · static dashboard</footer>209 210  <script>211    const STATE_POS = {212      '01': [48, 28], '02': [62, 34], '03': [58, 40], '06': [64, 46], '07': [66, 44], '08': [42, 58],213      '09': [76, 52], '10': [102, 68], '11': [156, 80], '12': [176, 72], '13': [168, 62], '14': [150, 52],214      '18': [188, 78], '19': [98, 58], '21': [88, 72], '22': [74, 70], '23': [62, 70], '24': [30, 82],215      '27': [52, 92], '29': [46, 118], '32': [48, 134], '33': [76, 138], '36': [70, 110], '37': [90, 96]216    };217 218    let mapData = { gst_by_state: {}, pds_by_state: {}, state_labels: {} };219    let mapLayer = 'gst';220 221    async function loadHealth() {222      const el = document.getElementById('health-bar');223      try {224        const r = await fetch('/health');225        const j = await r.json();226        const counts = j.table_row_counts || {};227        const keys = Object.keys(counts).sort();228        const preview = keys.slice(0, 6).map(k => `${k}: ${counts[k]}`).join(' · ');229        el.innerHTML = `230          <span class="pill ok">${j.status}</span>231          <span><strong>Total rows</strong> ${j.total_rows != null ? j.total_rows.toLocaleString() : '—'}</span>232          <span><strong>DB</strong> <code style="font-size:0.75rem">${(j.database_path || '').split('/').slice(-3).join('/')}</code></span>233          <span><strong>Tables</strong> ${keys.length} · ${preview}${keys.length > 6 ? ' …' : ''}</span>234        `;235      } catch (e) {236        el.innerHTML = `<span class="err">Health check failed: ${e.message}</span>`;237      }238    }239 240    function renderCards(domains) {241      const root = document.getElementById('domain-cards');242      root.innerHTML = '';243      domains.forEach(d => {244        const card = document.createElement('article');245        card.className = 'card';246        const tables = (d.tables || []).map(t =>247          `<span>${t.table}: <strong>${t.row_count.toLocaleString()}</strong></span>`248        ).join('');249        const samples = (d.sample_queries || []).map(q => `<li><code>${escapeHtml(q)}</code></li>`).join('');250        card.innerHTML = `251          <h3>${escapeHtml(d.domain)}</h3>252          <div class="scale">${escapeHtml(d.real_world_scale || '')}</div>253          <div style="font-size:0.85rem;color:var(--muted)">${escapeHtml(d.description || '')}</div>254          <div class="counts">${tables}</div>255          <ul class="samples">${samples}</ul>256          <details class="ddl">257            <summary>Schema DDL (collapsible)</summary>258            <pre>${escapeHtml(d.schema_ddl || '')}</pre>259          </details>260        `;261        root.appendChild(card);262      });263    }264 265    function escapeHtml(s) {266      return String(s)267        .replace(/&/g, '&amp;')268        .replace(/</g, '&lt;')269        .replace(/>/g, '&gt;')270        .replace(/"/g, '&quot;');271    }272 273    function valueForState(code, layer) {274      const g = mapData.gst_by_state[code] || 0;275      const p = mapData.pds_by_state[code] || 0;276      if (layer === 'gst') return g;277      if (layer === 'pds') return p;278      return g + p;279    }280 281    function drawMap() {282      const bubbles = document.getElementById('bubbles');283      const labels = document.getElementById('labels');284      bubbles.innerHTML = '';285      labels.innerHTML = '';286      const codes = new Set([287        ...Object.keys(mapData.gst_by_state || {}),288        ...Object.keys(mapData.pds_by_state || {})289      ]);290      let maxV = 0;291      codes.forEach(c => { maxV = Math.max(maxV, valueForState(c, mapLayer)); });292      const scale = maxV > 0 ? 1 / Math.sqrt(maxV) : 1;293 294      codes.forEach(code => {295        const pos = STATE_POS[code];296        if (!pos) return;297        const v = valueForState(code, mapLayer);298        if (v <= 0) return;299        const r = Math.max(2.2, Math.sqrt(v) * scale * 14);300        const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');301        circle.setAttribute('cx', pos[0]);302        circle.setAttribute('cy', pos[1]);303        circle.setAttribute('r', r);304        const fill = mapLayer === 'pds' ? 'rgba(245,166,35,0.45)' :305          mapLayer === 'gst' ? 'rgba(61,139,253,0.45)' : 'rgba(160,120,255,0.4)';306        circle.setAttribute('fill', fill);307        circle.setAttribute('stroke', mapLayer === 'pds' ? '#f5a623' : '#3d8bfd');308        circle.setAttribute('stroke-width', '0.35');309        const lbl = mapData.state_labels[code] || code;310        const tip = document.createElementNS('http://www.w3.org/2000/svg', 'title');311        tip.textContent = `${lbl} (${code}): ${v.toLocaleString()} rows`;312        circle.appendChild(tip);313        bubbles.appendChild(circle);314 315        const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');316        text.setAttribute('x', pos[0]);317        text.setAttribute('y', pos[1] + r + 3.5);318        text.setAttribute('text-anchor', 'middle');319        text.setAttribute('fill', '#8b9cb3');320        text.setAttribute('font-size', '3.2');321        text.textContent = lbl;322        labels.appendChild(text);323      });324    }325 326    document.querySelectorAll('.map-controls button').forEach(btn => {327      btn.addEventListener('click', () => {328        document.querySelectorAll('.map-controls button').forEach(b => b.classList.remove('active'));329        btn.classList.add('active');330        mapLayer = btn.getAttribute('data-layer');331        drawMap();332      });333    });334 335    async function loadDomains() {336      const err = document.getElementById('domain-error');337      err.hidden = true;338      try {339        const r = await fetch('/domains');340        if (!r.ok) throw new Error(await r.text());341        const j = await r.json();342        mapData = j.map || mapData;343        renderCards(j.domains || []);344        drawMap();345      } catch (e) {346        err.textContent = 'Failed to load /domains: ' + e.message;347        err.hidden = false;348      }349    }350 351    loadHealth();352    loadDomains();353    setInterval(loadHealth, 12000);354    async function resetEnv() {355  const res = await fetch('/reset');356  const data = await res.json();357 358  document.getElementById("task-output").innerText =359    "🎯 TASK:\n" + data.goal + "\n\n" +360    "💡 HINT:\n" + data.anti_pattern_hint + "\n\n" +361    "🆔 Task ID: " + data.task_id;362 363  document.getElementById("query-input").value =364    data.current_query || "";365 366  document.getElementById("plan-output").innerText =367    JSON.stringify(data.execution_plan, null, 2);368 369  document.getElementById("state-output").innerText =370    "Level: " + data.curriculum_level;371}372 373async function runStep() {374  const body = {375    optimized_query: document.getElementById("query-input").value,376    identified_pattern: document.getElementById("pattern-input").value,377    explanation: document.getElementById("explanation-input").value,378    index_statements: [],379    schema_analysis: ""380  };381 382  const res = await fetch('/step', {383    method: "POST",384    headers: {"Content-Type": "application/json"},385    body: JSON.stringify(body)386  });387 388  const data = await res.json();389 390  document.getElementById("reward-output").innerText =391  JSON.stringify(data.reward || data, null, 2);392 393  document.getElementById("plan-output").innerText =394    JSON.stringify(data.observation?.execution_plan || {}, null, 2);395 396  loadState();397}398 399async function loadState() {400  const res = await fetch('/state');401  const data = await res.json();402 403  document.getElementById("state-output").innerText =404    JSON.stringify(data, null, 2);405}406  </script>407</body>408</html>409