// Topics data const topics = [ { id: 1, title: "Introduction to Prompt Engineering", subtitle: "What & Why" }, { id: 2, title: "Prompt Structure", subtitle: "Building Blocks" }, { id: 3, title: "Clarity & Specificity", subtitle: "Writing Precise Prompts" }, { id: 4, title: "Context & Background", subtitle: "Providing Information" }, { id: 5, title: "Output Format", subtitle: "Specifying Structure" }, { id: 6, title: "Iterative Refinement", subtitle: "Testing & Improving" }, { id: 7, title: "Advanced Techniques", subtitle: "Expert Methods" }, { id: 8, title: "Real-World Applications", subtitle: "Putting It Together" } ]; // State management let currentTopic = 1; let completedTopics = []; // Initialize app function init() { renderTopicList(); initializeCanvases(); updateProgress(); showContextExample('minimal'); showFormatExample('list'); showIteration(1); updateSpecificity(); setChallenge('email'); } // Render topic list in sidebar function renderTopicList() { const topicList = document.getElementById('topicList'); topicList.innerHTML = topics.map(topic => `
${topic.subtitle}
${iteration.notes}
`; } // Challenge scenarios const challenges = { email: { scenario: "Your manager asked you to write a follow-up email to a client who attended yesterday's product demo. The client seemed interested but had concerns about pricing and implementation timeline." }, code: { scenario: "You need to create a JavaScript function that validates email addresses and returns detailed error messages for invalid formats. It should handle edge cases like missing @ symbols, invalid domains, and special characters." }, creative: { scenario: "Create a compelling Instagram caption for a new eco-friendly water bottle launch. Your brand targets young professionals who care about sustainability. The post should encourage engagement and include a call-to-action." }, analysis: { scenario: "You have sales data from Q1-Q4 showing declining revenue in Q3. Analyze what might have caused this dip and provide actionable recommendations. Consider seasonality, marketing spend, and competition." } }; let currentChallenge = 'email'; function setChallenge(type) { currentChallenge = type; // Update button states const buttons = document.querySelectorAll('.challenge-box .scenario-btn'); buttons.forEach(btn => btn.classList.remove('active')); event.target.classList.add('active'); document.getElementById('challengeScenario').textContent = challenges[type].scenario; document.getElementById('challengeInput').value = ''; document.getElementById('challengeFeedback').classList.remove('show'); } function evaluateChallenge() { const input = document.getElementById('challengeInput').value; const feedback = document.getElementById('challengeFeedback'); if (!input.trim()) { feedback.innerHTML = '⚠️ Please write a prompt first!
'; feedback.classList.add('show'); return; } // Simple evaluation based on key elements const hasRole = /you are|act as|as a/i.test(input); const hasContext = input.length > 100; const hasFormat = /format|structure|provide|return|list|table/i.test(input); const hasConstraints = /words|length|tone|style|keep/i.test(input); let score = 0; let feedbackItems = []; if (hasRole) { score += 25; feedbackItems.push('✓ Good: Includes role/persona'); } else { feedbackItems.push('⚠️ Consider: Adding a role or persona'); } if (hasContext) { score += 25; feedbackItems.push('✓ Good: Provides context'); } else { feedbackItems.push('⚠️ Consider: Adding more context and background'); } if (hasFormat) { score += 25; feedbackItems.push('✓ Good: Specifies output format'); } else { feedbackItems.push('⚠️ Consider: Specifying the desired output format'); } if (hasConstraints) { score += 25; feedbackItems.push('✓ Good: Includes constraints'); } else { feedbackItems.push('⚠️ Consider: Adding constraints like length, tone, or style'); } let grade = ''; let color = ''; if (score >= 75) { grade = 'Excellent'; color = '#00FF88'; } else if (score >= 50) { grade = 'Good'; color = '#FFB800'; } else { grade = 'Needs Improvement'; color = '#FF6B35'; } feedback.innerHTML = `${item}
`).join('')} ${score >= 75 ? '🎉 Great job! Your prompt includes all key components.
' : ''} `; feedback.classList.add('show'); } function resetChallenge() { document.getElementById('challengeInput').value = ''; document.getElementById('challengeFeedback').classList.remove('show'); } // Practice challenge function startPractice(topicId) { alert('Practice mode: Try building a prompt for a simple task like \"Write a product description for noise-canceling headphones\" and include all four components: Role, Context, Task, and Format!'); } // Template copy function copyTemplate(element) { const template = element.querySelector('pre').textContent; // Create temporary textarea const textarea = document.createElement('textarea'); textarea.value = template; document.body.appendChild(textarea); textarea.select(); try { document.execCommand('copy'); // Show feedback const originalHTML = element.innerHTML; element.style.borderColor = '#00FF88'; setTimeout(() => { element.style.borderColor = '#333'; }, 1000); } catch (err) { console.error('Copy failed:', err); } document.body.removeChild(textarea); } // Canvas visualizations function initializeCanvases() { // Structure Canvas - Component visualization const structureCanvas = document.getElementById('structureCanvas'); if (structureCanvas) { const ctx = structureCanvas.getContext('2d'); drawStructureVisualization(ctx, structureCanvas); } // Context Canvas - Information layers const contextCanvas = document.getElementById('contextCanvas'); if (contextCanvas) { const ctx = contextCanvas.getContext('2d'); drawContextVisualization(ctx, contextCanvas); } // Refinement Canvas - Improvement curve const refinementCanvas = document.getElementById('refinementCanvas'); if (refinementCanvas) { const ctx = refinementCanvas.getContext('2d'); drawRefinementVisualization(ctx, refinementCanvas); } // Techniques Canvas - Pattern comparison const techniquesCanvas = document.getElementById('techniquesCanvas'); if (techniquesCanvas) { const ctx = techniquesCanvas.getContext('2d'); drawTechniquesVisualization(ctx, techniquesCanvas); } } function drawStructureVisualization(ctx, canvas) { canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight; const components = [ { name: 'Role', color: '#0066FF', y: 80 }, { name: 'Context', color: '#00D9FF', y: 160 }, { name: 'Task', color: '#FFB800', y: 240 }, { name: 'Format', color: '#00FF88', y: 320 } ]; const centerX = canvas.width / 2; // Draw connecting lines ctx.strokeStyle = '#333'; ctx.lineWidth = 2; ctx.beginPath(); ctx.moveTo(centerX, 60); ctx.lineTo(centerX, 340); ctx.stroke(); // Draw components components.forEach(comp => { // Circle ctx.fillStyle = comp.color; ctx.beginPath(); ctx.arc(centerX, comp.y, 30, 0, Math.PI * 2); ctx.fill(); // Text ctx.fillStyle = '#FFFFFF'; ctx.font = 'bold 14px sans-serif'; ctx.textAlign = 'center'; ctx.fillText(comp.name, centerX, comp.y + 5); }); // Title ctx.fillStyle = '#00D9FF'; ctx.font = 'bold 18px sans-serif'; ctx.textAlign = 'center'; ctx.fillText('Prompt Structure Components', centerX, 30); } function drawContextVisualization(ctx, canvas) { canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight; const layers = [ { name: 'Task Only', width: 100, color: '#FF6B35' }, { name: '+ Basic Context', width: 200, color: '#FFB800' }, { name: '+ Full Context', width: 350, color: '#00FF88' } ]; const startY = 100; const layerHeight = 60; const spacing = 30; layers.forEach((layer, index) => { const y = startY + (index * (layerHeight + spacing)); // Draw rectangle ctx.fillStyle = layer.color + '44'; ctx.fillRect(50, y, layer.width, layerHeight); // Draw border ctx.strokeStyle = layer.color; ctx.lineWidth = 2; ctx.strokeRect(50, y, layer.width, layerHeight); // Draw text ctx.fillStyle = '#FFFFFF'; ctx.font = '14px sans-serif'; ctx.textAlign = 'left'; ctx.fillText(layer.name, 60, y + 35); }); // Title ctx.fillStyle = '#00D9FF'; ctx.font = 'bold 18px sans-serif'; ctx.textAlign = 'left'; ctx.fillText('Context Layers: From Minimal to Rich', 50, 50); } function drawRefinementVisualization(ctx, canvas) { canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight; const points = [ { x: 100, y: 300, label: 'Iteration 1' }, { x: 300, y: 200, label: 'Iteration 2' }, { x: 500, y: 120, label: 'Iteration 3' }, { x: 700, y: 80, label: 'Final' } ]; // Draw curve ctx.strokeStyle = '#0066FF'; ctx.lineWidth = 3; ctx.beginPath(); ctx.moveTo(points[0].x, points[0].y); for (let i = 1; i < points.length; i++) { const xMid = (points[i - 1].x + points[i].x) / 2; ctx.quadraticCurveTo(xMid, points[i - 1].y, points[i].x, points[i].y); } ctx.stroke(); // Draw points points.forEach((point, index) => { ctx.fillStyle = '#00D9FF'; ctx.beginPath(); ctx.arc(point.x, point.y, 8, 0, Math.PI * 2); ctx.fill(); // Labels ctx.fillStyle = '#FFFFFF'; ctx.font = '12px sans-serif'; ctx.textAlign = 'center'; ctx.fillText(point.label, point.x, point.y + 25); }); // Y-axis label ctx.save(); ctx.translate(30, 200); ctx.rotate(-Math.PI / 2); ctx.fillStyle = '#888'; ctx.font = '14px sans-serif'; ctx.textAlign = 'center'; ctx.fillText('Quality', 0, 0); ctx.restore(); // X-axis label ctx.fillStyle = '#888'; ctx.font = '14px sans-serif'; ctx.textAlign = 'center'; ctx.fillText('Iterations', canvas.width / 2, canvas.height - 20); // Title ctx.fillStyle = '#00D9FF'; ctx.font = 'bold 18px sans-serif'; ctx.textAlign = 'center'; ctx.fillText('Prompt Improvement Through Iteration', canvas.width / 2, 30); } function drawTechniquesVisualization(ctx, canvas) { canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight; const techniques = [ { name: 'Basic', score: 40, color: '#FF6B35', x: 150 }, { name: 'Chain-of-Thought', score: 75, color: '#FFB800', x: 350 }, { name: 'Few-Shot', score: 85, color: '#00D9FF', x: 550 }, { name: 'Combined', score: 95, color: '#00FF88', x: 750 } ]; const maxHeight = 250; const barWidth = 80; const baseY = 320; techniques.forEach(tech => { const barHeight = (tech.score / 100) * maxHeight; // Draw bar ctx.fillStyle = tech.color + '88'; ctx.fillRect(tech.x - barWidth / 2, baseY - barHeight, barWidth, barHeight); // Draw border ctx.strokeStyle = tech.color; ctx.lineWidth = 2; ctx.strokeRect(tech.x - barWidth / 2, baseY - barHeight, barWidth, barHeight); // Score text ctx.fillStyle = '#FFFFFF'; ctx.font = 'bold 16px sans-serif'; ctx.textAlign = 'center'; ctx.fillText(tech.score + '%', tech.x, baseY - barHeight - 10); // Technique name ctx.font = '12px sans-serif'; ctx.fillText(tech.name, tech.x, baseY + 25); }); // Title ctx.fillStyle = '#00D9FF'; ctx.font = 'bold 18px sans-serif'; ctx.textAlign = 'center'; ctx.fillText('Technique Effectiveness Comparison', canvas.width / 2, 30); // Y-axis ctx.strokeStyle = '#333'; ctx.lineWidth = 2; ctx.beginPath(); ctx.moveTo(80, 70); ctx.lineTo(80, baseY); ctx.stroke(); // Y-axis label ctx.fillStyle = '#888'; ctx.font = '12px sans-serif'; ctx.textAlign = 'right'; ctx.fillText('0%', 75, baseY + 5); ctx.fillText('50%', 75, baseY - 125); ctx.fillText('100%', 75, baseY - 250); } // Checklist interaction document.addEventListener('click', function(e) { if (e.target.tagName === 'LI' && e.target.parentElement.classList.contains('checklist')) { e.target.classList.toggle('checked'); } }); // Initialize on load window.addEventListener('load', init); // Handle window resize for canvases window.addEventListener('resize', function() { initializeCanvases(); });