document.addEventListener('DOMContentLoaded', function() {
// Initialize local storage for study tracking
if (!localStorage.getItem('studySessions')) {
localStorage.setItem('studySessions', '0');
}
if (!localStorage.getItem('studyStreak')) {
localStorage.setItem('studyStreak', '0');
}
if (!localStorage.getItem('lastStudyDate')) {
localStorage.setItem('lastStudyDate', new Date().toDateString());
}
// Check if user studied today to update streak
const lastStudyDate = localStorage.getItem('lastStudyDate');
const today = new Date().toDateString();
if (lastStudyDate !== today) {
// Reset streak if more than one day has passed
const lastDate = new Date(lastStudyDate);
const todayDate = new Date();
const diffTime = Math.abs(todayDate - lastDate);
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
if (diffDays > 1) {
localStorage.setItem('studyStreak', '0');
}
}
// Update UI with stored data
updateStudyStats();
});
function updateStudyStats() {
const sessions = localStorage.getItem('studySessions');
const streak = localStorage.getItem('studyStreak');
document.querySelectorAll('.session-count').forEach(el => {
el.textContent = sessions;
});
document.querySelectorAll('.streak-count').forEach(el => {
el.textContent = streak;
});
}
function startStudySession(subject) {
// Validate subject
if (!subject) {
showErrorToast("Please select a subject to study!");
return;
}
// In a real app, this would start tracking study time
console.log(`Starting study session for ${subject}`);
// Update session count
const sessions = parseInt(localStorage.getItem('studySessions')) + 1;
localStorage.setItem('studySessions', sessions.toString());
// Update streak if needed
const lastStudyDate = localStorage.getItem('lastStudyDate');
const today = new Date().toDateString();
if (lastStudyDate !== today) {
const streak = parseInt(localStorage.getItem('studyStreak')) + 1;
localStorage.setItem('studyStreak', streak.toString());
localStorage.setItem('lastStudyDate', today);
}
updateStudyStats();
showSuccessToast(`Started studying ${subject}! Good luck!`);
}
function showErrorToast(message) {
const toast = document.createElement('div');
toast.className = 'fixed bottom-4 left-1/2 transform -translate-x-1/2 bg-red-500 text-white px-6 py-3 rounded-lg shadow-xl flex items-center animate-fade-in z-50';
toast.innerHTML = `
${message}
`;
document.body.appendChild(toast);
feather.replace();
setTimeout(() => {
toast.classList.add('opacity-0', 'transition-opacity', 'duration-300');
setTimeout(() => toast.remove(), 300);
}, 3000);
}
function showSuccessToast(message) {
const toast = document.createElement('div');
toast.className = 'fixed bottom-4 left-1/2 transform -translate-x-1/2 bg-green-500 text-white px-6 py-3 rounded-lg shadow-xl flex items-center animate-fade-in z-50';
toast.innerHTML = `
${message}
`;
document.body.appendChild(toast);
feather.replace();
setTimeout(() => {
toast.classList.add('opacity-0', 'transition-opacity', 'duration-300');
setTimeout(() => toast.remove(), 300);
}, 3000);
}
// Photo upload functionality
function setupPhotoUpload() {
const uploadElements = document.querySelectorAll('.photo-upload');
uploadElements.forEach(upload => {
const input = upload.querySelector('input[type="file"]');
const preview = upload.querySelector('.photo-preview');
if (input && preview) {
input.addEventListener('change', (e) => {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = (event) => {
preview.src = event.target.result;
preview.style.display = 'block';
};
reader.readAsDataURL(file);
}
});
}
});
}
// Helper functions for study assistance
function provideHint(questionElement) {
// This would be connected to your question system
const hint = questionElement.dataset.hint || "Try breaking the problem down into smaller steps.";
// Show hint
showSuccessToast(`Hint: ${hint}`);
// Speak the hint using Web Speech API
speakText(hint);
// Provide similar example
const example = questionElement.dataset.example || "Here's a similar problem: " +
questionElement.textContent.replace(/\d+/g, function(match) {
return Math.floor(Math.random() * 10) + 1;
});
setTimeout(() => {
showSuccessToast(`Example: ${example}`);
speakText(example);
}, 2000);
}
// AI Quiz Generation Service using Open Trivia DB API
async function generateQuizQuestions(subject, difficulty = 'medium', topic = '') {
// Map our subject categories to Open Trivia categories
const categoryMap = {
'math': 19, // Mathematics
'science': 17, // Science & Nature
'history': 23, // History
'languages': 20, // Mythology (as a placeholder)
'computer_science': 18 // Computers
};
const categoryId = categoryMap[subject] || 9; // General Knowledge as fallback
try {
// Fetch questions from Open Trivia DB API
const response = await fetch(`https://opentdb.com/api.php?amount=5&category=${categoryId}&difficulty=${difficulty}&type=multiple&encode=url3986`);
const data = await response.json();
if (data.response_code !== 0 || !data.results) {
throw new Error('Failed to fetch questions from API');
}
// Process the API response into our question format
return data.results.map(q => {
// Decode URL-encoded strings and fix HTML entities
const decodedQuestion = decodeURIComponent(q.question)
.replace(/"/g, '"')
.replace(/&/g, '&')
.replace(/'/g, "'");
const decodedCorrect = decodeURIComponent(q.correct_answer)
.replace(/"/g, '"')
.replace(/&/g, '&')
.replace(/'/g, "'");
const decodedIncorrect = q.incorrect_answers.map(ans =>
decodeURIComponent(ans)
.replace(/"/g, '"')
.replace(/&/g, '&')
.replace(/'/g, "'")
);
// Combine and shuffle options
const allOptions = [...decodedIncorrect, decodedCorrect];
const shuffledOptions = shuffleArray(allOptions);
return {
question: decodedQuestion,
options: shuffledOptions,
correctIndex: shuffledOptions.indexOf(decodedCorrect),
hint: `Think about ${q.category.toLowerCase()} concepts`,
example: `This is a ${difficulty} level question about ${q.category.toLowerCase()}`
};
});
} catch (error) {
console.error('Error fetching quiz questions:', error);
showErrorToast('Failed to fetch questions. Using sample questions instead.');
return generateFallbackQuestions(subject, difficulty, topic);
}
}
function generateFallbackQuestions(subject, difficulty, topic) {
// Fallback questions if API fails
const fallbackQuestions = [
{
question: `What is the capital of France? (Fallback for ${subject})`,
options: ["London", "Paris", "Berlin", "Madrid"],
correctIndex: 1,
hint: "It's known as the City of Light",
example: "Other European capitals include Rome and Berlin"
},
{
question: `What is 5 × 7? (Fallback for ${subject})`,
options: ["25", "30", "35", "40"],
correctIndex: 2,
hint: "It's 5 less than 40",
example: "Similar to 6 × 6 = 36"
},
{
question: `What is the chemical symbol for oxygen? (Fallback for ${subject})`,
options: ["O", "Ox", "Og", "On"],
correctIndex: 0,
hint: "It's a single letter",
example: "H is for Hydrogen"
}
];
return fallbackQuestions;
}
// Helper function to shuffle array
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
return array;
}
function speakText(text) {
if ('speechSynthesis' in window) {
const utterance = new SpeechSynthesisUtterance(text);
utterance.voice = speechSynthesis.getVoices().find(voice =>
voice.name.includes('Female') || voice.lang.includes('en-US')
);
utterance.rate = 0.9;
utterance.pitch = 1.2;
speechSynthesis.speak(utterance);
}
}
function setupHelpButtons() {
// Add help button to question pages
if (document.querySelector('.question-container')) {
const helpBtn = document.createElement('button');
helpBtn.className = 'help-btn';
helpBtn.innerHTML = '';
helpBtn.onclick = () => {
const currentQuestion = document.querySelector('.question-container:not([style*="display: none"])');
if (currentQuestion) {
provideHint(currentQuestion);
}
};
document.body.appendChild(helpBtn);
feather.replace();
}
}
// Initialize all helper features
document.addEventListener('DOMContentLoaded', () => {
setupPhotoUpload();
setupHelpButtons();
// Load voices for speech synthesis
if ('speechSynthesis' in window) {
speechSynthesis.onvoiceschanged = () => {
// Voices are now loaded
};
}
});