enchance data
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// ==UserScript==
|
||||
// @name Grepolis Remote Control
|
||||
// @namespace http://tampermonkey.net/
|
||||
// @version 1.2
|
||||
// @version 1.3
|
||||
// @description Polls grepo.haunter-pets.top for remote commands and executes them in-game
|
||||
// @author Dimitrios
|
||||
// @match https://*.grepolis.com/game/*
|
||||
@@ -69,8 +69,12 @@
|
||||
function gatherState() {
|
||||
const towns = uw.ITowns?.towns || {};
|
||||
const player = uw.Game?.player_name || '';
|
||||
const player_id = uw.Game?.player_id ?? null;
|
||||
const alliance_id = uw.Game?.alliance_id ?? null;
|
||||
const total_points = uw.Game?.player_points ?? 0;
|
||||
const world = uw.Game?.world_id || '';
|
||||
|
||||
|
||||
const townList = Object.values(towns).map(town => {
|
||||
const res = town.resources();
|
||||
const buildings = town.buildings()?.attributes ?? {};
|
||||
@@ -135,9 +139,35 @@
|
||||
log(`storage capacity lookup failed: ${e}`);
|
||||
}
|
||||
|
||||
// ---- Coordinates & sea zone -----------------------------------------
|
||||
let x = null, y = null, sea = null;
|
||||
try {
|
||||
x = town.getIslandCoordinateX?.() ?? null;
|
||||
y = town.getIslandCoordinateY?.() ?? null;
|
||||
if (typeof x === 'number' && typeof y === 'number') {
|
||||
sea = Math.floor(x / 100) * 10 + Math.floor(y / 100);
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
// ---- Researches -----------------------------------------------------
|
||||
let researches = {};
|
||||
try {
|
||||
const r = town.researches?.();
|
||||
if (r) researches = r.attributes ?? (typeof r === 'object' ? r : {});
|
||||
} catch (e) {}
|
||||
|
||||
// ---- Extra town flags -----------------------------------------------
|
||||
let has_premium = false;
|
||||
let bonuses = {};
|
||||
let wonder_points = 0;
|
||||
try { has_premium = town.hasPremium?.() || false; } catch (e) {}
|
||||
try { bonuses = town.getBonus?.() || {}; } catch (e) {}
|
||||
try { wonder_points = town.wonder_points || 0; } catch (e) {}
|
||||
|
||||
return {
|
||||
town_id: town.id,
|
||||
town_name: town.name,
|
||||
x, y, sea,
|
||||
wood: res.wood,
|
||||
stone: res.stone,
|
||||
iron: res.iron,
|
||||
@@ -149,10 +179,14 @@
|
||||
units: unitsObj,
|
||||
buildingOrder: buildQueue,
|
||||
buildData: buildDataMap,
|
||||
researches,
|
||||
has_premium,
|
||||
bonuses,
|
||||
wonder_points,
|
||||
};
|
||||
});
|
||||
|
||||
return { player, world_id: world, towns: townList };
|
||||
return { player, player_id, alliance_id, total_points, world_id: world, towns: townList };
|
||||
}
|
||||
|
||||
function pushState() {
|
||||
|
||||
18
db.py
18
db.py
@@ -35,11 +35,29 @@ def init_db():
|
||||
town_id TEXT PRIMARY KEY,
|
||||
town_name TEXT,
|
||||
player TEXT,
|
||||
player_id TEXT,
|
||||
alliance_id TEXT,
|
||||
world_id TEXT,
|
||||
x REAL,
|
||||
y REAL,
|
||||
sea INTEGER,
|
||||
data TEXT NOT NULL, -- full JSON snapshot
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)
|
||||
''')
|
||||
|
||||
# Migration: add new columns if upgrading an existing database
|
||||
for _col in [
|
||||
'ALTER TABLE town_state ADD COLUMN player_id TEXT',
|
||||
'ALTER TABLE town_state ADD COLUMN alliance_id TEXT',
|
||||
'ALTER TABLE town_state ADD COLUMN x REAL',
|
||||
'ALTER TABLE town_state ADD COLUMN y REAL',
|
||||
'ALTER TABLE town_state ADD COLUMN sea INTEGER',
|
||||
]:
|
||||
try:
|
||||
c.execute(_col)
|
||||
except Exception:
|
||||
pass # column already exists
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
@@ -18,25 +18,39 @@ def receive_state():
|
||||
|
||||
towns = data.get('towns', [])
|
||||
player = data.get('player', '')
|
||||
player_id = data.get('player_id', '')
|
||||
alliance_id = str(data.get('alliance_id', '') or '')
|
||||
world_id = data.get('world_id', '')
|
||||
|
||||
conn = get_db()
|
||||
c = conn.cursor()
|
||||
for town in towns:
|
||||
x = town.get('x')
|
||||
y = town.get('y')
|
||||
sea = town.get('sea')
|
||||
c.execute('''
|
||||
INSERT INTO town_state (town_id, town_name, player, world_id, data, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
INSERT INTO town_state
|
||||
(town_id, town_name, player, player_id, alliance_id, world_id, x, y, sea, data, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(town_id) DO UPDATE SET
|
||||
town_name = excluded.town_name,
|
||||
player = excluded.player,
|
||||
player_id = excluded.player_id,
|
||||
alliance_id = excluded.alliance_id,
|
||||
world_id = excluded.world_id,
|
||||
x = excluded.x,
|
||||
y = excluded.y,
|
||||
sea = excluded.sea,
|
||||
data = excluded.data,
|
||||
updated_at = excluded.updated_at
|
||||
''', (
|
||||
str(town['town_id']),
|
||||
town.get('town_name', ''),
|
||||
player,
|
||||
player_id,
|
||||
alliance_id,
|
||||
world_id,
|
||||
x, y, sea,
|
||||
json.dumps(town),
|
||||
datetime.utcnow().isoformat()
|
||||
))
|
||||
|
||||
@@ -23,7 +23,8 @@ def index():
|
||||
def get_towns():
|
||||
conn = get_db()
|
||||
rows = conn.execute('''
|
||||
SELECT town_id, town_name, player, world_id, data, updated_at
|
||||
SELECT town_id, town_name, player, player_id, alliance_id,
|
||||
world_id, x, y, sea, data, updated_at
|
||||
FROM town_state
|
||||
ORDER BY town_name ASC
|
||||
''').fetchall()
|
||||
@@ -36,7 +37,12 @@ def get_towns():
|
||||
'town_id': row['town_id'],
|
||||
'town_name': row['town_name'],
|
||||
'player': row['player'],
|
||||
'player_id': row['player_id'],
|
||||
'alliance_id': row['alliance_id'],
|
||||
'world_id': row['world_id'],
|
||||
'x': row['x'],
|
||||
'y': row['y'],
|
||||
'sea': row['sea'],
|
||||
'updated_at': row['updated_at'],
|
||||
'resources': {
|
||||
'wood': d.get('wood', 0),
|
||||
@@ -51,6 +57,11 @@ def get_towns():
|
||||
'god': d.get('god', None),
|
||||
'build_queue': d.get('buildingOrder', []),
|
||||
'build_data': d.get('buildData', {}),
|
||||
'researches': d.get('researches', {}),
|
||||
'has_premium': d.get('has_premium', False),
|
||||
'bonuses': d.get('bonuses', {}),
|
||||
'wonder_points': d.get('wonder_points', 0),
|
||||
'total_points': d.get('total_points', 0),
|
||||
})
|
||||
return jsonify(towns)
|
||||
|
||||
|
||||
@@ -253,6 +253,11 @@
|
||||
<strong style="font-size: 0.75rem; color: #888; text-transform: uppercase;">Στρατος</strong>
|
||||
<div id="td-units" style="font-size: 0.85rem; margin-top: 4px; line-height: 1.5; color: #a4c84a;"></div>
|
||||
</div>
|
||||
|
||||
<div style="flex: 1; min-width: 130px;">
|
||||
<strong style="font-size: 0.75rem; color: #888; text-transform: uppercase;">Ερευνες</strong>
|
||||
<div id="td-researches" style="font-size: 0.8rem; margin-top: 4px; line-height: 1.5; color: #c8a44a;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -474,8 +479,8 @@ function renderTowns() {
|
||||
return `
|
||||
<div class="town-card ${selected} ${stale ? 'town-stale' : ''}"
|
||||
onclick="selectTown('${t.town_id}')">
|
||||
<div class="town-name">${t.town_name}</div>
|
||||
<div class="town-meta">${t.points} pts · ${t.god || 'No god'} · ${ageMin}m ago</div>
|
||||
<div class="town-name">${t.town_name}${t.has_premium ? ' <span style="color:#c8a44a;font-size:0.7rem;">★</span>' : ''}</div>
|
||||
<div class="town-meta">${t.sea != null ? `🌊 Θ${t.sea} · ` : ''}${t.points} pts · ${t.god || 'No god'} · ${ageMin}m ago</div>
|
||||
<div class="town-res">
|
||||
<div class="res-item"><div class="res-icon res-wood"></div>${fmt(t.resources.wood)}</div>
|
||||
<div class="res-item"><div class="res-icon res-stone"></div>${fmt(t.resources.stone)}</div>
|
||||
@@ -532,12 +537,29 @@ function renderTownDetails() {
|
||||
`;
|
||||
|
||||
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 = `
|
||||
<div>Πόντοι: <strong>${t.points}</strong></div>
|
||||
<div>Πόντοι: <strong>${t.points}</strong>${t.wonder_points ? ` / Θαύμα: <strong>${t.wonder_points}</strong>` : ''}</div>
|
||||
<div>Θεός: <strong>${godName}</strong></div>
|
||||
<div>Παίκτης: <strong style="color:#aaa">${t.player}</strong></div>
|
||||
<div>Θάλασσα: <strong style="color:#6fcfcf">${seaStr}</strong><span style="color:#666;font-size:0.72rem">${coordStr}</span></div>
|
||||
<div>Παίκτης: <strong style="color:#aaa">${t.player}</strong>${t.has_premium ? ' <span style="color:#c8a44a" title="Premium">★</span>' : ''}</div>
|
||||
${t.alliance_id ? `<div>Συμμαχία: <strong style="color:#aaa">${t.alliance_id}</strong></div>` : ''}
|
||||
`;
|
||||
|
||||
// ---- Researches ----
|
||||
const researchObj = t.researches || {};
|
||||
const researchEntries = Object.entries(researchObj).filter(([, v]) => v === true || v === 1 || Number(v) > 0);
|
||||
let resHtml = '';
|
||||
if (researchEntries.length) {
|
||||
resHtml = researchEntries.map(([k]) =>
|
||||
`<div>✓ ${k.replace(/_/g, ' ')}</div>`
|
||||
).join('');
|
||||
} else {
|
||||
resHtml = '<div style="color:#555">Καμία έρευνα</div>';
|
||||
}
|
||||
document.getElementById('td-researches').innerHTML = resHtml;
|
||||
|
||||
const unitsObj = t.units || {};
|
||||
let unitsHtml = '';
|
||||
for(const [unitKey, count] of Object.entries(unitsObj)) {
|
||||
|
||||
Reference in New Issue
Block a user