Virtual Lab Notes Generator

Virtual Lab Notes Generator

SimLab Recorder

Virtual Lab Notes Generator
Experiment Identification
Procedure, Observation, and Data Log

Record every action, its visual result, and any raw data generated.

#
Action / Step
Observation
Raw Data / Reading
Remove

Objective: ${data.objective}

Hypothesis: ${data.hypothesis}

`; // 3. Log Table (Simplified for HTML preview) if (data.log.length > 0) { html += `

II. Procedure Log & Observations

`; let tableHtml = ``; data.log.forEach(row => { tableHtml += ``; }); tableHtml += `
Step # Action Observation Raw Data
${row.step} ${row.action} ${row.obs} ${row.data}
`; html += tableHtml; } // 4. Conclusion Section html += `

III. Analysis & Conclusion (To be filled)

`; html += `
`; container.innerHTML = html; } function vlngSwitchTab(tabId) { document.querySelectorAll('.vlng-tab-btn').forEach(b => b.classList.remove('active')); document.querySelectorAll('.vlng-content').forEach(c => c.classList.remove('active')); const idx = tabId === 'setup' ? 0 : (tabId === 'log' ? 1 : 2); document.querySelectorAll('.vlng-tab-btn')[idx].classList.add('active'); document.getElementById('vlng-' + tabId).classList.add('active'); if (tabId === 'report') { vlngRenderReport(); } } function vlngLoadExample() { if(!confirm("Overwrite current data and load example Titration experiment?")) return; document.getElementById('inp-title').value = "Titration of an Unknown Acid"; document.getElementById('inp-simulator').value = "ChemLab Online v2.1"; document.getElementById('inp-objective').value = "Determine the concentration of an unknown monoprotic acid solution using standard NaOH."; document.getElementById('inp-hypothesis').value = "The unknown acid concentration is predicted to be approximately 0.1 M, based on source material context."; // Clear and refill log entries document.getElementById('vlng-log-rows-container').innerHTML = ''; vlngAddLogRow(1, "Prepare 50 mL of 0.1 M NaOH solution and fill the virtual burette.", "Initial burette volume set to 0.00 mL.", "Volume NaOH: 50 mL"); vlngAddLogRow(2, "Add 3 drops of phenolphthalein indicator to 10 mL acid solution.", "Solution color is clear and colorless.", "Initial pH: 2.3"); vlngAddLogRow(3, "Titrate with NaOH until endpoint (slight pink color).", "Endpoint reached after sustained pink color for 30s.", "Final Burette Reading: 10.55 mL"); vlngAddLogRow(4, "Record NaOH volume used.", "10.55 mL", "Volume used: 0.01055 L"); vlngRenderReport(); vlngSwitchTab('report'); } /* --- PDF Generation --- */ async function vlngGeneratePDF() { vlngRenderReport(); // Ensure report is updated const data = { title: document.getElementById('inp-title').value || "Experiment Title", simulator: document.getElementById('inp-simulator').value || "Simulator Used", objective: document.getElementById('inp-objective').value || "Objective pending.", hypothesis: document.getElementById('inp-hypothesis').value || "Hypothesis pending.", log: vlngGetLogData() }; if (data.log.length === 0) { alert("Please add procedure steps before generating the PDF."); return; } const { jsPDF } = window.jspdf; const doc = new jsPDF('p', 'mm', 'a4'); // Styling const blue = [70, 130, 180]; // Steel Blue let y = 20; // 1. Header doc.setFillColor(...blue); doc.rect(0, 0, 210, 20, 'F'); doc.setTextColor(255, 255, 255); doc.setFontSize(16); doc.text("Virtual Lab Notes", 14, 13); doc.setFontSize(10); doc.text(`Experiment: ${data.title}`, 14, 17); y = 30; // 2. Metadata doc.setTextColor(0, 0, 0); doc.setFontSize(10); doc.setFont("helvetica", "bold"); doc.text("Objective:", 14, y); doc.text("Hypothesis:", 105, y); y += 5; doc.setFont("times", "normal"); doc.setTextColor(50, 50, 50); const splitObj = doc.splitTextToSize(data.objective, 85); doc.text(splitObj, 14, y); const splitHyp = doc.splitTextToSize(data.hypothesis, 85); doc.text(splitHyp, 105, y); y += Math.max(splitObj.length, splitHyp.length) * 5 + 10; // 3. Log Table doc.setFontSize(12); doc.setFont("helvetica", "bold"); doc.setTextColor(70, 130, 180); doc.text("Procedure Log & Data", 14, y); y += 5; const tableBody = data.log.map(item => [ item.step, item.action, item.obs, item.data ]); doc.autoTable({ startY: y, head: [['#', 'Action / Step', 'Observation', 'Raw Data']], body: tableBody, theme: 'grid', headStyles: { fillColor: blue, fontSize: 9 }, styles: { fontSize: 8, overflow: 'linebreak' }, columnStyles: { 0: { cellWidth: 8, halign: 'center', fontStyle: 'bold' }, 1: { cellWidth: 50 }, 2: { cellWidth: 60 }, 3: { cellWidth: 55, font: 'courier' } } }); // 4. Conclusion y = doc.lastAutoTable.finalY + 10; if (y > 270) { doc.addPage(); y = 20; } doc.setFontSize(12); doc.setFont("helvetica", "bold"); doc.text("Analysis & Conclusion", 14, y); y += 5; doc.setFontSize(10); doc.setFont("times", "italic"); doc.text("...", 14, y + 5); doc.save(`LabNotes_${data.title.replace(/\s/g, '_')}.pdf`); }
Scroll to Top