Experiment Replication Checklist

Experiment Replication Checklist

1. Experiment Metadata
2. Materials & Setup
3. Step-by-Step Methodology

Manage Replication Verification Points

These are the specific requirements a replicator must meet to ensure validity.

Add New Verification Point

Defined Verification Points

Category Type Requirement Actions

Experiment Replication Checklist Draft

Click "Generate Checklist Document" to preview the final document.

${data.exp_materials || 'N/A'}

Detailed Methodology:

${data.exp_methodology || 'N/A'}

3. Replication Verification Checklist

Items to verify before attempting replication:

    `; // --- 2. Checklist --- const groupedChecks = verificationChecks.reduce((acc, check) => { acc[check.category] = acc[check.category] || []; acc[check.category].push(check); return acc; }, {}); Object.entries(groupedChecks).forEach(([category, checks]) => { html += `

    ${category} (${checks.filter(c => c.type === 'Required').length} Required)

    `; checks.forEach(check => { const color = check.type === 'Required' ? 'var(--danger-color)' : 'var(--success-color)'; html += `
  • [ ] ${check.type.toUpperCase()}: ${check.point}
  • `; }); }); html += `
`; reviewContent.innerHTML = html; pdfDownloadBtn.disabled = false; switchTab(2); // Switch to review tab }; /** * PDF Generation Function */ const downloadPDF = () => { const data = getMetaFormData(); const jsPDF = window.jspdf.jsPDF; const doc = new jsPDF('p', 'pt', 'a4'); let currentY = 40; const margin = 40; const pageWidth = doc.internal.pageSize.width; const maxWidth = pageWidth - (margin * 2); const checkPageBreak = (spaceNeeded) => { if (currentY + spaceNeeded > doc.internal.pageSize.height - margin) { doc.addPage(); currentY = margin; } }; const addSectionHeader = (title, color = [0, 0, 0]) => { checkPageBreak(25); doc.setFontSize(16); doc.setFont('Helvetica', 'bold'); doc.setTextColor(color[0], color[1], color[2]); doc.text(title, margin, currentY); currentY += 10; doc.setLineWidth(0.5); doc.setDrawColor(200); doc.line(margin, currentY, pageWidth - margin, currentY); currentY += 12; doc.setTextColor(0); }; const addText = (text, size = 10, style = 'normal', indent = 0) => { doc.setFontSize(size); doc.setFont('Helvetica', style); const lines = doc.splitTextToSize(text, maxWidth - indent); checkPageBreak(lines.length * 9); doc.text(lines, margin + indent, currentY); currentY += (lines.length * 9); }; const addKeyValue = (key, value, isBold = false) => { doc.setFontSize(10); doc.setFont('Helvetica', isBold ? 'bold' : 'normal'); const keyText = `${key}: `; const keyWidth = doc.getStringUnitWidth(keyText) * 10; const valueLines = doc.splitTextToSize(value, maxWidth - keyWidth); doc.text(keyText, margin, currentY); doc.setFont('Helvetica', 'normal'); doc.text(valueLines[0], margin + keyWidth, currentY); currentY += 10; for(let i = 1; i < valueLines.length; i++) { doc.text(valueLines[i], margin + keyWidth, currentY); currentY += 10; } }; // --- PDF Content --- // Title Block doc.setFontSize(20); doc.setFont('Helvetica', 'bold'); doc.setTextColor(0, 128, 128); doc.text(`EXPERIMENT REPLICATION CHECKLIST`, pageWidth / 2, currentY, { align: 'center' }); currentY += 15; // 1. Metadata addSectionHeader("1. Experiment Identification", [0, 128, 128]); addKeyValue("Title", data.exp_title, true); addKeyValue("Researcher", data.lead_researcher, true); addKeyValue("Date Completed", data.exp_date, true); addKeyValue("Domain", data.exp_domain, true); currentY += 5; addText("Summary / Goal:", 10, 'bold'); addText(data.exp_summary, 10, 'normal', 10); currentY += 10; // 2. Materials & Methodology addSectionHeader("2. Materials & Methodology", [0, 128, 128]); addText("Key Materials:", 10, 'bold'); addText(data.exp_materials, 10, 'normal', 10); currentY += 5; addText("Detailed Procedure:", 10, 'bold'); addText(data.exp_methodology, 10, 'normal', 10); currentY += 10; // 3. Verification Checklist addSectionHeader("3. Replication Verification Checklist", [0, 128, 128]); const groupedChecks = verificationChecks.reduce((acc, check) => { acc[check.category] = acc[check.category] || []; acc[check.category].push(check); return acc; }, {}); const allChecks = Object.entries(groupedChecks).flatMap(([category, checks]) => { const header = { content: category, styles: { fontStyle: 'bold', fillColor: [240, 240, 240], textColor: [0] } }; const checkRows = checks.map(check => { const color = check.type === 'Required' ? [244, 67, 54] : [76, 175, 80]; return [`[ ]`, check.type, check.point, color]; }); return [header, ...checkRows]; }); const finalChecks = allChecks.filter(item => typeof item !== 'string'); const checkTableHead = [["", "Type", "Verification Requirement"]]; const checkTableBody = finalChecks.map(item => { if (item.content) { return [{ content: item.content, colSpan: 3, styles: item.styles }]; } else { return [ item[0], // [ ] { content: item[1], styles: { textColor: item[3] } }, // Type item[2] // Requirement ]; } }); doc.autoTable({ startY: currentY, head: checkTableHead, body: checkTableBody, theme: 'grid', headStyles: { fillColor: [74, 78, 105], textColor: [255] }, // Secondary color styles: { fontSize: 9, cellPadding: 5, font: 'Helvetica' }, columnStyles: { 0: { cellWidth: 20, font: 'Courier' }, 1: { cellWidth: 70, fontStyle: 'bold' } } }); currentY = doc.autoTable.previous.finalY + 10; doc.save(`${data.exp_title.replace(/\s/g, '_')}_Replication_Checklist.pdf`); }; // --- Tab Navigation --- const switchTab = (tabIndex) => { tabs.forEach((tab, index) => { tab.classList.toggle('active', index === tabIndex); contents[index].classList.toggle('active', index === tabIndex); }); currentTab = tabIndex; updateNavButtons(); if (tabIndex === 2) { renderReviewSheet(); } } const updateNavButtons = () => { prevBtn.disabled = currentTab === 0; nextBtn.disabled = currentTab === tabs.length - 1; } tabs.forEach((tab, index) => { tab.addEventListener('click', () => { const tabNode = tab.closest('.checklist-tab-button'); const newIndex = Array.from(tabNode.parentNode.children).indexOf(tabNode); switchTab(newIndex); }); }); nextBtn.addEventListener('click', () => { if (currentTab < tabs.length - 1) switchTab(currentTab + 1); }); prevBtn.addEventListener('click', () => { if (currentTab > 0) switchTab(currentTab - 1); }); // --- Event Listeners and Initial Load --- generateReviewBtn.addEventListener('click', renderReviewSheet); pdfDownloadBtn.addEventListener('click', downloadPDF); // Initial Setup setInitialDate(); renderVerificationChecks(); updateNavButtons(); });
Scroll to Top