AI Verdict (Simulated):
${stock.aiVerdict}
`;
analysisCardsContainer.appendChild(card);
});
};
const handleAnalyzeButtonClick = () => {
const tickersString = stockTickersInput.value.trim();
if (!tickersString) {
showMessage("Please enter at least one stock ticker.", "error");
return;
}
const tickers = tickersString.split(',').map(t => t.trim().toUpperCase()).filter(t => t !== '');
if (tickers.length === 0) {
showMessage("No valid stock tickers entered.", "error");
return;
}
analyzeButtonText.classList.add('hidden');
analyzeButtonLoader.classList.remove('hidden');
analyzeStocksButton.disabled = true;
resultsDisplaySection.style.display = 'block';
loadingIndicatorResults.style.display = 'block';
analysisCardsContainer.innerHTML = ''; // Clear previous results
pdfDownloadButtonContainer.style.display = 'none';
resultsHeader.textContent = `Analysis Results for: ${tickers.join(', ')}`;
// Simulate API call & AI Analysis
setTimeout(() => {
const results = tickers.map(ticker => generateMockStockAnalysis(ticker));
renderAnalysisCards(results);
analyzeButtonText.classList.remove('hidden');
analyzeButtonLoader.classList.add('hidden');
analyzeStocksButton.disabled = false;
loadingIndicatorResults.style.display = 'none';
pdfDownloadButtonContainer.style.display = 'block';
showMessage(`Analysis complete for ${tickers.join(', ')}.`, "success");
}, 1800); // Simulate 1.8 seconds processing
};
// --- PDF Download ---
const downloadPDF = () => {
if (analyzedStockData.length === 0) {
showMessage("No data to download.", "error"); return;
}
if (typeof window.jspdf === 'undefined' || typeof window.jspdf.jsPDF === 'undefined') {
showMessage('PDF generation library (jsPDF) is not loaded.', 'error'); return;
}
const { jsPDF: JSPDF } = window.jspdf;
const doc = new JSPDF();
const today = new Date().toLocaleDateString('en-US');
doc.setFontSize(16);
doc.text("AI-Based Microcap & Penny Stock Analysis", 14, 22);
doc.setFontSize(10);
doc.text(`Report Generated: ${today} for Tickers: ${analyzedStockData.map(s=>s.ticker).join(', ')}`, 14, 30);
doc.setFontSize(8);
doc.text("Note: Simulated data for demonstration purposes only. Not financial advice.", 14, 35);
let yPos = 45;
analyzedStockData.forEach((stock, index) => {
if (index > 0 && yPos > 250) { // Check for page break before starting new stock
doc.addPage();
yPos = 20;
}
doc.setFillColor(243, 244, 246); // gray-100 for header bg
doc.rect(14, yPos - 5, 182, 8, 'F');
doc.setFontSize(12);
doc.setTextColor(20,20,20);
doc.text(`${stock.name} (${stock.ticker}) - Price: ${formatPrice(stock.currentPrice)}`, 16, yPos);
yPos += 8;
doc.setFontSize(10);
doc.setTextColor(0);
const dataPoints = [
`AI Risk Score: ${stock.riskScore}/100`,
`AI Potential Score: ${stock.potentialScore}/100`,
`Avg. Volume (Sim.): ${formatVolume(stock.volume)}`,
`Volatility (Sim.): ${stock.volatilityIndex}`,
`News Sentiment (Sim.): ${stock.newsSentiment}`,
`Recent Catalyst (Sim.): ${stock.recentCatalyst}`
];
dataPoints.forEach(point => {
if (yPos > 275) { doc.addPage(); yPos = 20; }
doc.text(point, 16, yPos); yPos += 6;
});
yPos += 2;
doc.setFontSize(10);
doc.setFont(undefined, 'bold');
doc.text("AI Verdict (Simulated):", 16, yPos); yPos += 5;
doc.setFont(undefined, 'normal');
const verdictLines = doc.splitTextToSize(stock.aiVerdict, 178);
doc.text(verdictLines, 16, yPos);
yPos += (verdictLines.length * 5) + 8; // Add some space after verdict
});
doc.save(`Microcap_Analysis_${today.replace(/\//g, '-')}.pdf`);
showMessage("PDF report downloaded.", "success");
};
// --- Event Listeners ---
if (analyzeStocksButton) analyzeStocksButton.addEventListener('click', handleAnalyzeButtonClick);
if (downloadPdfButton) downloadPdfButton.addEventListener('click', downloadPDF);
// --- Initialization ---
const initializeApp = () => {
if (currentYearSpan) currentYearSpan.textContent = new Date().getFullYear();
// Optionally trigger analysis for default tickers on load
// handleAnalyzeButtonClick();
showMessage("Analyzer ready. Enter stock tickers to begin.", "success", 2000);
};
initializeApp();
});