Attacker rolled: ${attRolls.join(', ')}
Defender rolled: ${defRolls.join(', ')}
Casualties: Attacker -${attLosses}, Defender -${defLosses}
`;
}
/**
* Adds a battle result to the log model and re-renders the table.
*/
function rbgsLogBattle(initial, result, newAtt, newDef) {
rollCounter++;
const logEntry = {
roll: rollCounter,
attArmies: initial.attArmies,
defArmies: initial.defArmies,
attDice: initial.attDiceCount,
defDice: initial.defDiceCount,
attRolls: result.attRolls.join(', '),
defRolls: result.defRolls.join(', '),
attLoss: result.attLosses,
defLoss: result.defLosses,
newAtt: newAtt,
newDef: newDef
};
battleLog.push(logEntry);
rbgsRenderLogTable();
}
/**
* Renders the `battleLog` model into the log table.
*/
function rbgsRenderLogTable() {
logTbody.innerHTML = '';
// Show latest first
[...battleLog].reverse().forEach(log => {
const row = logTbody.insertRow();
row.innerHTML = `
${log.roll} |
${log.attArmies} |
${log.defArmies} |
${log.attDice} |
${log.defDice} |
${log.attRolls} |
${log.defRolls} |
${log.attLoss} |
${log.defLoss} |
${log.newAtt} |
${log.newDef} |
`;
});
}
/**
* Clears the log model and table.
*/
function rbgsClearLog() {
if (confirm("Are you sure you want to clear the entire battle log?")) {
battleLog = [];
rollCounter = 0;
rbgsRenderLogTable();
}
}
// --- PDF Download Function ---
async function rbgsDownloadPDF() {
if (!logTable || !window.jspdf || !window.html2canvas) {
console.error("PDF generation libraries or log table not found.");
alert("Error: PDF generation failed.");
return;
}
if (battleLog.length === 0) {
alert("Log is empty. Nothing to download.");
return;
}
const { jsPDF } = window.jspdf;
try {
// Use html2canvas to capture the styled table
const canvas = await html2canvas(logTable, {
scale: 2, // Higher quality
useCORS: true,
logging: false
});
const imgData = canvas.toDataURL('image/png');
// 3. Create PDF
const imgWidth = canvas.width;
const imgHeight = canvas.height;
// Use landscape if table is wide
const orientation = imgWidth > imgHeight ? 'l' : 'p';
const doc = new jsPDF(orientation, 'mm', 'a4');
const pdfWidth = doc.internal.pageSize.getWidth();
const pdfHeight = doc.internal.pageSize.getHeight();
const margin = 10;
const effectiveWidth = pdfWidth - (margin * 2);
const effectiveHeight = (imgHeight * effectiveWidth) / imgWidth;
let heightLeft = effectiveHeight;
let position = margin;
doc.setFontSize(18);
doc.text("Risk Battle Simulator Log", margin, position);
position += 10;
heightLeft -= 10;
// Add first page
doc.addImage(imgData, 'PNG', margin, position, effectiveWidth, effectiveHeight);
heightLeft -= (pdfHeight - margin - position);
// Add new pages if content overflows
while (heightLeft > 0) {
position = heightLeft - effectiveHeight - margin;
doc.addPage();
doc.addImage(imgData, 'PNG', margin, position, effectiveWidth, effectiveHeight);
heightLeft -= (pdfHeight - margin * 2);
}
doc.save('Risk_Battle_Log.pdf');
} catch (error) {
console.error("Error generating PDF: ", error);
alert("An error occurred while generating the PDF.");
}
}
// --- Event Listeners ---
// Null checks for robust event binding
if (nextBtn) nextBtn.addEventListener('click', rbgsNextTab);
if (prevBtn) prevBtn.addEventListener('click', rbgsPrevTab);
if (attArmiesInput) attArmiesInput.addEventListener('input', rbgsUpdateDiceOptions);
if (defArmiesInput) defArmiesInput.addEventListener('input', rbgsUpdateDiceOptions);
if (rollBtn) rollBtn.addEventListener('click', rbgsHandleRollOnce);
if (blitzBtn) blitzBtn.addEventListener('click', rbgsHandleBlitz);
if (clearLogBtn) clearLogBtn.addEventListener('click', rbgsClearLog);
if (pdfDownloadBtn) pdfDownloadBtn.addEventListener('click', rbgsDownloadPDF);
// --- Initialization ---
function rbgsInit() {
rbgsUpdateDiceOptions();
rbgsUpdateNavButtons();
}
rbgsInit();
}); // End of DOMContentLoaded