// ================================================================ // Town Viewer Component (Left panel + Town detail view) // ================================================================ window.renderTowns = function() { const container = document.getElementById('town-list'); if (!window.towns || !window.towns.length) { container.innerHTML = '

No towns received yet.

'; return; } // Get active filters const searchTerm = (document.getElementById('town-search')?.value || '').toLowerCase(); const reqFullWh = document.getElementById('filter-full-wh')?.checked; const reqFestival = document.getElementById('filter-festival')?.checked; const reqPoints = document.getElementById('filter-points')?.checked; const filteredTowns = window.towns.filter(t => { // 1. Search by name const tName = t.town_name || ''; if (searchTerm && !tName.toLowerCase().includes(searchTerm)) return false; const res = t.resources || {}; const cap = res.storage || 1; const wPct = (res.wood || 0) / cap; const sPct = (res.stone || 0) / cap; const iPct = (res.iron || 0) / cap; // 2. Full WH (>95%) if (reqFullWh && Math.max(wPct, sPct, iPct) < 0.95) return false; // 3. Festival (Wood>15k, Stone>18k, Iron>15k) // City Festival exact costs = 15000, 18000, 15000 if (reqFestival && ((res.wood || 0) < 15000 || (res.stone || 0) < 18000 || (res.iron || 0) < 15000)) return false; // 4. Large Points const pts = typeof t.points === 'number' ? t.points : parseInt(t.points) || 0; if (reqPoints && pts < 10000) return false; return true; }); if (filteredTowns.length === 0) { container.innerHTML = '

Καμία πόλη δεν ταιριάζει στα κριτήρια.

'; return; } const now = Date.now(); container.innerHTML = filteredTowns.map(t => { const updatedMs = new Date(t.updated_at + 'Z').getTime(); const ageMin = Math.round((now - updatedMs) / 60000); const stale = ageMin > 3; const selected = t.town_id === window.selectedTownId ? 'selected' : ''; const res = t.resources || {}; const cap = res.storage || 1; const wPct = (res.wood || 0) / cap; const sPct = (res.stone || 0) / cap; const iPct = (res.iron || 0) / cap; let markers = ''; if (wPct >= 0.95 || sPct >= 0.95 || iPct >= 0.95) { markers += '⚠️'; } if ((res.wood || 0) >= 15000 && (res.stone || 0) >= 18000 && (res.iron || 0) >= 15000) { markers += '🎭'; } const getC = (pct) => pct >= 0.95 ? 'color:#ff4a4a;font-weight:bold;' : ''; return `
${markers}${t.town_name || 'Άγνωστη'}${t.has_premium ? ' ' : ''}
${t.sea != null ? `🌊 Θ${t.sea} · ` : ''}${t.points || 0} pts · ${t.god || 'No god'} · ${ageMin}m ago
${window.fmt(res.wood || 0)}
${window.fmt(res.stone || 0)}
${window.fmt(res.iron || 0)}
${window.fmt(res.population || 0)}
`; }).join(''); }; window.selectTown = function(id) { window.selectedTownId = id; window.renderTowns(); document.getElementById('no-town-selected').style.display = 'none'; document.getElementById('command-form-wrap').style.display = 'block'; document.getElementById('town-details-panel').style.display = 'block'; window.renderBuildQueuePreview(); window.renderBuildingDropdown(); window.renderUnitDropdown(); window.renderTownDetails(); }; window.getSelectedTown = function() { return window.towns.find(t => t.town_id === window.selectedTownId); }; window.renderTownDetails = function() { const t = window.getSelectedTown(); if(!t) return; document.getElementById('td-name').textContent = t.town_name || 'Άγνωστη'; const resObj = t.resources || {}; const cap = resObj.storage || 1; const getCol = (amt) => { const pct = amt / cap; if (pct >= 0.95) return 'color: #ff4a4a;'; // Red if (pct >= 0.85) return 'color: #ffa500;'; // Orange return 'color: #fff;'; }; // Calculate resources reserved in the bot's pending queues let reservedWood = 0, reservedStone = 0, reservedIron = 0; if (window.cmds) { window.cmds.forEach(cmd => { if ((cmd.status === 'pending' || cmd.status === 'executing') && cmd.town_id == t.town_id) { if (cmd.type === 'build' && t.build_data) { const p = typeof cmd.payload === 'string' ? JSON.parse(cmd.payload) : cmd.payload; const cost = t.build_data[p.building_id]; if (cost) { reservedWood += cost.wood || 0; reservedStone += cost.stone || 0; reservedIron += cost.iron || 0; } } else if (cmd.type === 'recruit' && t.unit_data) { const p = typeof cmd.payload === 'string' ? JSON.parse(cmd.payload) : cmd.payload; const amt = parseInt(p.amount) || 1; const cost = t.unit_data[p.unit_id]; if (cost) { reservedWood += (cost.wood || 0) * amt; reservedStone += (cost.stone || 0) * amt; reservedIron += (cost.iron || 0) * amt; } } } }); } const resHtml = (actual, reserved) => { let base = `${window.fmt(actual)}`; if (reserved > 0) { base += ` (-${window.fmt(reserved)})`; } return base; }; const capFmt = (resObj.storage != null && resObj.storage !== '') ? window.fmt(resObj.storage) : '?'; document.getElementById('td-resources').innerHTML = `
Χωρητικότητα: ${capFmt}
${window.RES_ICONS.wood} Ξύλο: ${resHtml(resObj.wood || 0, reservedWood)}
${window.RES_ICONS.stone} Πέτρα: ${resHtml(resObj.stone || 0, reservedStone)}
${window.RES_ICONS.iron} Ασήμι: ${resHtml(resObj.iron || 0, reservedIron)}
${window.RES_ICONS.pop} Πληθυσμός: ${resObj.population || 0}
`; const godName = t.god ? t.god.charAt(0).toUpperCase() + t.god.slice(1) : 'Κανένας'; const seaStr = t.sea != null ? `Θ${t.sea}` : '—'; const coordStr = (t.x != null && t.y != null) ? ` (${Math.round(t.x)}:${Math.round(t.y)})` : ''; document.getElementById('td-general').innerHTML = `
Πόντοι: ${t.points}${t.wonder_points ? ` / Θαύμα: ${t.wonder_points}` : ''}
Θεός: ${godName}
Θάλασσα: ${seaStr}${coordStr}
Παίκτης: ${t.player}${t.has_premium ? ' ' : ''}
${t.alliance_id ? `
Συμμαχία: ${t.alliance_id}
` : ''} `; // ---- Researches ---- const researchObj = t.researches || {}; const researchEntries = Object.entries(researchObj).filter(([k, v]) => k !== 'id' && k !== 'town_id' && (v === true || v === 1 || Number(v) > 0) ); let researchHtml = ''; if (researchEntries.length) { researchHtml = researchEntries.map(([k]) => `
✓ ${k.replace(/_/g, ' ')}
` ).join(''); } else { researchHtml = '
Καμία έρευνα
'; } document.getElementById('td-researches').innerHTML = researchHtml; const unitsObj = t.units || {}; let unitsHtml = ''; for(const [unitKey, count] of Object.entries(unitsObj)) { if(count > 0 && unitKey !== 'militia') { const name = window.UNIT_NAMES_GR[unitKey] || unitKey; unitsHtml += `
${name}: ${count}
`; } } if(unitsHtml === '') unitsHtml = '
Κανένα στράτευμα
'; document.getElementById('td-units').innerHTML = unitsHtml; };