Обновить kripto-magnat.html

This commit is contained in:
2026-06-20 00:47:13 +07:00
parent 0eae5f59a7
commit 5bf53e3a47
+225 -63
View File
@@ -30,9 +30,10 @@
.tabs { .tabs {
display: flex; gap: 10px; margin-bottom: 20px; display: flex; gap: 10px; margin-bottom: 20px;
background: rgba(0,0,0,0.3); padding: 10px; border-radius: 12px; background: rgba(0,0,0,0.3); padding: 10px; border-radius: 12px;
flex-wrap: wrap;
} }
.tab { .tab {
flex: 1; padding: 12px; border: none; border-radius: 8px; flex: 1; min-width: 100px; padding: 12px; border: none; border-radius: 8px;
background: rgba(255,255,255,0.05); color: #fff; cursor: pointer; background: rgba(255,255,255,0.05); color: #fff; cursor: pointer;
font-size: 14px; font-weight: bold; transition: all 0.3s; font-size: 14px; font-weight: bold; transition: all 0.3s;
} }
@@ -55,14 +56,23 @@
.crypto-item { .crypto-item {
background: rgba(255,255,255,0.05); padding: 15px; background: rgba(255,255,255,0.05); padding: 15px;
border-radius: 8px; margin-bottom: 10px; border-radius: 8px; margin-bottom: 10px;
display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: 10px; border: 1px solid rgba(255,255,255,0.05);
align-items: center; border: 1px solid rgba(255,255,255,0.05); }
.crypto-header {
display: flex; justify-content: space-between; align-items: center;
margin-bottom: 10px;
} }
.crypto-name { font-weight: bold; font-size: 16px; } .crypto-name { font-weight: bold; font-size: 16px; }
.crypto-price { color: #00f2fe; font-size: 18px; font-weight: bold; } .crypto-price { color: #00f2fe; font-size: 18px; font-weight: bold; }
.crypto-change { font-size: 14px; } .crypto-change { font-size: 14px; margin-left: 10px; }
.crypto-change.up { color: #4caf50; } .crypto-change.up { color: #4caf50; }
.crypto-change.down { color: #f44336; } .crypto-change.down { color: #f44336; }
.crypto-buttons {
display: flex; gap: 5px; flex-wrap: wrap;
}
.crypto-buttons button {
flex: 1; min-width: 60px; padding: 8px 5px;
}
.btn { .btn {
padding: 8px 16px; border: none; border-radius: 6px; padding: 8px 16px; border: none; border-radius: 6px;
@@ -76,6 +86,14 @@
.btn:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 5px 15px rgba(0,0,0,0.3); } .btn:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 5px 15px rgba(0,0,0,0.3); }
.btn:disabled { opacity: 0.4; cursor: not-allowed; } .btn:disabled { opacity: 0.4; cursor: not-allowed; }
.quick-buy {
display: flex; gap: 5px; margin-top: 10px;
}
.quick-buy button {
flex: 1; padding: 6px; font-size: 11px;
background: rgba(76, 175, 80, 0.3);
}
.progress-bar { .progress-bar {
background: rgba(255,255,255,0.1); border-radius: 10px; background: rgba(255,255,255,0.1); border-radius: 10px;
height: 30px; overflow: hidden; margin: 10px 0; height: 30px; overflow: hidden; margin: 10px 0;
@@ -92,9 +110,10 @@
border-radius: 8px; margin-bottom: 10px; border-radius: 8px; margin-bottom: 10px;
display: flex; justify-content: space-between; align-items: center; display: flex; justify-content: space-between; align-items: center;
border: 1px solid rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.05);
flex-wrap: wrap; gap: 10px;
} }
.shop-item.owned { border-color: #4caf50; background: rgba(76, 175, 80, 0.1); } .shop-item.owned { border-color: #4caf50; background: rgba(76, 175, 80, 0.1); }
.item-info { flex: 1; } .item-info { flex: 1; min-width: 150px; }
.item-name { font-weight: bold; font-size: 16px; margin-bottom: 5px; } .item-name { font-weight: bold; font-size: 16px; margin-bottom: 5px; }
.item-desc { font-size: 12px; opacity: 0.7; } .item-desc { font-size: 12px; opacity: 0.7; }
.item-price { color: #ffd700; font-weight: bold; margin-right: 15px; } .item-price { color: #ffd700; font-weight: bold; margin-right: 15px; }
@@ -119,6 +138,7 @@
} }
.api-status.connected { color: #4caf50; } .api-status.connected { color: #4caf50; }
.api-status.error { color: #f44336; } .api-status.error { color: #f44336; }
.api-status.fallback { color: #ff9800; }
.transfer-section { .transfer-section {
background: rgba(255, 152, 0, 0.1); border: 1px solid rgba(255, 152, 0, 0.3); background: rgba(255, 152, 0, 0.1); border: 1px solid rgba(255, 152, 0, 0.3);
@@ -138,10 +158,20 @@
} }
.construction-stage.completed { border-color: #4caf50; background: rgba(76, 175, 80, 0.1); } .construction-stage.completed { border-color: #4caf50; background: rgba(76, 175, 80, 0.1); }
.construction-stage.active { border-color: #00f2fe; background: rgba(0, 242, 254, 0.1); } .construction-stage.active { border-color: #00f2fe; background: rgba(0, 242, 254, 0.1); }
.save-indicator {
position: fixed; bottom: 10px; right: 10px;
padding: 8px 16px; border-radius: 20px;
font-size: 12px; background: rgba(76, 175, 80, 0.9);
color: white; z-index: 1000;
opacity: 0; transition: opacity 0.3s;
}
.save-indicator.show { opacity: 1; }
</style> </style>
</head> </head>
<body> <body>
<div class="api-status" id="apiStatus">⏳ API: ожидание...</div> <div class="api-status" id="apiStatus">⏳ API: ожидание...</div>
<div class="save-indicator" id="saveIndicator">💾 Сохранено!</div>
<div class="container"> <div class="container">
<h1>💎 Крипто-Магнат</h1> <h1>💎 Крипто-Магнат</h1>
@@ -149,15 +179,15 @@
<div class="status-bar"> <div class="status-bar">
<div class="status-item"> <div class="status-item">
<div class="status-label">💵 Наличные</div> <div class="status-label">💵 Наличные</div>
<div class="status-value" id="cash">0</div> <div class="status-value" id="cash">$10 000</div>
</div> </div>
<div class="status-item"> <div class="status-item">
<div class="status-label">₿ Крипто</div> <div class="status-label">₿ Крипто</div>
<div class="status-value" id="cryptoValue">0</div> <div class="status-value" id="cryptoValue">$0</div>
</div> </div>
<div class="status-item"> <div class="status-item">
<div class="status-label">🏢 Бизнесы</div> <div class="status-label">🏢 Бизнесы</div>
<div class="status-value" id="businessIncome">0/сек</div> <div class="status-value" id="businessIncome">$0/сек</div>
</div> </div>
<div class="status-item"> <div class="status-item">
<div class="status-label">🏠 Дом</div> <div class="status-label">🏠 Дом</div>
@@ -262,6 +292,7 @@
const INVESTOR_TABLE = 'investor_data'; const INVESTOR_TABLE = 'investor_data';
const MY_SAVE = 'crypto_save'; const MY_SAVE = 'crypto_save';
const MY_TABLE = 'crypto_data'; const MY_TABLE = 'crypto_data';
const LOCAL_STORAGE_KEY = 'cryptoTycoonSave';
let myState = { let myState = {
cash: 10000, cash: 10000,
@@ -305,6 +336,7 @@
let api = null; let api = null;
const statusEl = document.getElementById('apiStatus'); const statusEl = document.getElementById('apiStatus');
const saveIndicator = document.getElementById('saveIndicator');
function updateStatus(text, type = '') { function updateStatus(text, type = '') {
statusEl.textContent = text; statusEl.textContent = text;
@@ -320,6 +352,11 @@
while (el.children.length > 50) el.removeChild(el.lastChild); while (el.children.length > 50) el.removeChild(el.lastChild);
} }
function showSaveIndicator() {
saveIndicator.classList.add('show');
setTimeout(() => saveIndicator.classList.remove('show'), 2000);
}
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
// API ИНИЦИАЛИЗАЦИЯ // API ИНИЦИАЛИЗАЦИЯ
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
@@ -351,29 +388,52 @@
setTimeout(() => { setTimeout(() => {
if (!api) { if (!api) {
updateStatus(' API недоступен', 'error'); updateStatus('⚠️ API недоступен, используем localStorage', 'fallback');
log('API недоступен', 'error'); log('API недоступен, работаем с localStorage', 'warning');
loadState();
updateUI();
renderCrypto();
renderHouse();
renderBusinesses();
renderLuxury();
setInterval(tick, 1000);
setInterval(updateCryptoPrices, 3000);
setInterval(saveState, 10000);
} }
}, 5000); }, 5000);
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
// СОХРАНЕНИЕ / ЗАГРУЗКА // СОХРАНЕНИЕ / ЗАГРУЗКА (С FALLBACK НА LOCALSTORAGE!)
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
async function loadState() { async function loadState() {
if (!api) return; if (api) {
try { try {
const result = await api.selectData(MY_TABLE, { key: 'state' }, MY_SAVE); const result = await api.selectData(MY_TABLE, { key: 'state' }, MY_SAVE);
if (result.data && result.data.length > 0) { if (result.data && result.data.length > 0) {
myState = JSON.parse(result.data[0].value); myState = JSON.parse(result.data[0].value);
log('Состояние загружено', 'success'); log('Состояние загружено из API', 'success');
return;
} }
} catch (e) { } catch (e) {
log('Ошибка загрузки: ' + e.message, 'error'); log('Ошибка загрузки API: ' + e.message, 'error');
}
}
// Fallback на localStorage
const saved = localStorage.getItem(LOCAL_STORAGE_KEY);
if (saved) {
try {
myState = JSON.parse(saved);
log('Состояние загружено из localStorage', 'success');
} catch (e) {
log('Ошибка загрузки localStorage', 'error');
}
} }
} }
async function saveState() { async function saveState() {
if (!api) return; if (api) {
try { try {
await api.deleteData(MY_TABLE, { key: 'state' }, MY_SAVE); await api.deleteData(MY_TABLE, { key: 'state' }, MY_SAVE);
await api.insertData(MY_TABLE, { await api.insertData(MY_TABLE, {
@@ -381,19 +441,44 @@
value: JSON.stringify(myState), value: JSON.stringify(myState),
updated_at: new Date().toISOString() updated_at: new Date().toISOString()
}, MY_SAVE); }, MY_SAVE);
showSaveIndicator();
return;
} catch (e) { } catch (e) {
log('Ошибка сохранения: ' + e.message, 'error'); log('Ошибка сохранения API: ' + e.message, 'error');
} }
} }
// Fallback на localStorage
try {
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(myState));
showSaveIndicator();
} catch (e) {
log('Ошибка сохранения localStorage: ' + e.message, 'error');
}
}
// Автосохранение при закрытии страницы
window.addEventListener('beforeunload', () => {
if (api) {
navigator.sendBeacon('/api/save', JSON.stringify({
table: MY_TABLE,
key: 'state',
value: JSON.stringify(myState),
save: MY_SAVE
}));
}
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(myState));
});
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
// КРИПТО БИРЖА // КРИПТО БИРЖА (ИСПРАВЛЕНО!)
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
function updateCryptoPrices() { function updateCryptoPrices() {
for (let symbol in cryptos) { for (let symbol in cryptos) {
const change = (Math.random() - 0.5) * 0.1; const change = (Math.random() - 0.5) * 0.1;
cryptos[symbol].change = change; cryptos[symbol].change = change;
cryptos[symbol].price *= (1 + change); cryptos[symbol].price *= (1 + change);
if (cryptos[symbol].price < 0.000001) cryptos[symbol].price = 0.000001;
} }
renderCrypto(); renderCrypto();
updateUI(); updateUI();
@@ -406,19 +491,34 @@
const crypto = cryptos[symbol]; const crypto = cryptos[symbol];
const changeClass = crypto.change >= 0 ? 'up' : 'down'; const changeClass = crypto.change >= 0 ? 'up' : 'down';
const changeSign = crypto.change >= 0 ? '+' : ''; const changeSign = crypto.change >= 0 ? '+' : '';
const canBuy = myState.cash >= crypto.price;
const hasPortfolio = myState.portfolio[symbol] > 0;
list.innerHTML += ` list.innerHTML += `
<div class="crypto-item"> <div class="crypto-item">
<div class="crypto-header">
<div> <div>
<div class="crypto-name">${symbol}</div> <div class="crypto-name">${symbol}</div>
<div style="font-size: 12px; opacity: 0.7;">${crypto.name}</div> <div style="font-size: 12px; opacity: 0.7;">${crypto.name}</div>
</div> </div>
<div class="crypto-price">$${crypto.price.toFixed(2)}</div>
<div class="crypto-change ${changeClass}">${changeSign}${(crypto.change * 100).toFixed(2)}%</div>
<div> <div>
<button class="btn btn-buy" onclick="buyCrypto('${symbol}')">Купить</button> <span class="crypto-price">$${crypto.price < 1 ? crypto.price.toFixed(6) : crypto.price.toFixed(2)}</span>
<button class="btn btn-sell" onclick="sellCrypto('${symbol}')" ${myState.portfolio[symbol] ? '' : 'disabled'}>Продать</button> <span class="crypto-change ${changeClass}">${changeSign}${(crypto.change * 100).toFixed(2)}%</span>
</div> </div>
</div> </div>
<div class="crypto-buttons">
<button class="btn btn-buy" onclick="buyCryptoAmount('${symbol}', 100)" ${myState.cash < 100 ? 'disabled' : ''}>Купить на $100</button>
<button class="btn btn-buy" onclick="buyCryptoAmount('${symbol}', 1000)" ${myState.cash < 1000 ? 'disabled' : ''}>Купить на $1000</button>
<button class="btn btn-buy" onclick="buyCryptoPercent('${symbol}', 0.1)" ${myState.cash < 10 ? 'disabled' : ''}>10%</button>
<button class="btn btn-sell" onclick="sellCryptoPercent('${symbol}', 1)" ${!hasPortfolio ? 'disabled' : ''}>Продать всё</button>
</div>
${hasPortfolio ? `
<div style="margin-top: 10px; font-size: 13px; opacity: 0.8;">
У вас: ${myState.portfolio[symbol].toFixed(6)} ${symbol}
(≈$${(myState.portfolio[symbol] * crypto.price).toFixed(2)})
</div>
` : ''}
</div>
`; `;
} }
renderPortfolio(); renderPortfolio();
@@ -430,14 +530,23 @@
let html = ''; let html = '';
for (let symbol in myState.portfolio) { for (let symbol in myState.portfolio) {
const amount = myState.portfolio[symbol]; const amount = myState.portfolio[symbol];
if (amount < 0.000001) continue;
const value = amount * cryptos[symbol].price; const value = amount * cryptos[symbol].price;
totalValue += value; totalValue += value;
html += ` html += `
<div class="crypto-item"> <div class="crypto-item">
<div class="crypto-header">
<div class="crypto-name">${symbol}</div> <div class="crypto-name">${symbol}</div>
<div>${amount.toFixed(6)}</div>
<div class="crypto-price">$${value.toFixed(2)}</div> <div class="crypto-price">$${value.toFixed(2)}</div>
</div> </div>
<div style="font-size: 13px; opacity: 0.8;">
${amount.toFixed(6)} ${symbol}
</div>
<button class="btn btn-sell" style="margin-top: 10px; width: 100%;"
onclick="sellCryptoPercent('${symbol}', 1)">
Продать всё за $${value.toFixed(2)}
</button>
</div>
`; `;
} }
if (html === '') { if (html === '') {
@@ -447,33 +556,43 @@
document.getElementById('cryptoValue').textContent = '$' + Math.floor(totalValue).toLocaleString(); document.getElementById('cryptoValue').textContent = '$' + Math.floor(totalValue).toLocaleString();
} }
function buyCrypto(symbol) { // Покупка на указанную сумму в долларах (ИСПРАВЛЕНО!)
const amount = parseFloat(prompt(`Сколько ${symbol} купить? (цена: $${cryptos[symbol].price.toFixed(2)})`)); function buyCryptoAmount(symbol, amountUsd) {
if (!amount || amount <= 0) return; const price = cryptos[symbol].price;
const cost = amount * cryptos[symbol].price; if (myState.cash < amountUsd) {
if (myState.cash < cost) { log(`Недостаточно средств (есть $${Math.floor(myState.cash)}, нужно $${amountUsd})`, 'error');
log('Недостаточно средств', 'error');
return; return;
} }
myState.cash -= cost; const amount = amountUsd / price;
myState.cash -= amountUsd;
myState.portfolio[symbol] = (myState.portfolio[symbol] || 0) + amount; myState.portfolio[symbol] = (myState.portfolio[symbol] || 0) + amount;
log(`Куплено ${amount} ${symbol} за $${cost.toFixed(2)}`, 'success'); log(`Куплено ${amount.toFixed(6)} ${symbol} за $${amountUsd}`, 'success');
saveState();
renderCrypto(); renderCrypto();
updateUI(); updateUI();
} }
function sellCrypto(symbol) { // Покупка на процент от денег
const amount = parseFloat(prompt(`Сколько ${symbol} продать? (есть: ${myState.portfolio[symbol]})`)); function buyCryptoPercent(symbol, percent) {
if (!amount || amount <= 0) return; const amountUsd = myState.cash * percent;
if (myState.portfolio[symbol] < amount) { buyCryptoAmount(symbol, amountUsd);
log('Недостаточно криптовалюты', 'error'); }
// Продажа процента от криптовалюты
function sellCryptoPercent(symbol, percent) {
if (!myState.portfolio[symbol] || myState.portfolio[symbol] < 0.000001) {
log(`У вас нет ${symbol}`, 'error');
return; return;
} }
const amount = myState.portfolio[symbol] * percent;
const revenue = amount * cryptos[symbol].price; const revenue = amount * cryptos[symbol].price;
myState.cash += revenue; myState.cash += revenue;
myState.portfolio[symbol] -= amount; myState.portfolio[symbol] -= amount;
if (myState.portfolio[symbol] < 0.000001) delete myState.portfolio[symbol]; if (myState.portfolio[symbol] < 0.000001) {
log(`Продано ${amount} ${symbol} за $${revenue.toFixed(2)}`, 'success'); delete myState.portfolio[symbol];
}
log(`Продано ${amount.toFixed(6)} ${symbol} за $${revenue.toFixed(2)}`, 'success');
saveState();
renderCrypto(); renderCrypto();
updateUI(); updateUI();
} }
@@ -482,10 +601,10 @@
// ПЕРЕВОДЫ // ПЕРЕВОДЫ
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
async function transferFrom(source) { async function transferFrom(source) {
if (!api) { log('API недоступен', 'error'); return; } if (!api) { log('API недоступен для переводов', 'error'); return; }
const input = document.getElementById(source === 'clicker' ? 'fromClicker' : 'fromInvestor'); const input = document.getElementById(source === 'clicker' ? 'fromClicker' : 'fromInvestor');
const amount = parseFloat(input.value); const amount = parseFloat(input.value);
if (!amount || amount <= 0) { log('Введите сумму', 'error'); return; } if (!amount || amount <= 0) { log('Введите корректную сумму', 'error'); return; }
try { try {
let sourceTable, sourceSave, sourceKey; let sourceTable, sourceSave, sourceKey;
@@ -509,7 +628,7 @@
const available = source === 'clicker' ? state.score : state.capital; const available = source === 'clicker' ? state.score : state.capital;
if (available < amount) { if (available < amount) {
log('Недостаточно средств в источнике', 'error'); log(`Недостаточно средств в источнике (есть ${Math.floor(available)}, нужно ${amount})`, 'error');
return; return;
} }
@@ -527,8 +646,9 @@
}, sourceSave, source); }, sourceSave, source);
myState.cash += amount; myState.cash += amount;
log(`Получено $${amount} из ${source}`, 'success'); log(`Получено $${amount.toLocaleString()} из ${source}`, 'success');
input.value = ''; input.value = '';
saveState();
updateUI(); updateUI();
await refreshAvailable(); await refreshAvailable();
} catch (e) { } catch (e) {
@@ -537,11 +657,14 @@
} }
async function transferTo(target) { async function transferTo(target) {
if (!api) { log('API недоступен', 'error'); return; } if (!api) { log('API недоступен для переводов', 'error'); return; }
const input = document.getElementById(target === 'clicker' ? 'toClicker' : 'toInvestor'); const input = document.getElementById(target === 'clicker' ? 'toClicker' : 'toInvestor');
const amount = parseFloat(input.value); const amount = parseFloat(input.value);
if (!amount || amount <= 0) { log('Введите сумму', 'error'); return; } if (!amount || amount <= 0) { log('Введите корректную сумму', 'error'); return; }
if (myState.cash < amount) { log('Недостаточно средств', 'error'); return; } if (myState.cash < amount) {
log(`Недостаточно средств (есть $${Math.floor(myState.cash)}, нужно $${amount})`, 'error');
return;
}
try { try {
let targetTable, targetSave, targetKey; let targetTable, targetSave, targetKey;
@@ -576,8 +699,9 @@
}, targetSave, target); }, targetSave, target);
myState.cash -= amount; myState.cash -= amount;
log(`Отправлено $${amount} в ${target}`, 'success'); log(`Отправлено $${amount.toLocaleString()} в ${target}`, 'success');
input.value = ''; input.value = '';
saveState();
updateUI(); updateUI();
} catch (e) { } catch (e) {
log('Ошибка перевода: ' + e.message, 'error'); log('Ошибка перевода: ' + e.message, 'error');
@@ -616,12 +740,17 @@
container.innerHTML += ` container.innerHTML += `
<div class="construction-stage ${isCompleted ? 'completed' : ''} ${isActive ? 'active' : ''}"> <div class="construction-stage ${isCompleted ? 'completed' : ''} ${isActive ? 'active' : ''}">
<div style="display: flex; justify-content: space-between; margin-bottom: 10px;"> <div style="display: flex; justify-content: space-between; margin-bottom: 10px; flex-wrap: wrap; gap: 10px;">
<div> <div>
<div style="font-weight: bold; font-size: 16px;">${stage.name}</div> <div style="font-weight: bold; font-size: 16px;">${stage.name}</div>
<div style="font-size: 12px; opacity: 0.7;">Стоимость: $${stage.cost.toLocaleString()} | Время: ${stage.time}с</div> <div style="font-size: 12px; opacity: 0.7;">Стоимость: $${stage.cost.toLocaleString()} | Время: ${stage.time}с</div>
</div> </div>
${isActive ? `<button class="btn btn-action" onclick="buildStage()">Строить</button>` : ''} ${isActive && !isCompleted ? `
<button class="btn btn-action" onclick="buildStage()"
${myState.cash < stage.cost ? 'disabled' : ''}>
${myState.house.progress > 0 ? '⚡ Ускорить' : '🏗️ Начать строить'}
</button>
` : ''}
${isCompleted ? '<div style="color: #4caf50; font-weight: bold;">✓ Готово</div>' : ''} ${isCompleted ? '<div style="color: #4caf50; font-weight: bold;">✓ Готово</div>' : ''}
</div> </div>
${isActive ? ` ${isActive ? `
@@ -641,12 +770,19 @@
} }
const stage = houseStages[myState.house.stage]; const stage = houseStages[myState.house.stage];
if (myState.cash < stage.cost) { if (myState.cash < stage.cost) {
log('Недостаточно средств', 'error'); log(`Недостаточно средств (есть $${Math.floor(myState.cash)}, нужно $${stage.cost})`, 'error');
return; return;
} }
if (myState.house.progress === 0) {
myState.cash -= stage.cost; myState.cash -= stage.cost;
}
myState.house.progress += 10;
if (myState.house.progress >= 100) {
myState.house.stage++;
myState.house.progress = 0; myState.house.progress = 0;
log(`Начато строительство: ${stage.name}`, 'success'); log(`Этап "${stage.name}" завершён!`, 'success');
}
saveState();
renderHouse(); renderHouse();
updateUI(); updateUI();
} }
@@ -663,7 +799,10 @@
<div class="shop-item ${owned ? 'owned' : ''}"> <div class="shop-item ${owned ? 'owned' : ''}">
<div class="item-info"> <div class="item-info">
<div class="item-name">${biz.name}</div> <div class="item-name">${biz.name}</div>
<div class="item-desc">Доход: $${biz.income}/сек</div> <div class="item-desc">
Доход: $${biz.income}/сек
${owned ? ` | Работников: ${myState.businesses[biz.id].workers} | Эффективность: x${myState.businesses[biz.id].efficiency.toFixed(1)}` : ''}
</div>
</div> </div>
<div class="item-price">$${biz.cost.toLocaleString()}</div> <div class="item-price">$${biz.cost.toLocaleString()}</div>
<button class="btn ${owned ? 'btn-action' : 'btn-buy'}" <button class="btn ${owned ? 'btn-action' : 'btn-buy'}"
@@ -679,24 +818,41 @@
function buyBusiness(id) { function buyBusiness(id) {
const biz = businesses.find(b => b.id === id); const biz = businesses.find(b => b.id === id);
if (myState.cash < biz.cost) { if (myState.cash < biz.cost) {
log('Недостаточно средств', 'error'); log(`Недостаточно средств (есть $${Math.floor(myState.cash)}, нужно $${biz.cost})`, 'error');
return; return;
} }
myState.cash -= biz.cost; myState.cash -= biz.cost;
myState.businesses[id] = { workers: 1, efficiency: 1 }; myState.businesses[id] = { workers: 1, efficiency: 1 };
log(`Куплен бизнес: ${biz.name}`, 'success'); log(`Куплен бизнес: ${biz.name}`, 'success');
saveState();
renderBusinesses(); renderBusinesses();
updateUI(); updateUI();
} }
function manageBusiness(id) { function manageBusiness(id) {
const biz = businesses.find(b => b.id === id); const biz = businesses.find(b => b.id === id);
const action = prompt(`Управление: ${biz.name}\n1. Нанять работника ($${biz.cost / 10})\n2. Уволить работника\n3. Улучшить эффективность ($${biz.cost / 5})\nВведите номер:`); const hireCost = Math.floor(biz.cost / 10);
const upgradeCost = Math.floor(biz.cost / 5);
const action = prompt(
`Управление: ${biz.name}\n\n` +
`Текущее состояние:\n` +
`- Работников: ${myState.businesses[id].workers}\n` +
`- Эффективность: x${myState.businesses[id].efficiency.toFixed(1)}\n` +
`- Доход: $${Math.floor(biz.income * myState.businesses[id].workers * myState.businesses[id].efficiency)}/сек\n\n` +
`Действия:\n` +
`1. Нанять работника ($${hireCost.toLocaleString()})\n` +
`2. Уволить работника (бесплатно)\n` +
`3. Улучшить эффективность x1.5 ($${upgradeCost.toLocaleString()})\n\n` +
`Введите номер действия:`
);
if (action === '1') { if (action === '1') {
const cost = biz.cost / 10; if (myState.cash < hireCost) {
if (myState.cash < cost) { log('Недостаточно средств', 'error'); return; } log(`Недостаточно средств (нужно $${hireCost})`, 'error');
myState.cash -= cost; return;
}
myState.cash -= hireCost;
myState.businesses[id].workers++; myState.businesses[id].workers++;
log(`Нанят работник в ${biz.name}`, 'success'); log(`Нанят работник в ${biz.name}`, 'success');
} else if (action === '2') { } else if (action === '2') {
@@ -707,12 +863,15 @@
log('Нельзя уволить последнего работника', 'error'); log('Нельзя уволить последнего работника', 'error');
} }
} else if (action === '3') { } else if (action === '3') {
const cost = biz.cost / 5; if (myState.cash < upgradeCost) {
if (myState.cash < cost) { log('Недостаточно средств', 'error'); return; } log(`Недостаточно средств (нужно $${upgradeCost})`, 'error');
myState.cash -= cost; return;
myState.businesses[id].efficiency *= 1.5;
log(`Улучшена эффективность ${biz.name}`, 'success');
} }
myState.cash -= upgradeCost;
myState.businesses[id].efficiency *= 1.5;
log(`Улучшена эффективность ${biz.name} до x${myState.businesses[id].efficiency.toFixed(1)}`, 'success');
}
saveState();
renderBusinesses(); renderBusinesses();
updateUI(); updateUI();
} }
@@ -744,13 +903,18 @@
function buyLuxury(id) { function buyLuxury(id) {
const item = luxuryItems.find(i => i.id === id); const item = luxuryItems.find(i => i.id === id);
if (myState.luxury[id]) {
log('У вас уже есть этот предмет', 'error');
return;
}
if (myState.cash < item.cost) { if (myState.cash < item.cost) {
log('Недостаточно средств', 'error'); log(`Недостаточно средств (есть $${Math.floor(myState.cash)}, нужно $${item.cost})`, 'error');
return; return;
} }
myState.cash -= item.cost; myState.cash -= item.cost;
myState.luxury[id] = true; myState.luxury[id] = true;
log(`Куплено: ${item.name}`, 'success'); log(`Куплено: ${item.name}`, 'success');
saveState();
renderLuxury(); renderLuxury();
updateUI(); updateUI();
} }
@@ -759,7 +923,6 @@
// ИГРОВОЙ ЦИКЛ // ИГРОВОЙ ЦИКЛ
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
function tick() { function tick() {
// Доход от бизнесов
let totalIncome = 0; let totalIncome = 0;
for (let id in myState.businesses) { for (let id in myState.businesses) {
const biz = businesses.find(b => b.id === id); const biz = businesses.find(b => b.id === id);
@@ -771,7 +934,6 @@
myState.cash += totalIncome; myState.cash += totalIncome;
} }
// Строительство дома
if (myState.house.stage < houseStages.length && myState.house.progress > 0) { if (myState.house.stage < houseStages.length && myState.house.progress > 0) {
const stage = houseStages[myState.house.stage]; const stage = houseStages[myState.house.stage];
myState.house.progress += (100 / stage.time); myState.house.progress += (100 / stage.time);