Compact flower & plushie display tracker with color codes, set progress, and flight hints.
当前为
// ==UserScript==
// @name 🌺 🧸 Display Case Tracker (Narrow Above PDA)
// @namespace http://tampermonkey.net/
// @version 2.7
// @description Compact flower & plushie display tracker with color codes, set progress, and flight hints.
// @author Nova
// @match https://www.torn.com/displaycase.php*
// @grant GM_addStyle
// ==/UserScript==
(function() {
'use strict';
const FLOWERS = {
"Dahlia": "MX 🇲🇽", "Orchid": "HW 🏝️", "African Violet": "SA 🇿🇦", "Cherry Blossom": "JP 🇯🇵",
"Peony": "CN 🇨🇳", "Ceibo Flower": "AR 🇦🇷", "Edelweiss": "CH 🇨🇭", "Crocus": "CA 🇨🇦",
"Heather": "UK 🇬🇧", "Tribulus Omanense": "AE 🇦🇪", "Banana Orchid": "KY 🇰🇾"
};
const PLUSHIES = {
"Sheep Plushie": "B.B 🏪", "Teddy Bear Plushie": "B.B 🏪", "Kitten Plushie": "B.B 🏪",
"Jaguar Plushie": "MX 🇲🇽", "Wolverine Plushie": "CA 🇨🇦", "Nessie Plushie": "UK 🇬🇧",
"Red Fox Plushie": "UK 🇬🇧", "Monkey Plushie": "AR 🇦🇷", "Chamois Plushie": "CH 🇨🇭",
"Panda Plushie": "CN 🇨🇳", "Lion Plushie": "SA 🇿🇦", "Camel Plushie": "AE 🇦🇪", "Stingray Plushie": "KY 🇰🇾"
};
GM_addStyle(`
#dcTracker {
position: fixed;
top: 48px;
left: 15px;
width: 210px;
background: #0b0b0b;
color: #ddd;
font-family: monospace;
font-size: 9px;
border: 1px solid #333;
border-radius: 6px;
z-index: 999999;
box-shadow: 0 4px 10px rgba(0,0,0,0.4);
padding: 5px;
line-height: 1.1;
max-height: 70vh;
overflow-y: auto;
}
.title { font-weight:700; color:#dfe7ff; margin:2px 0; }
.low { color:#ff4d4d; font-weight:700; margin-top:4px; }
ul { list-style:none; margin:0; padding:0; }
li { display:flex; justify-content:space-between; padding:1px 0; white-space:nowrap; }
.need { color:#f7b3b3; }
.loc { color:#aaa; font-size:8px; }
`);
const panel = document.createElement('div');
panel.id = 'dcTracker';
panel.innerHTML = `<div class="title">🌺🧸 Display Tracker</div><div id="dcContent">Loading...</div>`;
document.body.appendChild(panel);
function countSets(items, map) {
const counts = {};
Object.keys(map).forEach(name => counts[name] = 0);
document.querySelectorAll('.item-wrap .item').forEach(el => {
const name = el.querySelector('.item-name')?.innerText.trim();
const qty = parseInt(el.querySelector('.item-amount')?.innerText || "0");
if (map[name]) counts[name] = qty;
});
const minSet = Math.min(...Object.values(counts));
return { counts, sets: minSet };
}
function colorStock(qty) {
if (qty === 0) return '#ff9800';
if (qty < 600) return '#ff5252';
if (qty > 1000) return '#00c853';
return '#ccc';
}
function buildList(title, map) {
const { counts, sets } = countSets(document, map);
const max = Math.max(...Object.values(counts));
let low = Object.entries(counts).sort((a,b)=>a[1]-b[1])[0];
let html = `<div class="title">${title} — sets: ${sets} | pts: ${sets*10}</div>`;
if (low) html += `<div class="low">🛫 Low on ${low[0]} — travel to ${map[low[0]]} 🛬</div>`;
html += `<ul>`;
for (const [name, qty] of Object.entries(counts)) {
const need = max - qty;
html += `<li style="color:${colorStock(qty)}">
<span>${name.split(' ')[0]}</span>
<span>${qty} <span class="need">(${need})</span> <span class="loc">${map[name]}</span></span>
</li>`;
}
html += `</ul>`;
return html;
}
function render() {
const flowers = buildList('Flowers', FLOWERS);
const plushies = buildList('Plushies', PLUSHIES);
document.getElementById('dcContent').innerHTML = flowers + plushies;
}
const observer = new MutationObserver(render);
observer.observe(document.body, { childList: true, subtree: true });
setTimeout(render, 1500);
})();