dose-planner / index.html
Godito's picture
develope App Name: HeadNeck Dose Planner Purpose: To help radiologists or oncologists plan safe, personalized radiation doses based on tumor type, size, location, patient age, and treatment guidelines. - Initial Deployment
c6f7357 verified
Raw
History Blame Contribute Delete
45 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HeadNeck Dose Planner | Radiation Treatment Planning</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.gradient-bg {
background: linear-gradient(135deg, #1e3a8a 0%, #3b82f6 100%);
}
.dose-meter {
height: 8px;
border-radius: 4px;
background: linear-gradient(90deg, #10b981 0%, #f59e0b 50%, #ef4444 100%);
}
.anatomy-illustration {
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"><path d="M100,20 C120,20 130,40 140,60 C150,80 160,100 150,120 C140,140 120,160 100,170 C80,160 60,140 50,120 C40,100 50,80 60,60 C70,40 80,20 100,20 Z" fill="%23e5e7eb" stroke="%236b7280" stroke-width="2"/><circle cx="90" cy="50" r="5" fill="%23ef4444"/><circle cx="110" cy="50" r="5" fill="%23ef4444"/><path d="M90,70 C95,80 105,80 110,70" stroke="%236b7280" stroke-width="2" fill="none"/></svg>');
background-repeat: no-repeat;
background-position: center;
background-size: contain;
}
.tumor-marker {
position: absolute;
width: 16px;
height: 16px;
border-radius: 50%;
background-color: #ef4444;
transform: translate(-50%, -50%);
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { transform: translate(-50%, -50%) scale(1); opacity: 1; }
50% { transform: translate(-50%, -50%) scale(1.2); opacity: 0.7; }
100% { transform: translate(-50%, -50%) scale(1); opacity: 1; }
}
.print-only {
display: none;
}
@media print {
.no-print {
display: none;
}
.print-only {
display: block;
}
body {
padding: 20px;
background: white;
color: black;
}
}
</style>
</head>
<body class="bg-gray-50 min-h-screen font-sans">
<!-- Header -->
<header class="gradient-bg text-white shadow-lg">
<div class="container mx-auto px-4 py-6">
<div class="flex flex-col md:flex-row justify-between items-center">
<div class="flex items-center mb-4 md:mb-0">
<i class="fas fa-radiation-alt text-3xl mr-3"></i>
<div>
<h1 class="text-2xl font-bold">HeadNeck Dose Planner</h1>
<p class="text-sm opacity-80">Personalized Radiation Treatment Planning</p>
</div>
</div>
<nav class="flex space-x-4">
<a href="#" class="px-3 py-2 rounded hover:bg-blue-700 transition" id="homeLink">Home</a>
<a href="#" class="px-3 py-2 rounded hover:bg-blue-700 transition" id="newPlanLink">New Plan</a>
<a href="#" class="px-3 py-2 rounded hover:bg-blue-700 transition" id="savedPlansLink">Saved Plans</a>
<a href="#" class="px-3 py-2 rounded hover:bg-blue-700 transition" id="guidelinesLink">Guidelines</a>
</nav>
</div>
</div>
</header>
<!-- Main Content -->
<main class="container mx-auto px-4 py-8">
<!-- Patient Information Section -->
<section class="bg-white rounded-lg shadow-md p-6 mb-8">
<h2 class="text-xl font-semibold text-gray-800 mb-4 flex items-center">
<i class="fas fa-user-circle mr-2 text-blue-600"></i> Patient Information
</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Patient ID</label>
<input type="text" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Enter patient ID">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Name</label>
<input type="text" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Patient name">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Age</label>
<input type="number" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Age">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Gender</label>
<select class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">Select</option>
<option value="male">Male</option>
<option value="female">Female</option>
<option value="other">Other</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Weight (kg)</label>
<input type="number" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Weight">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Height (cm)</label>
<input type="number" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Height">
</div>
</div>
</section>
<!-- Tumor Characteristics Section -->
<section class="bg-white rounded-lg shadow-md p-6 mb-8">
<h2 class="text-xl font-semibold text-gray-800 mb-4 flex items-center">
<i class="fas fa-tumor mr-2 text-red-600"></i> Tumor Characteristics
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Tumor Type</label>
<select class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" id="tumorType">
<option value="">Select tumor type</option>
<option value="nasopharynx">Nasopharyngeal carcinoma</option>
<option value="oropharynx">Oropharyngeal carcinoma</option>
<option value="hypopharynx">Hypopharyngeal carcinoma</option>
<option value="larynx">Laryngeal carcinoma</option>
<option value="oral">Oral cavity cancer</option>
<option value="salivary">Salivary gland cancer</option>
<option value="sinonasal">Sinonasal cancer</option>
<option value="other">Other</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Tumor Stage</label>
<select class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" id="tumorStage">
<option value="">Select stage</option>
<option value="I">Stage I</option>
<option value="II">Stage II</option>
<option value="III">Stage III</option>
<option value="IVA">Stage IVA</option>
<option value="IVB">Stage IVB</option>
<option value="IVC">Stage IVC</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Tumor Size (cm)</label>
<input type="number" step="0.1" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" id="tumorSize" placeholder="Diameter in cm">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Tumor Location</label>
<select class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" id="tumorLocation">
<option value="">Select location</option>
<option value="right">Right side</option>
<option value="left">Left side</option>
<option value="midline">Midline</option>
<option value="bilateral">Bilateral</option>
</select>
</div>
</div>
<div class="mt-6 relative anatomy-illustration h-64 w-full rounded-md border border-gray-200" id="anatomyCanvas">
<!-- Tumor markers will be added here by JavaScript -->
</div>
<div class="mt-4 flex justify-center">
<button class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition mr-2" id="addTumorBtn">
<i class="fas fa-plus mr-1"></i> Add Tumor Marker
</button>
<button class="px-4 py-2 bg-gray-200 text-gray-700 rounded-md hover:bg-gray-300 transition" id="clearTumorsBtn">
<i class="fas fa-trash-alt mr-1"></i> Clear Markers
</button>
</div>
</section>
<!-- Treatment Planning Section -->
<section class="bg-white rounded-lg shadow-md p-6 mb-8">
<h2 class="text-xl font-semibold text-gray-800 mb-4 flex items-center">
<i class="fas fa-procedures mr-2 text-green-600"></i> Treatment Planning
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Treatment Intent</label>
<select class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" id="treatmentIntent">
<option value="curative">Curative</option>
<option value="palliative">Palliative</option>
<option value="adjuvant">Adjuvant</option>
<option value="neoadjuvant">Neoadjuvant</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Radiation Technique</label>
<select class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" id="radiationTechnique">
<option value="imrt">IMRT</option>
<option value="vmat">VMAT</option>
<option value="3dcrt">3D-CRT</option>
<option value="protons">Proton Therapy</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Total Dose (Gy)</label>
<input type="number" class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" id="totalDose" placeholder="Total dose in Gy">
<div class="mt-2">
<div class="dose-meter w-full"></div>
<div class="flex justify-between text-xs mt-1">
<span class="text-green-600">Safe</span>
<span class="text-yellow-500">Caution</span>
<span class="text-red-600">Danger</span>
</div>
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Fractionation</label>
<select class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" id="fractionation">
<option value="standard">Standard (2 Gy/fx)</option>
<option value="hyper">Hyperfractionated (1.2 Gy BID)</option>
<option value="hypo">Hypofractionated (2.5-3 Gy/fx)</option>
<option value="sbrt">SBRT (5-8 Gy/fx)</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Organs at Risk Priority</label>
<select class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" id="oarPriority">
<option value="balanced">Balanced Approach</option>
<option value="spinal">Spinal Cord Priority</option>
<option value="parotid">Parotid Sparing</option>
<option value="mandible">Mandible Sparing</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Concurrent Chemotherapy</label>
<select class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" id="concurrentChemo">
<option value="no">No</option>
<option value="cisplatin">Cisplatin</option>
<option value="carboplatin">Carboplatin</option>
<option value="cetuximab">Cetuximab</option>
<option value="other">Other</option>
</select>
</div>
</div>
<div class="mt-6">
<h3 class="text-lg font-medium text-gray-800 mb-2">Organs at Risk Constraints</h3>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Organ</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Max Dose (Gy)</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Mean Dose (Gy)</th>
<th class="px-4 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Priority</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
<tr>
<td class="px-4 py-2 whitespace-nowrap text-sm font-medium text-gray-900">Spinal Cord</td>
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">45</td>
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">-</td>
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">High</td>
</tr>
<tr>
<td class="px-4 py-2 whitespace-nowrap text-sm font-medium text-gray-900">Brainstem</td>
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">54</td>
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">-</td>
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">High</td>
</tr>
<tr>
<td class="px-4 py-2 whitespace-nowrap text-sm font-medium text-gray-900">Parotid Glands</td>
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">-</td>
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">26</td>
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">Medium</td>
</tr>
<tr>
<td class="px-4 py-2 whitespace-nowrap text-sm font-medium text-gray-900">Mandible</td>
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">70</td>
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">-</td>
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">Medium</td>
</tr>
<tr>
<td class="px-4 py-2 whitespace-nowrap text-sm font-medium text-gray-900">Optic Nerves</td>
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">50</td>
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">-</td>
<td class="px-4 py-2 whitespace-nowrap text-sm text-gray-500">High</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
<!-- Plan Summary & Actions -->
<section class="bg-white rounded-lg shadow-md p-6 mb-8">
<h2 class="text-xl font-semibold text-gray-800 mb-4 flex items-center">
<i class="fas fa-file-medical mr-2 text-purple-600"></i> Plan Summary
</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div class="bg-blue-50 p-4 rounded-lg border border-blue-100">
<h3 class="font-medium text-blue-800 mb-2">Recommended Dose</h3>
<p class="text-3xl font-bold text-blue-600" id="recommendedDose">0 Gy</p>
<p class="text-sm text-blue-700 mt-1" id="doseExplanation">Based on tumor characteristics</p>
</div>
<div class="bg-green-50 p-4 rounded-lg border border-green-100">
<h3 class="font-medium text-green-800 mb-2">Fractionation</h3>
<p class="text-2xl font-bold text-green-600" id="recommendedFractions">0 fractions</p>
<p class="text-sm text-green-700 mt-1" id="fractionExplanation">Standard fractionation</p>
</div>
<div class="bg-purple-50 p-4 rounded-lg border border-purple-100">
<h3 class="font-medium text-purple-800 mb-2">Risk Assessment</h3>
<p class="text-2xl font-bold text-purple-600" id="riskLevel">Low</p>
<p class="text-sm text-purple-700 mt-1" id="riskExplanation">Normal tissue constraints achievable</p>
</div>
</div>
<div class="mt-6 bg-yellow-50 p-4 rounded-lg border border-yellow-200" id="planNotes">
<h3 class="font-medium text-yellow-800 mb-2 flex items-center">
<i class="fas fa-exclamation-triangle mr-2"></i> Plan Notes
</h3>
<p class="text-yellow-700">Enter patient and tumor information to generate a personalized treatment plan.</p>
</div>
<div class="mt-6 flex flex-wrap justify-between">
<div class="mb-4 md:mb-0">
<button class="px-4 py-2 bg-gray-200 text-gray-700 rounded-md hover:bg-gray-300 transition mr-2 no-print" id="resetBtn">
<i class="fas fa-redo mr-1"></i> Reset Form
</button>
<button class="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition no-print" id="calculateBtn">
<i class="fas fa-calculator mr-1"></i> Calculate Plan
</button>
</div>
<div>
<button class="px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 transition mr-2 no-print" id="savePlanBtn">
<i class="fas fa-save mr-1"></i> Save Plan
</button>
<button class="px-4 py-2 bg-purple-600 text-white rounded-md hover:bg-purple-700 transition no-print" id="printPlanBtn">
<i class="fas fa-print mr-1"></i> Print Plan
</button>
</div>
</div>
</section>
<!-- Print Section (Hidden until printing) -->
<section class="print-only bg-white p-6">
<div class="flex justify-between items-center mb-6 border-b pb-4">
<div>
<h1 class="text-2xl font-bold text-gray-800">HeadNeck Dose Planner</h1>
<p class="text-gray-600">Radiation Treatment Plan</p>
</div>
<div class="text-right">
<p class="text-sm text-gray-500">Generated on: <span id="printDate"></span></p>
<p class="text-sm text-gray-500">Plan ID: <span id="printPlanId"></span></p>
</div>
</div>
<div class="mb-6">
<h2 class="text-xl font-semibold text-gray-800 mb-2">Patient Information</h2>
<div class="grid grid-cols-3 gap-4 text-sm">
<div>
<p class="font-medium">Patient ID:</p>
<p id="printPatientId"></p>
</div>
<div>
<p class="font-medium">Name:</p>
<p id="printPatientName"></p>
</div>
<div>
<p class="font-medium">Age:</p>
<p id="printPatientAge"></p>
</div>
</div>
</div>
<div class="mb-6">
<h2 class="text-xl font-semibold text-gray-800 mb-2">Tumor Characteristics</h2>
<div class="grid grid-cols-3 gap-4 text-sm">
<div>
<p class="font-medium">Tumor Type:</p>
<p id="printTumorType"></p>
</div>
<div>
<p class="font-medium">Stage:</p>
<p id="printTumorStage"></p>
</div>
<div>
<p class="font-medium">Size:</p>
<p id="printTumorSize"></p>
</div>
</div>
</div>
<div class="mb-6">
<h2 class="text-xl font-semibold text-gray-800 mb-2">Treatment Plan</h2>
<div class="grid grid-cols-3 gap-4 text-sm">
<div>
<p class="font-medium">Total Dose:</p>
<p id="printTotalDose"></p>
</div>
<div>
<p class="font-medium">Fractions:</p>
<p id="printFractions"></p>
</div>
<div>
<p class="font-medium">Technique:</p>
<p id="printTechnique"></p>
</div>
</div>
</div>
<div class="mb-6">
<h2 class="text-xl font-semibold text-gray-800 mb-2">Organs at Risk Constraints</h2>
<table class="min-w-full border text-sm">
<thead>
<tr class="bg-gray-100">
<th class="border px-4 py-2 text-left">Organ</th>
<th class="border px-4 py-2 text-left">Max Dose (Gy)</th>
<th class="border px-4 py-2 text-left">Mean Dose (Gy)</th>
</tr>
</thead>
<tbody>
<tr>
<td class="border px-4 py-2">Spinal Cord</td>
<td class="border px-4 py-2">45</td>
<td class="border px-4 py-2">-</td>
</tr>
<tr>
<td class="border px-4 py-2">Brainstem</td>
<td class="border px-4 py-2">54</td>
<td class="border px-4 py-2">-</td>
</tr>
<tr>
<td class="border px-4 py-2">Parotid Glands</td>
<td class="border px-4 py-2">-</td>
<td class="border px-4 py-2">26</td>
</tr>
<tr>
<td class="border px-4 py-2">Mandible</td>
<td class="border px-4 py-2">70</td>
<td class="border px-4 py-2">-</td>
</tr>
</tbody>
</table>
</div>
<div class="mt-8 pt-4 border-t">
<div class="flex justify-between">
<div class="w-1/2 pr-4">
<p class="font-medium mb-2">Physician Signature:</p>
<div class="h-16 border-b border-gray-400"></div>
<p class="text-sm text-gray-500 mt-1">Name & Date</p>
</div>
<div class="w-1/2 pl-4">
<p class="font-medium mb-2">Medical Physicist Signature:</p>
<div class="h-16 border-b border-gray-400"></div>
<p class="text-sm text-gray-500 mt-1">Name & Date</p>
</div>
</div>
</div>
<div class="mt-8 text-center text-xs text-gray-500">
<p>This document was automatically generated by HeadNeck Dose Planner software.</p>
<p>For clinical use only. Verify all dosimetric parameters before treatment.</p>
</div>
</section>
</main>
<!-- Footer -->
<footer class="gradient-bg text-white py-6">
<div class="container mx-auto px-4">
<div class="flex flex-col md:flex-row justify-between items-center">
<div class="mb-4 md:mb-0">
<p class="text-sm">&copy; 2023 HeadNeck Dose Planner. For medical professionals only.</p>
<p class="text-xs opacity-70 mt-1">Version 1.0.0</p>
</div>
<div class="flex space-x-4">
<a href="#" class="text-sm hover:underline">Privacy Policy</a>
<a href="#" class="text-sm hover:underline">Terms of Use</a>
<a href="#" class="text-sm hover:underline">Contact Support</a>
</div>
</div>
</div>
</footer>
<!-- JavaScript -->
<script>
document.addEventListener('DOMContentLoaded', function() {
// Tumor marker functionality
const anatomyCanvas = document.getElementById('anatomyCanvas');
const addTumorBtn = document.getElementById('addTumorBtn');
const clearTumorsBtn = document.getElementById('clearTumorsBtn');
const tumorSizeInput = document.getElementById('tumorSize');
const tumorLocationInput = document.getElementById('tumorLocation');
let tumorMarkers = [];
addTumorBtn.addEventListener('click', function() {
if (!tumorSizeInput.value || !tumorLocationInput.value) {
alert('Please enter tumor size and location first');
return;
}
const size = parseFloat(tumorSizeInput.value);
const location = tumorLocationInput.value;
// Create a new tumor marker
const marker = document.createElement('div');
marker.className = 'tumor-marker';
// Set size based on input (scaled for visualization)
const markerSize = Math.min(16 + (size * 4), 40);
marker.style.width = `${markerSize}px`;
marker.style.height = `${markerSize}px`;
// Position based on location
let left, top;
const canvasRect = anatomyCanvas.getBoundingClientRect();
const canvasWidth = canvasRect.width;
const canvasHeight = canvasRect.height;
switch(location) {
case 'right':
left = 70 + (Math.random() * 10);
top = 50 + (Math.random() * 20);
break;
case 'left':
left = 30 + (Math.random() * 10);
top = 50 + (Math.random() * 20);
break;
case 'midline':
left = 50 + (Math.random() * 10);
top = 50 + (Math.random() * 10);
break;
case 'bilateral':
left = 50 + (Math.random() * 40 - 20);
top = 50 + (Math.random() * 20);
break;
default:
left = 50;
top = 50;
}
// Convert percentages to pixels
const leftPx = (left / 100) * canvasWidth;
const topPx = (top / 100) * canvasHeight;
marker.style.left = `${leftPx}px`;
marker.style.top = `${topPx}px`;
// Add tooltip with tumor info
marker.title = `Size: ${size} cm\nLocation: ${location}`;
anatomyCanvas.appendChild(marker);
tumorMarkers.push(marker);
});
clearTumorsBtn.addEventListener('click', function() {
tumorMarkers.forEach(marker => {
anatomyCanvas.removeChild(marker);
});
tumorMarkers = [];
});
// Calculate plan functionality
const calculateBtn = document.getElementById('calculateBtn');
const recommendedDose = document.getElementById('recommendedDose');
const doseExplanation = document.getElementById('doseExplanation');
const recommendedFractions = document.getElementById('recommendedFractions');
const fractionExplanation = document.getElementById('fractionExplanation');
const riskLevel = document.getElementById('riskLevel');
const riskExplanation = document.getElementById('riskExplanation');
const planNotes = document.getElementById('planNotes');
calculateBtn.addEventListener('click', function() {
const tumorType = document.getElementById('tumorType').value;
const tumorStage = document.getElementById('tumorStage').value;
const treatmentIntent = document.getElementById('treatmentIntent').value;
const fractionation = document.getElementById('fractionation').value;
const concurrentChemo = document.getElementById('concurrentChemo').value;
if (!tumorType || !tumorStage) {
alert('Please enter tumor characteristics first');
return;
}
// Calculate recommended dose based on inputs
let dose = 66; // Default for curative
let fractions = 33;
let risk = 'Low';
let notes = [];
// Adjust based on treatment intent
if (treatmentIntent === 'palliative') {
dose = 20;
fractions = 5;
risk = 'Low';
notes.push('Palliative regimen selected');
} else if (treatmentIntent === 'adjuvant') {
dose = 60;
fractions = 30;
notes.push('Adjuvant treatment after surgery');
} else if (treatmentIntent === 'neoadjuvant') {
dose = 50;
fractions = 25;
notes.push('Neoadjuvant treatment before surgery');
}
// Adjust based on tumor stage
if (tumorStage === 'I') {
dose = Math.max(50, dose - 6);
} else if (tumorStage === 'II') {
dose = Math.max(60, dose - 6);
} else if (tumorStage === 'IVB' || tumorStage === 'IVC') {
dose = Math.min(70, dose + 4);
risk = 'High';
notes.push('Advanced stage disease - consider dose escalation');
}
// Adjust based on fractionation
if (fractionation === 'hyper') {
fractions = Math.ceil(dose / 1.2) * 2;
notes.push('Hyperfractionated regimen (BID)');
} else if (fractionation === 'hypo') {
fractions = Math.ceil(dose / 2.5);
notes.push('Hypofractionated regimen');
} else if (fractionation === 'sbrt') {
fractions = 5;
dose = 35;
notes.push('SBRT regimen selected');
}
// Adjust based on concurrent chemotherapy
if (concurrentChemo !== 'no') {
if (treatmentIntent === 'curative') {
dose = 70;
fractions = 35;
}
notes.push(`Concurrent ${concurrentChemo} - consider dose modifications`);
risk = 'Medium';
}
// Special cases for tumor types
if (tumorType === 'nasopharynx') {
dose = 70;
fractions = 35;
notes.push('Nasopharyngeal carcinoma - standard dose 70Gy');
} else if (tumorType === 'larynx') {
if (tumorStage === 'I' || tumorStage === 'II') {
dose = 66;
fractions = 33;
notes.push('Early stage laryngeal cancer - consider voice preservation');
}
}
// Update the UI
recommendedDose.textContent = `${dose} Gy`;
recommendedFractions.textContent = `${fractions} fractions`;
// Set risk level and color
riskLevel.textContent = risk;
if (risk === 'High') {
riskLevel.className = 'text-2xl font-bold text-red-600';
} else if (risk === 'Medium') {
riskLevel.className = 'text-2xl font-bold text-yellow-600';
} else {
riskLevel.className = 'text-2xl font-bold text-green-600';
}
// Update explanations
doseExplanation.textContent = getDoseExplanation(tumorType, tumorStage, treatmentIntent);
fractionExplanation.textContent = getFractionExplanation(fractionation);
riskExplanation.textContent = getRiskExplanation(risk);
// Update plan notes
if (notes.length > 0) {
planNotes.innerHTML = `
<h3 class="font-medium text-yellow-800 mb-2 flex items-center">
<i class="fas fa-exclamation-triangle mr-2"></i> Plan Notes
</h3>
<ul class="list-disc list-inside text-yellow-700">
${notes.map(note => `<li>${note}</li>`).join('')}
</ul>
`;
}
});
function getDoseExplanation(type, stage, intent) {
if (intent === 'palliative') {
return 'Palliative dose regimen';
}
let explanation = `Standard dose for ${type}`;
if (stage === 'I' || stage === 'II') {
explanation += ' (early stage)';
} else if (stage === 'III' || stage === 'IVA') {
explanation += ' (locally advanced)';
} else {
explanation += ' (advanced/metastatic)';
}
return explanation;
}
function getFractionExplanation(fractionation) {
switch(fractionation) {
case 'hyper': return 'Hyperfractionated (BID) regimen';
case 'hypo': return 'Hypofractionated regimen';
case 'sbrt': return 'Stereotactic body radiotherapy';
default: return 'Standard fractionation (2 Gy/fx)';
}
}
function getRiskExplanation(risk) {
switch(risk) {
case 'High': return 'Careful OAR evaluation needed';
case 'Medium': return 'Standard constraints achievable';
default: return 'Normal tissue constraints achievable';
}
}
// Print functionality
const printPlanBtn = document.getElementById('printPlanBtn');
printPlanBtn.addEventListener('click', function() {
// Set print date
const now = new Date();
document.getElementById('printDate').textContent = now.toLocaleDateString() + ' ' + now.toLocaleTimeString();
// Generate random plan ID
document.getElementById('printPlanId').textContent = 'PL-' + Math.floor(100000 + Math.random() * 900000);
// Populate patient info
document.getElementById('printPatientId').textContent = document.querySelector('input[placeholder="Enter patient ID"]').value || 'Not specified';
document.getElementById('printPatientName').textContent = document.querySelector('input[placeholder="Patient name"]').value || 'Not specified';
document.getElementById('printPatientAge').textContent = document.querySelector('input[placeholder="Age"]').value || 'Not specified';
// Populate tumor info
document.getElementById('printTumorType').textContent = document.getElementById('tumorType').value || 'Not specified';
document.getElementById('printTumorStage').textContent = document.getElementById('tumorStage').value || 'Not specified';
document.getElementById('printTumorSize').textContent = tumorSizeInput.value ? tumorSizeInput.value + ' cm' : 'Not specified';
// Populate treatment info
document.getElementById('printTotalDose').textContent = recommendedDose.textContent;
document.getElementById('printFractions').textContent = recommendedFractions.textContent;
document.getElementById('printTechnique').textContent = document.getElementById('radiationTechnique').value || 'Not specified';
// Trigger print
window.print();
});
// Reset form
const resetBtn = document.getElementById('resetBtn');
resetBtn.addEventListener('click', function() {
if (confirm('Are you sure you want to reset all fields?')) {
// Clear all form inputs
document.querySelectorAll('input, select').forEach(element => {
if (element.type !== 'button') {
element.value = '';
}
});
// Clear tumor markers
clearTumorsBtn.click();
// Reset recommendations
recommendedDose.textContent = '0 Gy';
recommendedFractions.textContent = '0 fractions';
riskLevel.textContent = 'Low';
riskLevel.className = 'text-2xl font-bold text-green-600';
doseExplanation.textContent = 'Based on tumor characteristics';
fractionExplanation.textContent = 'Standard fractionation';
riskExplanation.textContent = 'Normal tissue constraints achievable';
// Reset plan notes
planNotes.innerHTML = `
<h3 class="font-medium text-yellow-800 mb-2 flex items-center">
<i class="fas fa-exclamation-triangle mr-2"></i> Plan Notes
</h3>
<p class="text-yellow-700">Enter patient and tumor information to generate a personalized treatment plan.</p>
`;
}
});
// Save plan functionality (simulated)
const savePlanBtn = document.getElementById('savePlanBtn');
savePlanBtn.addEventListener('click', function() {
const patientId = document.querySelector('input[placeholder="Enter patient ID"]').value;
if (!patientId) {
alert('Please enter at least a Patient ID to save the plan');
return;
}
// In a real app, this would save to a database
// Here we just simulate with a confirmation
alert(`Plan saved for patient ${patientId}`);
// Change button to indicate success
savePlanBtn.innerHTML = '<i class="fas fa-check mr-1"></i> Plan Saved';
savePlanBtn.className = 'px-4 py-2 bg-green-600 text-white rounded-md transition mr-2 no-print';
setTimeout(() => {
savePlanBtn.innerHTML = '<i class="fas fa-save mr-1"></i> Save Plan';
savePlanBtn.className = 'px-4 py-2 bg-green-600 text-white rounded-md hover:bg-green-700 transition mr-2 no-print';
}, 2000);
});
// Navigation links
document.querySelectorAll('#homeLink, #newPlanLink, #savedPlansLink, #guidelinesLink').forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault();
alert('Navigation would go to: ' + this.textContent);
});
});
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Godito/dose-planner" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>