Created
July 15, 2025 18:17
-
-
Save williamjayjay/c87964ba2e98aebaa3ba84bccce10e94 to your computer and use it in GitHub Desktop.
RPG GAME - Focus Pomodoro D3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="pt-BR"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Diário do Aventureiro - Registro de Missões</title> | |
<link href="https://fonts.googleapis.com/css2?family=Cinzel:wght@400;700&family=MedievalSharp&display=swap" | |
rel="stylesheet"> | |
<style> | |
:root { | |
/* Cores e Elementos Inspirados em Diablo III */ | |
--primary-color: #8c0a0a; | |
/* Vermelho escuro de Diablo */ | |
--secondary-color: #5e0000; | |
/* Vermelho ainda mais escuro */ | |
--background-color: #0d0d0d; | |
/* Fundo quase preto */ | |
--card-background: #1c1c1c; | |
/* Placas de metal escuro */ | |
--text-color: #e0d8c0; | |
/* Papel antigo / pergaminho */ | |
--xp-color: #ffd700; | |
/* Ouro */ | |
--border-color: #4a3b2e; | |
/* Borda de metal enferrujado */ | |
--progress-bar-bg: #2d2d2d; | |
/* Fundo da barra de vida/recurso */ | |
--progress-bar-fill: #0a700a; | |
/* Verde de vida */ | |
--button-bg: #8c0a0a; | |
/* Botão vermelho */ | |
--button-hover-bg: #a32d2d; | |
/* Hover mais claro */ | |
--border-radius: 4px; | |
/* Cantos menos arredondados */ | |
--padding-size: 20px; | |
} | |
body { | |
font-family: 'MedievalSharp', cursive; | |
/* Fonte de RPG */ | |
margin: 0; | |
padding: 0; | |
background-color: var(--background-color); | |
color: var(--text-color); | |
display: flex; | |
flex-direction: column; | |
align-items: center; | |
min-height: 100vh; | |
overflow-x: hidden; | |
background-image: url('https://blz-contentstack-images.akamaized.net/v3/assets/bltfad370659b122b0c/blt3f5a287a32d665a3/62e08e68400037064d1f2113/01_D2R_Launch_Wallpaper_Desktop_1920x1080.jpg'); | |
/* Exemplo de BG de Diablo */ | |
background-size: cover; | |
background-position: center; | |
background-attachment: fixed; | |
position: relative; | |
} | |
body::before { | |
content: ''; | |
position: absolute; | |
top: 0; | |
left: 0; | |
right: 0; | |
bottom: 0; | |
background-color: rgba(0, 0, 0, 0.7); | |
/* Overlay escuro para melhorar legibilidade */ | |
z-index: 1; | |
} | |
.container { | |
position: relative; | |
z-index: 2; | |
background-color: var(--card-background); | |
border-radius: var(--border-radius); | |
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.8); | |
padding: var(--padding-size); | |
margin: var(--padding-size); | |
width: 95%; | |
max-width: 1000px; | |
display: flex; | |
flex-wrap: wrap; | |
gap: var(--padding-size); | |
box-sizing: border-box; | |
border: 2px solid var(--border-color); | |
/* Borda mais pronunciada */ | |
background-image: url('https://www.diablowiki.net/images/thumb/8/87/UI_Inventory_Background.png/250px-UI_Inventory_Background.png'); | |
/* Textura de fundo do painel */ | |
background-size: cover; | |
background-blend-mode: multiply; | |
background-color: var(--card-background); | |
} | |
h1, | |
h2 { | |
font-family: 'Cinzel', serif; | |
/* Fonte de título de Diablo */ | |
color: var(--primary-color); | |
text-align: center; | |
margin-bottom: var(--padding-size); | |
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.9); | |
text-transform: uppercase; | |
letter-spacing: 1.5px; | |
} | |
/* Seções de Registro e Atributos */ | |
.log-mission-section, | |
.skills-section, | |
.history-section { | |
flex: 1; | |
min-width: 350px; | |
background-color: rgba(30, 30, 30, 0.9); | |
/* Fundo semitransparente para card */ | |
padding: var(--padding-size); | |
border-radius: var(--border-radius); | |
box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.6); | |
box-sizing: border-box; | |
border: 1px solid var(--border-color); | |
/* Borda do card interno */ | |
} | |
.mission-controls label { | |
display: block; | |
margin-bottom: 10px; | |
font-weight: bold; | |
color: var(--text-color); | |
font-size: 1.1em; | |
} | |
.mission-controls input[type="text"], | |
.mission-controls select { | |
width: calc(100% - 24px); | |
padding: 12px; | |
margin-bottom: 20px; | |
border: 1px solid var(--border-color); | |
border-radius: var(--border-radius); | |
background-color: #3d3d3d; | |
color: var(--text-color); | |
box-sizing: border-box; | |
font-size: 1em; | |
font-family: 'MedievalSharp', cursive; | |
appearance: none; | |
/* Remove estilo padrão do select */ | |
background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23e0d8c0%22%20d%3D%22M287%2069.9a14.6%2014.6%200%2000-20.6%200l-123.8%20123.8L19.8%2069.9a14.6%2014.6%200%2000-20.6%2020.6L145.7%20247.7c6%206%2014.6%206%2020.6%200L287%2090.5a14.6%2014.6%200%20000-20.6z%22%2F%3E%3C%2Fsvg%3E'); | |
background-repeat: no-repeat; | |
background-position: right 10px top 50%; | |
background-size: 12px auto; | |
} | |
.mission-controls button { | |
background-color: var(--button-bg); | |
color: #fff; | |
padding: 15px 25px; | |
border: 1px solid var(--border-color); | |
border-radius: var(--border-radius); | |
cursor: pointer; | |
font-size: 1.1em; | |
transition: background-color 0.3s ease, transform 0.2s ease; | |
text-transform: uppercase; | |
font-weight: bold; | |
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.5); | |
width: 100%; | |
font-family: 'Cinzel', serif; | |
} | |
.mission-controls button:hover { | |
background-color: var(--button-hover-bg); | |
transform: translateY(-2px); | |
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.7); | |
} | |
.mission-controls button:disabled { | |
background-color: #555; | |
cursor: not-allowed; | |
opacity: 0.7; | |
transform: none; | |
box-shadow: none; | |
} | |
/* Seção de Skills */ | |
.xp-display { | |
text-align: center; | |
font-size: 2.2em; | |
margin-bottom: 30px; | |
color: var(--xp-color); | |
font-weight: bold; | |
text-shadow: 0 0 12px rgba(255, 215, 0, 0.6); | |
letter-spacing: 1px; | |
} | |
.skills-list { | |
display: flex; | |
flex-direction: column; | |
gap: 20px; | |
} | |
.skill-item { | |
background-color: rgba(40, 40, 40, 0.9); | |
padding: 15px; | |
border-radius: var(--border-radius); | |
display: flex; | |
flex-direction: column; | |
gap: 12px; | |
border: 1px solid var(--border-color); | |
box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.4); | |
} | |
.skill-header { | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
} | |
.skill-item span { | |
font-size: 1.3em; | |
font-weight: bold; | |
color: var(--primary-color); | |
font-family: 'Cinzel', serif; | |
} | |
.skill-item .level { | |
background-color: var(--secondary-color); | |
padding: 6px 14px; | |
border-radius: 4px; | |
font-size: 0.95em; | |
color: #fff; | |
text-transform: uppercase; | |
font-family: 'Cinzel', serif; | |
border: 1px solid var(--primary-color); | |
} | |
/* Barra de Progresso (Vida/Mana estilo Diablo) */ | |
.progress-bar-container { | |
width: 100%; | |
background-color: var(--progress-bar-bg); | |
border-radius: 4px; | |
height: 16px; | |
/* Mais robusta */ | |
overflow: hidden; | |
position: relative; | |
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.5); | |
border: 1px solid #1a1a1a; | |
} | |
.progress-bar-fill { | |
height: 100%; | |
background-color: var(--progress-bar-fill); | |
width: 0%; | |
border-radius: 4px; | |
transition: width 0.5s ease-in-out; | |
box-shadow: inset 0 0 5px rgba(0, 255, 0, 0.3); | |
/* Brilho verde */ | |
} | |
.progress-text { | |
position: absolute; | |
width: 100%; | |
text-align: center; | |
line-height: 16px; | |
font-size: 0.85em; | |
color: #fff; | |
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.7); | |
top: 0; | |
font-family: 'Cinzel', serif; | |
} | |
.skill-item button { | |
background-color: var(--xp-color); | |
color: #333; | |
padding: 12px 20px; | |
border: 1px solid #a89400; | |
border-radius: var(--border-radius); | |
cursor: pointer; | |
font-size: 1em; | |
font-weight: bold; | |
transition: background-color 0.3s ease, transform 0.2s ease; | |
text-transform: uppercase; | |
align-self: flex-end; | |
margin-top: 10px; | |
font-family: 'Cinzel', serif; | |
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.4); | |
} | |
.skill-item button:hover { | |
background-color: #e6b100; | |
transform: translateY(-1px); | |
} | |
.skill-item button:disabled { | |
background-color: #7f8c8d; | |
cursor: not-allowed; | |
opacity: 0.6; | |
transform: none; | |
box-shadow: none; | |
} | |
/* Seção de Histórico */ | |
.history-section { | |
width: 100%; | |
margin-top: var(--padding-size); | |
} | |
.history-list { | |
list-style-type: none; | |
padding: 0; | |
max-height: 350px; | |
overflow-y: auto; | |
border: 1px solid var(--border-color); | |
border-radius: var(--border-radius); | |
background-color: rgba(30, 30, 30, 0.9); | |
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3); | |
} | |
.history-list li { | |
padding: 12px 18px; | |
border-bottom: 1px dashed #3a3a3a; | |
font-size: 0.95em; | |
color: var(--text-color); | |
display: flex; | |
flex-direction: column; | |
align-items: flex-start; | |
} | |
.history-list li:last-child { | |
border-bottom: none; | |
} | |
.history-list li .task-name { | |
font-weight: bold; | |
color: var(--xp-color); | |
margin-bottom: 6px; | |
font-size: 1.1em; | |
font-family: 'Cinzel', serif; | |
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.7); | |
} | |
.history-list li .task-details { | |
display: flex; | |
flex-direction: column; | |
width: 100%; | |
font-size: 0.85em; | |
color: #ccc; | |
font-family: 'MedievalSharp', cursive; | |
} | |
.history-list li .task-details span { | |
margin-bottom: 4px; | |
} | |
/* Scrollbar Personalizada (Webkit) */ | |
::-webkit-scrollbar { | |
width: 10px; | |
} | |
::-webkit-scrollbar-track { | |
background: #2b2b2b; | |
border-radius: 5px; | |
} | |
::-webkit-scrollbar-thumb { | |
background: #555; | |
border-radius: 5px; | |
border: 1px solid #4a4a4a; | |
} | |
::-webkit-scrollbar-thumb:hover { | |
background: #777; | |
} | |
/* Responsividade */ | |
@media (max-width: 768px) { | |
.container { | |
flex-direction: column; | |
margin: 10px; | |
padding: 15px; | |
} | |
.log-mission-section, | |
.skills-section, | |
.history-section { | |
min-width: unset; | |
width: 100%; | |
padding: 15px; | |
} | |
h1, | |
h2 { | |
font-size: 1.8em; | |
} | |
.xp-display { | |
font-size: 1.8em; | |
} | |
.skill-item span { | |
font-size: 1.1em; | |
} | |
.skill-item button { | |
padding: 10px 15px; | |
font-size: 0.9em; | |
} | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<div class="log-mission-section"> | |
<h2>Registro de Missões Concluídas</h2> | |
<div class="mission-controls"> | |
<label for="taskName">Nome da Missão (Obrigatório):</label> | |
<input type="text" id="taskName" placeholder="Ex: Treino de Espada, Estudo de Magia" required> | |
<label for="pomodoroDuration">Duração da Missão (Minutos):</label> | |
<select id="pomodoroDuration"> | |
<option value="10">Treino Leve (10 min)</option> | |
<option value="18" selected>Patrulha Padrão (18 min)</option> | |
<option value="25">Expedição Longa (25 min)</option> | |
<option value="50">Jornada Épica (50 min)</option> | |
</select> | |
<button id="registerMission">Registrar Conclusão</button> | |
</div> | |
</div> | |
<div class="skills-section"> | |
<h2>Atributos do Aventureiro</h2> | |
<div class="xp-display"> | |
XP Disponível: <span id="currentXP">0</span> | |
</div> | |
<div class="skills-list"> | |
<div class="skill-item"> | |
<div class="skill-header"> | |
<span>Força</span> | |
<span class="level" id="strengthLevel">Nível 1</span> | |
</div> | |
<div class="progress-bar-container"> | |
<div class="progress-bar-fill" id="strengthProgress"></div> | |
<div class="progress-text" id="strengthProgressText">0/100</div> | |
</div> | |
<button data-skill="strength" disabled>Aprimorar Força</button> | |
</div> | |
<div class="skill-item"> | |
<div class="skill-header"> | |
<span>Inteligência</span> | |
<span class="level" id="intelligenceLevel">Nível 1</span> | |
</div> | |
<div class="progress-bar-container"> | |
<div class="progress-bar-fill" id="intelligenceProgress"></div> | |
<div class="progress-text" id="intelligenceProgressText">0/100</div> | |
</div> | |
<button data-skill="intelligence" disabled>Aprimorar Inteligência</button> | |
</div> | |
<div class="skill-item"> | |
<div class="skill-header"> | |
<span>Agilidade</span> | |
<span class="level" id="agilityLevel">Nível 1</span> | |
</div> | |
<div class="progress-bar-container"> | |
<div class="progress-bar-fill" id="agilityProgress"></div> | |
<div class="progress-text" id="agilityProgressText">0/100</div> | |
</div> | |
<button data-skill="agility" disabled>Aprimorar Agilidade</button> | |
</div> | |
<div class="skill-item"> | |
<div class="skill-header"> | |
<span>Resistência</span> | |
<span class="level" id="resistanceLevel">Nível 1</span> | |
</div> | |
<div class="progress-bar-container"> | |
<div class="progress-bar-fill" id="resistanceProgress"></div> | |
<div class="progress-text" id="resistanceProgressText">0/100</div> | |
</div> | |
<button data-skill="resistance" disabled>Aprimorar Resistência</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="container history-section"> | |
<h2>Pergaminhos de Conquistas Passadas</h2> | |
<ul id="pomodoroHistoryList" class="history-list"> | |
<li style="text-align: center; color: #777;">Nenhuma missão registrada ainda.</li> | |
</ul> | |
</div> | |
<script> | |
const registerMissionButton = document.getElementById('registerMission'); | |
const taskNameInput = document.getElementById('taskName'); | |
const pomodoroDurationSelect = document.getElementById('pomodoroDuration'); | |
const xpDisplay = document.getElementById('currentXP'); | |
const skillButtons = document.querySelectorAll('.skill-item button'); | |
const pomodoroHistoryList = document.getElementById('pomodoroHistoryList'); | |
let xpPoints = 0; | |
let pomodoroHistory = []; | |
// Valores de XP para cada duração de "pomodoro" | |
const xpValues = { | |
'10': 1, | |
'18': 2, | |
'25': 3, | |
'50': 5, // Nova duração | |
}; | |
const skillsData = { | |
strength: { level: 1, progress: 0, maxProgress: 100 }, | |
intelligence: { level: 1, progress: 0, maxProgress: 100 }, | |
agility: { level: 1, progress: 0, maxProgress: 100 }, | |
resistance: { level: 1, progress: 0, maxProgress: 100 }, | |
}; | |
// --- Utility Function for Formatting Dates --- | |
function formatDateTime(date) { | |
if (!date) return 'N/A'; | |
const options = { | |
year: 'numeric', month: '2-digit', day: '2-digit', | |
hour: '2-digit', minute: '2-digit', second: '2-digit', | |
hour12: false | |
}; | |
return new Date(date).toLocaleString('pt-BR', options); | |
} | |
// --- Save/Load Game Data (via localStorage) --- | |
function saveGameData() { | |
const gameData = { | |
xpPoints: xpPoints, | |
skills: skillsData, | |
pomodoroHistory: pomodoroHistory.map(item => ({ | |
...item, | |
timestamp: item.timestamp ? item.timestamp.toISOString() : null, | |
})), | |
lastSave: new Date().toISOString() | |
}; | |
localStorage.setItem('rpgMissionLogData', JSON.stringify(gameData)); | |
console.log('Game data saved:', gameData); | |
} | |
function loadGameData() { | |
const savedData = localStorage.getItem('rpgMissionLogData'); | |
if (savedData) { | |
const gameData = JSON.parse(savedData); | |
xpPoints = gameData.xpPoints || 0; | |
xpDisplay.textContent = xpPoints; | |
pomodoroHistory = (gameData.pomodoroHistory || []).map(item => ({ | |
...item, | |
timestamp: item.timestamp ? new Date(item.timestamp) : null, | |
})); | |
if (gameData.skills) { | |
for (const skillName in gameData.skills) { | |
if (skillsData[skillName]) { | |
skillsData[skillName].level = gameData.skills[skillName].level; | |
skillsData[skillName].progress = gameData.skills[skillName].progress; | |
updateSkillDisplay(skillName); | |
} | |
} | |
} | |
console.log('Game data loaded:', gameData); | |
} | |
updateUpgradeButtons(); | |
renderHistory(); | |
} | |
// --- Register Mission Function --- | |
function registerMission() { | |
// AJUSTE: Verifica se o nome da missão está vazio | |
const taskName = taskNameInput.value.trim(); | |
if (taskName === '') { | |
alert('Atenção, Aventureiro! O nome da missão é obrigatório para registrar sua conquista.'); | |
taskNameInput.focus(); | |
return; // Impede que o restante da função seja executado | |
} | |
const selectedDuration = pomodoroDurationSelect.value; | |
const xpAwarded = xpValues[selectedDuration] || 0; // Se não encontrar, dá 0 XP | |
if (xpAwarded === 0) { | |
alert('Duração de missão inválida. Por favor, selecione uma opção válida.'); | |
return; | |
} | |
xpPoints += xpAwarded; | |
xpDisplay.textContent = xpPoints; | |
const missionRecord = { | |
name: taskName, | |
duration: `${selectedDuration} min`, // Armazena a duração em minutos | |
xp: xpAwarded, | |
timestamp: new Date(), // Data e hora da conclusão | |
}; | |
pomodoroHistory.unshift(missionRecord); // Adiciona ao início da lista | |
// Limita o histórico a 20 itens | |
if (pomodoroHistory.length > 20) { | |
pomodoroHistory.pop(); | |
} | |
renderHistory(); | |
saveGameData(); | |
updateUpgradeButtons(); | |
alert(`Missão "${taskName}" (${selectedDuration} min) concluída! Você ganhou ${xpAwarded} XP!`); | |
// Limpa o campo da missão após o registro | |
taskNameInput.value = ''; | |
pomodoroDurationSelect.value = '18'; // Volta para a opção padrão | |
} | |
// --- Skill Functions --- | |
function updateSkillDisplay(skillName) { | |
const skill = skillsData[skillName]; | |
const levelSpan = document.getElementById(`${skillName}Level`); | |
const progressBarFill = document.getElementById(`${skillName}Progress`); | |
const progressBarText = document.getElementById(`${skillName}ProgressText`); | |
levelSpan.textContent = `Nível ${skill.level}`; | |
const percentage = (skill.progress / skill.maxProgress) * 100; | |
progressBarFill.style.width = `${percentage}%`; | |
progressBarText.textContent = `${skill.progress}/${skill.maxProgress}`; | |
} | |
function updateUpgradeButtons() { | |
skillButtons.forEach(button => { | |
button.disabled = xpPoints < 1; | |
}); | |
} | |
function upgradeSkill(event) { | |
if (xpPoints >= 1) { | |
const skillName = event.target.dataset.skill; | |
const skill = skillsData[skillName]; | |
skill.progress += 25; // Cada aprimoramento custa 1 XP e dá 25 de progresso | |
if (skill.progress >= skill.maxProgress) { | |
skill.level++; | |
skill.progress = 0; | |
alert(`Parabéns! Sua skill de ${skillName.charAt(0).toUpperCase() + skillName.slice(1)} alcançou o Nível ${skill.level}!`); | |
} | |
xpPoints--; // Gasta 1 XP | |
xpDisplay.textContent = xpPoints; | |
updateSkillDisplay(skillName); | |
saveGameData(); | |
updateUpgradeButtons(); | |
} else { | |
alert('Você não tem XP suficiente para aprimorar!'); | |
} | |
} | |
// --- History Functions --- | |
function renderHistory() { | |
pomodoroHistoryList.innerHTML = ''; // Limpa a lista atual | |
if (pomodoroHistory.length === 0) { | |
const li = document.createElement('li'); | |
li.style.textAlign = 'center'; | |
li.style.color = '#777'; | |
li.textContent = 'Nenhuma missão registrada ainda.'; | |
pomodoroHistoryList.appendChild(li); | |
return; | |
} | |
pomodoroHistory.forEach(item => { | |
const li = document.createElement('li'); | |
li.innerHTML = ` | |
<span class="task-name">${item.name}</span> | |
<div class="task-details"> | |
<span>Duração: ${item.duration} (Ganhou ${item.xp} XP)</span> | |
<span>Registrado em: ${formatDateTime(item.timestamp)}</span> | |
</div> | |
`; | |
pomodoroHistoryList.appendChild(li); | |
}); | |
} | |
// --- Event Listeners --- | |
registerMissionButton.addEventListener('click', registerMission); | |
skillButtons.forEach(button => { | |
button.addEventListener('click', upgradeSkill); | |
}); | |
// --- Initialization --- | |
document.addEventListener('DOMContentLoaded', () => { | |
loadGameData(); | |
for (const skillName in skillsData) { | |
updateSkillDisplay(skillName); | |
} | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment