// Global variables
let currentSlideIndex = 0;
let slideInterval;
let speechSynthesis = window.speechSynthesis;
let currentUtterance = null;
let slides = [];
const slideDuration = 8000; // 8 seconds per slide
// Generate presentation based on topic using OpenAI
async function generatePresentation(topic, slideCount) {
try {
// Show loading state
document.querySelector('main').innerHTML = `
Generating your presentation about ${topic}...
`;
// Prepare prompt for OpenAI
const prompt = `Create a ${slideCount}-slide presentation about "${topic}".
For each slide, provide:
1. A concise slide title (max 8 words)
2. Detailed content (3-5 bullet points or 1-2 paragraphs)
Format as JSON with array of {title, content}. Include introduction and conclusion slides.`;
// Call OpenAI API (you'll need to replace OPENAI_API_KEY with your actual key)
// Mock response for testing since we can't use actual API key
const mockResponse = {
"choices": [{
"message": {
"content": JSON.stringify([
{
"title": "Introduction to Evaporation",
"content": "Evaporation is the process where liquid turns into vapor. It occurs when molecules gain enough energy to escape the liquid's surface. This is a key part of the water cycle."
},
{
"title": "How Evaporation Works",
"content": "Molecules in a liquid move at different speeds. The fastest molecules can break free from the surface. Heat increases the rate of evaporation."
},
{
"title": "Factors Affecting Evaporation",
"content": "Temperature - Higher temps increase evaporation. Surface area - More area means faster evaporation. Humidity - Lower humidity speeds up evaporation. Air flow - Moving air carries away vapor."
},
{
"title": "Evaporation vs Boiling",
"content": "Evaporation happens at any temp below boiling point. It occurs only at the surface. Boiling happens throughout the liquid at a specific temperature."
},
{
"title": "Applications of Evaporation",
"content": "Used in cooling systems like sweating. Important in distillation processes. Used in salt production from seawater. Helps in drying clothes and foods."
}
])
}
}]
};
// Use mock response instead of actual API call
const data = mockResponse;
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${OPENAI_API_KEY}`
},
body: JSON.stringify({
model: "gpt-3.5-turbo",
messages: [
{
role: "user",
content: prompt
}
],
temperature: 0.7
})
});
const data = await response.json();
const content = data.choices[0].message.content;
let slideData;
try {
// Try to parse JSON if returned as JSON string
slideData = JSON.parse(content);
} catch {
// If parsing fails, assume it's text and create slides
const sections = content.split('\n\n').filter(s => s.trim().length > 0);
slideData = sections.map((section, i) => {
const lines = section.split('\n');
const title = lines[0].replace('Title:', '').replace('Slide Title:', '').trim();
const content = lines.slice(1).join('\n').trim();
return { title, content };
});
}
// Process into slides
slides = [];
for (let i = 0; i < slideData.length; i++) {
const slide = slideData[i];
slides.push({
image: `http://static.photos/1200x630/${i+1}`,
title: slide.title || (i === 0 ? `Introduction to ${topic}` : `${topic}: Key Point ${i}`),
text: slide.content || slide.text || `Content for slide ${i+1} about ${topic}`
});
}
// Start the slideshow
startSlideshowWithVoice();
// Start the slideshow without redirect
startSlideshowWithVoice();
} catch (error) {
console.error('Error generating presentation:', error);
// Fallback with better sample content
slides = [];
for (let i = 0; i < slideCount; i++) {
let title, text;
if (i === 0) {
title = `Introduction to ${topic}`;
text = `${topic} is an important process in nature. Let's explore its key aspects in this presentation.`;
} else if (i === slideCount - 1) {
title = `Conclusion on ${topic}`;
text = `We've covered the main points about ${topic}. Thank you for your attention!`;
} else {
title = `${topic}: Key Aspect ${i}`;
text = `This slide discusses important details about ${topic}. Specific information about aspect ${i} would be presented here. For example, we might explain how this relates to the overall topic.`;
});
}
// Ensure we have at least one slide
if (slides.length === 0) {
slides.push({
image: `http://static.photos/science/1200x630/1`,
title: `Presentation on ${topic}`,
text: `This presentation will explore various aspects of ${topic}. Let's begin our journey of discovery!`
});
});
// Start the slideshow with fallback content
startSlideshowWithVoice();
}
}
function startSlideshowWithVoice() {
// Clear any existing interval
if (slideInterval) {
clearInterval(slideInterval);
}
if (currentUtterance) {
speechSynthesis.cancel();
}
// Start with first slide
updateSlide(0);
// Set up automatic slideshow
slideInterval = setInterval(() => {
currentSlideIndex = (currentSlideIndex + 1) % slides.length;
updateSlide(currentSlideIndex);
}, slideDuration);
// Speak the first slide
speakCurrentSlide();
}
function updateSlide(index) {
const slide = slides[index];
const slideshow = document.querySelector('custom-slideshow');
if (slideshow) {
slideshow.setAttribute('image', slide.image);
slideshow.setAttribute('title', slide.title);
slideshow.setAttribute('text', slide.text);
slideshow.setAttribute('current-index', index + 1);
slideshow.setAttribute('total-slides', slides.length);
// Update progress bar
updateProgressBar();
}
// Speak the new slide content
speakCurrentSlide();
}
function speakCurrentSlide() {
if (currentUtterance) {
speechSynthesis.cancel();
}
const slide = slides[currentSlideIndex];
const text = `${slide.title}. ${slide.text}`; // Speak both title and content
currentUtterance = new SpeechSynthesisUtterance(text);
currentUtterance.rate = 1;
currentUtterance.pitch = 1;
currentUtterance.volume = 1;
speechSynthesis.speak(currentUtterance);
}
function updateProgressBar() {
const progressBar = document.querySelector('.progress-fill');
if (progressBar) {
progressBar.style.width = '0%';
// Reset animation
void progressBar.offsetWidth;
progressBar.style.width = '100%';
progressBar.style.transitionDuration = `${slideDuration/1000}s`;
}
}
// Expose controls to the window
window.toggleVoice = function() {
if (speechSynthesis.speaking) {
speechSynthesis.cancel();
} else {
speakCurrentSlide();
}
};
window.nextSlide = function() {
currentSlideIndex = (currentSlideIndex + 1) % slides.length;
updateSlide(currentSlideIndex);
// Reset interval
clearInterval(slideInterval);
slideInterval = setInterval(() => {
currentSlideIndex = (currentSlideIndex + 1) % slides.length;
updateSlide(currentSlideIndex);
}, slideDuration);
};
window.prevSlide = function() {
currentSlideIndex = (currentSlideIndex - 1 + slides.length) % slides.length;
updateSlide(currentSlideIndex);
// Reset interval
clearInterval(slideInterval);
slideInterval = setInterval(() => {
currentSlideIndex = (currentSlideIndex + 1) % slides.length;
updateSlide(currentSlideIndex);
}, slideDuration);
};
// Pause on hover
document.querySelector('custom-slideshow')?.addEventListener('mouseenter', () => {
clearInterval(slideInterval);
if (currentUtterance) {
speechSynthesis.pause();
}
});
document.querySelector('custom-slideshow')?.addEventListener('mouseleave', () => {
slideInterval = setInterval(() => {
currentSlideIndex = (currentSlideIndex + 1) % slides.length;
updateSlide(currentSlideIndex);
}, slideDuration);
if (currentUtterance) {
speechSynthesis.resume();
}
});