/**
* Reads the gym page DOM and returns:
* { attr: 'strength'|'speed'|..., current: number, gym: string }
* or `null` if the page doesn't look like a Torn gym page.
*
* Torn's gym page is a React app using CSS modules with hash suffixes
* (e.g. class="strength___iXqEf", class="propertyValue___IYxjf"). This
* scraper targets Torn's actual structure rather than guessing at selectors.
*/
const KNOWN_ATTRS = ['strength', 'defense', 'speed', 'dexterity', 'endurance', 'intelligence'];
export function currentAttribute() {
const li = findActiveAttributeLi();
if (!li) return null;
const attr = extractAttrFromLi(li);
if (!attr) return null;
const current = extractValueFromLi(li);
if (current == null) return null;
const gym = findGymName() || 'Unknown gym';
return { attr, current, gym };
}
function findActiveAttributeLi() {
// Priority 1: the
with the "success" class (just trained).
const lis = document.querySelectorAll('ul[class*="properties"] > li[class*="success"]');
for (const li of lis) {
if (extractAttrFromLi(li)) return li;
}
// Priority 2: the corresponding to the .gained message's attribute.
const gained = document.querySelector('[class*="gained"]');
if (gained) {
const text = (gained.textContent || '').toLowerCase();
for (const attr of KNOWN_ATTRS) {
if (text.includes(attr)) {
const li = document.querySelector('ul[class*="properties"] > li[class^="' + attr + '___"]');
if (li) return li;
}
}
}
// Priority 3: the first in the properties list.
const all = document.querySelectorAll('ul[class*="properties"] > li');
for (const li of all) {
if (extractAttrFromLi(li)) return li;
}
return null;
}
function extractAttrFromLi(li) {
const cls = li.className || '';
for (const attr of KNOWN_ATTRS) {
if (cls.split(/\s+/).some((c) => c.startsWith(attr + '___'))) return attr;
}
return null;
}
function extractValueFromLi(li) {
const valueSpan = li.querySelector('[class^="propertyValue"]');
if (!valueSpan) return null;
return parseNumber(valueSpan.textContent);
}
function findGymName() {
// Find the currently selected gym button. It has the "active" class.
const activeBtn = document.querySelector('button[class*="gymButton"][class*="active"]');
if (activeBtn) {
const label = activeBtn.getAttribute('aria-label') || '';
// aria-label format: ". Membership cost - $X. Energy usage - N per train."
// The gym name is everything before the first ". ".
const dot = label.indexOf('. ');
if (dot !== -1) return label.slice(0, dot);
return label; // no period, return whole label as fallback
}
return null;
}
function parseNumber(text) {
if (!text) return null;
const cleaned = text.replace(/,/g, '').trim();
if (!/^\d+(\.\d+)?$/.test(cleaned)) return null;
const n = parseFloat(cleaned);
return Number.isFinite(n) ? Math.floor(n) : null;
}