HTML
Krankenhaus-Management-Simulation
Unvollständiger Mockup einer Patienten Aufnahme Zimmer Zuordnungssimulation
Keine Vorschau vorhanden
Code-Snapshot
Dies ist der veröffentlichte Zustand. Spätere Änderungen am Code überschreiben diese Veröffentlichung nicht automatisch.
[{"text":"Projekt","spriteCssClass":"fa fa-folder","items":[{"text":"index.html","spriteCssClass":"fa fa-file-code-o","code":"<!DOCTYPE html>\n<html lang='de'>\n<head>\n <meta charset='UTF-8'>\n <meta name='viewport' content='width=device-width, initial-scale=1.0'>\n <title>Krankenhaus-Management-Simulation</title>\n <link rel='stylesheet' href='style.css'>\n</head>\n<body>\n <header class='hero'>\n <div>\n <p class='eyebrow'>CodeRoom Projekt Lab</p>\n <h1>Krankenhaus-Management-Simulation</h1>\n <p class='subtitle'>Steuere Aufnahme, Untersuchung und Behandlung, bevor die Wartezeiten kritisch werden.</p>\n </div>\n <div class='status-card'>\n <span class='status-label'>Krankenhausstatus</span>\n <strong id='hospitalStatus'>Stabil</strong>\n <small id='statusHint'>Das Team ist bereit.</small>\n </div>\n </header>\n\n <main class='layout'>\n <section class='panel control-panel'>\n <h2>Leitstelle</h2>\n <div class='button-row'>\n <button id='addPatientButton'>Patient aufnehmen</button>\n <button id='treatPatientButton'>Behandlung starten</button>\n <button id='pauseButton' class='secondary'>Pause</button>\n </div>\n <div class='resource-grid'>\n <div>\n <span>Ärzte frei</span>\n <strong id='doctorCount'>2</strong>\n </div>\n <div>\n <span>Zimmer frei</span>\n <strong id='roomCount'>3</strong>\n </div>\n <div>\n <span>Pflege frei</span>\n <strong id='nurseCount'>3</strong>\n </div>\n </div>\n <p class='hint'>Tipp: Kritische Fälle sollten zuerst behandelt werden. TODO: Baue später eine echte Prioritätenlogik ein.</p>\n </section>\n\n <section class='panel queue-panel'>\n <div class='section-heading'>\n <h2>Notaufnahme</h2>\n <span id='queueCount'>0 wartend</span>\n </div>\n <div id='patientList' class='patient-list'></div>\n </section>\n\n <section class='panel rooms-panel'>\n <div class='section-heading'>\n <h2>Zimmerplan</h2>\n <span>Prototyp</span>\n </div>\n <div class='rooms'>\n <div class='room'><strong>Zimmer 1</strong><span id='roomOne'>frei</span></div>\n <div class='room'><strong>Zimmer 2</strong><span id='roomTwo'>frei</span></div>\n <div class='room'><strong>Zimmer 3</strong><span id='roomThree'>frei</span></div>\n </div>\n <p class='hint'>TODO: Verknüpfe echte Patientendaten mit den Zimmern.</p>\n </section>\n\n <section class='panel stats-panel'>\n <h2>Tagesstatistik</h2>\n <div class='stats'>\n <div><span>Behandelt</span><strong id='treatedCount'>0</strong></div>\n <div><span>Entlassen</span><strong id='releasedCount'>0</strong></div>\n <div><span>Kritisch</span><strong id='criticalCount'>0</strong></div>\n <div><span>Ø Wartezeit</span><strong id='avgWaitTime'>0</strong></div>\n </div>\n </section>\n </main>\n\n <script src='script.js'></script>\n</body>\n</html>","isMain":true},{"text":"script.js","spriteCssClass":"fa fa-file-code-o","code":"const patientNames = ['Mia Becker', 'Noah Schulz', 'Lea Wagner', 'Emil Hoffmann', 'Sara Klein', 'Ben Fischer'];\nconst conditions = ['Atemnot', 'Fieber', 'Sportverletzung', 'Bauchschmerzen', 'Schwindel', 'Schnittwunde'];\nconst priorities = ['stabil', 'dringend', 'kritisch'];\n\nlet patients = [];\nlet treated = 0;\nlet released = 0;\nlet isPaused = false;\nlet nextId = 1;\nlet waitingTimes = [];\n\n// Array to track room occupancy\nlet rooms = ['frei', 'frei', 'frei'];\n\n// Event system\nconst events = [\n { type: 'normal', message: 'Neue Lieferung von Medikamenten eingetroffen.', probability: 0.6 },\n { type: 'normal', message: 'Rettungswagen eingetroffen mit neuem Patienten.', probability: 0.5 },\n { type: 'normal', message: 'Schulung des Personals abgeschlossen.', probability: 0.4 },\n { type: 'grippewelle', message: 'Grippewelle gemeldet! Erhöhte Patientenzahlen erwartet.', probability: 0.2 },\n { type: 'normal', message: 'Technische Wartung der Geräte durchgeführt.', probability: 0.5 },\n { type: 'normal', message: 'Besprechung des Behandlungsteams abgeschlossen.', probability: 0.4 }\n];\n\nconst patientList = document.querySelector('#patientList');\nconst queueCount = document.querySelector('#queueCount');\nconst treatedCount = document.querySelector('#treatedCount');\nconst releasedCount = document.querySelector('#releasedCount');\nconst criticalCount = document.querySelector('#criticalCount');\nconst avgWaitTime = document.querySelector('#avgWaitTime');\nconst hospitalStatus = document.querySelector('#hospitalStatus');\nconst statusHint = document.querySelector('#statusHint');\nconst doctorCount = document.querySelector('#doctorCount');\nconst roomCount = document.querySelector('#roomCount');\nconst nurseCount = document.querySelector('#nurseCount');\nconst pauseButton = document.querySelector('#pauseButton');\n\nfunction randomItem(list) {\n return list[Math.floor(Math.random() * list.length)];\n}\nfunction triggerRandomEvent() {\n // Filter events based on their probability\n const possibleEvents = events.filter(event => Math.random() < event.probability);\n \n if (possibleEvents.length > 0) {\n const randomEvent = randomItem(possibleEvents);\n \n // Show event message in status area\n statusHint.textContent = randomEvent.message;\n \n // Handle special event types\n if (randomEvent.type === 'grippewelle') {\n // Add two additional patients during flu wave\n addPatient();\n addPatient();\n \n // Update status to reflect the flu wave\n hospitalStatus.textContent = 'Angespannt';\n }\n }\n}\n\n\nfunction createPatient() {\n const priority = randomItem(priorities);\n\n return {\n id: nextId++,\n name: randomItem(patientNames),\n condition: randomItem(conditions),\n priority: priority,\n wait: 0,\n treatmentTime: priority === 'kritisch' ? 4 : 3\n };\n}\n\nfunction addPatient() {\n patients.push(createPatient());\n renderAll();\n}\n\nfunction selectPatient(patientId) {\n const patient = patients.find(p => p.id === patientId);\n if (patient) {\n statusHint.textContent = 'Patient ' + patient.name + ' ausgewählt.';\n return patient;\n }\n return null;\n}\n\nfunction admitPatient(patientId) {\n const patient = patients.find(p => p.id === patientId);\n if (!patient) {\n statusHint.textContent = 'Patient nicht gefunden.';\n return;\n }\n\n // Find a free room\n let roomIndex = -1;\n for (let i = 0; i < rooms.length; i++) {\n if (rooms[i] === 'frei') {\n roomIndex = i;\n break;\n }\n }\n\n if (roomIndex !== -1) {\n // Remove patient from waiting list\n patients = patients.filter(p => p.id !== patientId);\n treated += 1;\n\n if (patient.priority === 'kritisch') {\n released += 1;\n }\n\n // Record waiting time\n waitingTimes.push(patient.wait);\n\n // Assign patient to room\n rooms[roomIndex] = patient.name;\n statusHint.textContent = patient.name + ' wird in Zimmer ' + (roomIndex + 1) + ' aufgenommen.';\n\n // Release room after treatment time\n setTimeout(function() {\n rooms[roomIndex] = 'frei';\n statusHint.textContent = 'Zimmer ' + (roomIndex + 1) + ' ist wieder frei.';\n renderAll();\n }, patient.treatmentTime * 1000);\n } else {\n statusHint.textContent = 'Kein freies Zimmer verfügbar!';\n }\n\n renderAll();\n}\n\nfunction treatPatient() {\n if (patients.length === 0) {\n statusHint.textContent = 'Keine wartenden Patienten.';\n return;\n }\n\n // Find patient with highest priority (kritisch > dringend > stabil)\n let selectedPatient = null;\n let selectedIndex = -1;\n \n // First look for kritisch patients\n for (let i = 0; i < patients.length; i++) {\n if (patients[i].priority === 'kritisch') {\n selectedPatient = patients[i];\n selectedIndex = i;\n break;\n }\n }\n \n // If no kritisch, look for dringend\n if (selectedPatient === null) {\n for (let i = 0; i < patients.length; i++) {\n if (patients[i].priority === 'dringend') {\n selectedPatient = patients[i];\n selectedIndex = i;\n break;\n }\n }\n }\n \n // If no kritisch or dringend, look for stabil\n if (selectedPatient === null) {\n for (let i = 0; i < patients.length; i++) {\n if (patients[i].priority === 'stabil') {\n selectedPatient = patients[i];\n selectedIndex = i;\n break;\n }\n }\n }\n\n // Find a free room\n let roomIndex = -1;\n for (let i = 0; i < rooms.length; i++) {\n if (rooms[i] === 'frei') {\n roomIndex = i;\n break;\n }\n }\n\n // Remove the selected patient from the array\n if (selectedIndex !== -1 && roomIndex !== -1) {\n patients.splice(selectedIndex, 1);\n treated += 1;\n\n if (selectedPatient.priority === 'kritisch') {\n released += 1;\n }\n\n // Record waiting time of treated patient\n waitingTimes.push(selectedPatient.wait);\n\n // Assign patient to room\n rooms[roomIndex] = selectedPatient.name;\n statusHint.textContent = selectedPatient.name + ' wird in Zimmer ' + (roomIndex + 1) + ' behandelt.';\n\n // Release room after treatment time\n setTimeout(function() {\n rooms[roomIndex] = 'frei';\n statusHint.textContent = 'Zimmer ' + (roomIndex + 1) + ' ist wieder frei.';\n renderAll();\n }, selectedPatient.treatmentTime * 1000);\n } else if (roomIndex === -1) {\n statusHint.textContent = 'Kein freies Zimmer verfügbar!';\n }\n \n renderAll();\n}\n\nfunction updateWaitingTimes() {\n if (isPaused) {\n return;\n }\n\n patients.forEach(function(patient) {\n patient.wait += 1;\n\n // TODO: Verfeinere diese Eskalation mit mehreren Regeln.\n if (patient.wait > 8 && patient.priority === 'stabil') {\n patient.priority = 'dringend';\n }\n\n if (patient.wait > 14 && patient.priority === 'dringend') {\n patient.priority = 'kritisch';\n }\n });\n\n // Trigger random events occasionally\n if (Math.random() > 0.7) {\n triggerRandomEvent();\n }\n\n if (Math.random() > 0.55) {\n addPatient();\n return;\n }\n\n renderAll();\n}\n\nfunction createPatientCard(patient) {\n const card = document.createElement('article');\n card.className = 'patient-card';\n card.dataset.patientId = patient.id;\n\n if (patient.priority === 'dringend') {\n card.classList.add('warn');\n }\n\n if (patient.priority === 'kritisch') {\n card.classList.add('danger');\n }\n\n const info = document.createElement('div');\n\n const title = document.createElement('h3');\n title.textContent = patient.name;\n\n const condition = document.createElement('p');\n condition.textContent = 'Zustand: ' + patient.condition;\n\n const wait = document.createElement('p');\n wait.textContent = 'Wartezeit: ' + patient.wait + ' Minuten';\n\n const badge = document.createElement('span');\n badge.className = 'priority-badge';\n badge.textContent = patient.priority;\n\n const selectButton = document.createElement('button');\n selectButton.textContent = 'Auswählen';\n selectButton.className = 'select-button';\n selectButton.dataset.patientId = patient.id;\n\n const admitButton = document.createElement('button');\n admitButton.textContent = 'Aufnehmen';\n admitButton.className = 'admit-button';\n admitButton.dataset.patientId = patient.id;\n\n info.appendChild(title);\n info.appendChild(condition);\n info.appendChild(wait);\n card.appendChild(info);\n card.appendChild(badge);\n card.appendChild(selectButton);\n card.appendChild(admitButton);\n\n return card;\n}\n\nfunction renderPatients() {\n patientList.textContent = '';\n\n if (patients.length === 0) {\n const empty = document.createElement('p');\n empty.className = 'hint';\n empty.textContent = 'Die Notaufnahme ist leer. Nimm einen neuen Patienten auf.';\n patientList.appendChild(empty);\n return;\n }\n\n patients.forEach(function(patient) {\n patientList.appendChild(createPatientCard(patient));\n });\n}\n\nfunction renderStats() {\n const criticalPatients = patients.filter(function(patient) {\n return patient.priority === 'kritisch';\n }).length;\n\n queueCount.textContent = patients.length + ' wartend';\n treatedCount.textContent = treated;\n releasedCount.textContent = released;\n criticalCount.textContent = criticalPatients;\n\n // Calculate average waiting time\n if (waitingTimes.length > 0) {\n const sum = waitingTimes.reduce((a, b) => a + b, 0);\n const avg = Math.round(sum / waitingTimes.length);\n avgWaitTime.textContent = avg;\n } else {\n avgWaitTime.textContent = '0';\n }\n\n doctorCount.textContent = Math.max(0, 2 - criticalPatients);\n roomCount.textContent = Math.max(0, 3 - patients.length);\n nurseCount.textContent = Math.max(0, 3 - Math.floor(patients.length / 2));\n\n if (criticalPatients >= 3 || patients.length >= 7) {\n hospitalStatus.textContent = 'Überlastet';\n statusHint.textContent = 'Priorisiere kritische Fälle.';\n } else if (criticalPatients > 0 || patients.length >= 4) {\n hospitalStatus.textContent = 'Angespannt';\n } else {\n hospitalStatus.textContent = 'Stabil';\n }\n}\n\nfunction renderRooms() {\n const roomOne = document.querySelector('#roomOne');\n const roomTwo = document.querySelector('#roomTwo');\n const roomThree = document.querySelector('#roomThree');\n const roomElements = [roomOne, roomTwo, roomThree];\n\n roomElements.forEach(function(roomElement, index) {\n roomElement.textContent = rooms[index];\n });\n}\n\nfunction renderAll() {\n renderPatients();\n renderStats();\n renderRooms();\n}\n// Event listeners for select and admit buttons\ndocument.addEventListener('click', function(event) {\n if (event.target.classList.contains('select-button')) {\n const patientId = parseInt(event.target.dataset.patientId);\n selectPatient(patientId);\n } else if (event.target.classList.contains('admit-button')) {\n const patientId = parseInt(event.target.dataset.patientId);\n admitPatient(patientId);\n }\n});\n\n\ndocument.querySelector('#addPatientButton').addEventListener('click', addPatient);\ndocument.querySelector('#treatPatientButton').addEventListener('click', treatPatient);\npauseButton.addEventListener('click', function() {\n isPaused = !isPaused;\n pauseButton.textContent = isPaused ? 'Weiter' : 'Pause';\n statusHint.textContent = isPaused ? 'Simulation pausiert.' : 'Simulation läuft weiter.';\n});\n\naddPatient();\naddPatient();\nrenderAll();\nsetInterval(updateWaitingTimes, 2500);\n","isMain":false},{"text":"style.css","spriteCssClass":"fa fa-file-code-o","code":":root {\n --bg: #101827;\n --panel: #172235;\n --panel-light: #22314a;\n --text: #eef4ff;\n --muted: #9fb0cc;\n --accent: #57d3ff;\n --good: #68e391;\n --warn: #ffd166;\n --danger: #ff6b6b;\n}\n\n* {\n box-sizing: border-box;\n}\n\nbody {\n margin: 0;\n font-family: Arial, Helvetica, sans-serif;\n background: radial-gradient(circle at top left, #1f3b65, var(--bg));\n color: var(--text);\n min-height: 100vh;\n}\n\n.hero {\n display: flex;\n justify-content: space-between;\n gap: 1rem;\n padding: 2rem;\n align-items: stretch;\n}\n\n.eyebrow {\n color: var(--accent);\n text-transform: uppercase;\n letter-spacing: 0.12em;\n font-size: 0.8rem;\n margin: 0 0 0.5rem;\n}\n\nh1, h2, p {\n margin-top: 0;\n}\n\nh1 {\n font-size: clamp(2rem, 5vw, 4rem);\n margin-bottom: 0.5rem;\n}\n\n.subtitle {\n color: var(--muted);\n max-width: 680px;\n font-size: 1.1rem;\n}\n\n.status-card, .panel {\n background: rgba(23, 34, 53, 0.88);\n border: 1px solid rgba(255, 255, 255, 0.08);\n border-radius: 22px;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25);\n}\n\n.status-card {\n min-width: 220px;\n padding: 1.4rem;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.status-label, .section-heading span, .hint, .resource-grid span, .stats span, .room span {\n color: var(--muted);\n}\n\n.status-card strong {\n font-size: 2rem;\n margin: 0.4rem 0;\n}\n\n.layout {\n display: grid;\n grid-template-columns: 1fr 1.4fr;\n gap: 1rem;\n padding: 0 2rem 2rem;\n}\n\n.panel {\n padding: 1.3rem;\n}\n\n.queue-panel {\n grid-row: span 2;\n}\n\n.section-heading {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 1rem;\n}\n\n.button-row {\n display: flex;\n flex-wrap: wrap;\n gap: 0.7rem;\n margin-bottom: 1rem;\n}\n\nbutton {\n border: 0;\n border-radius: 999px;\n background: var(--accent);\n color: #07111f;\n font-weight: 700;\n padding: 0.8rem 1rem;\n cursor: pointer;\n transition: transform 0.15s ease, filter 0.15s ease;\n}\n\nbutton:hover {\n transform: translateY(-2px);\n filter: brightness(1.08);\n}\n\nbutton.secondary {\n background: var(--panel-light);\n color: var(--text);\n}\n\n.resource-grid, .stats {\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: 0.7rem;\n}\n\n.resource-grid div, .stats div, .room, .patient-card {\n background: var(--panel-light);\n border-radius: 16px;\n padding: 1rem;\n}\n\n.resource-grid strong, .stats strong {\n display: block;\n font-size: 1.7rem;\n margin-top: 0.2rem;\n}\n\n.patient-list {\n display: grid;\n gap: 0.8rem;\n}\n\n.patient-card {\n display: grid;\n grid-template-columns: 1fr auto auto auto;\n gap: 0.6rem;\n border-left: 8px solid var(--good);\n}\n.patient-card button {\n padding: 0.4rem 0.8rem;\n border-radius: 8px;\n font-size: 0.8rem;\n margin-left: 0.4rem;\n}\n\n.patient-card .select-button {\n background: var(--panel-light);\n color: var(--text);\n}\n\n.patient-card .admit-button {\n background: var(--accent);\n color: #07111f;\n}\n\n\n.patient-card.warn {\n border-left-color: var(--warn);\n}\n\n.patient-card.danger {\n border-left-color: var(--danger);\n}\n\n.patient-card h3 {\n margin: 0 0 0.3rem;\n}\n\n.patient-card p {\n margin: 0.15rem 0;\n color: var(--muted);\n}\n\n.priority-badge {\n padding: 0.35rem 0.6rem;\n border-radius: 999px;\n background: rgba(255, 255, 255, 0.1);\n align-self: start;\n font-weight: 700;\n}\n\n.rooms {\n display: grid;\n gap: 0.7rem;\n}\n\n.room {\n display: flex;\n justify-content: space-between;\n}\n\n.hint {\n margin: 1rem 0 0;\n line-height: 1.5;\n}\n\n@media (max-width: 850px) {\n .hero, .layout {\n grid-template-columns: 1fr;\n display: grid;\n padding-left: 1rem;\n padding-right: 1rem;\n }\n\n .hero {\n padding-top: 1rem;\n }\n\n .resource-grid, .stats {\n grid-template-columns: 1fr;\n }\n\n .button-row {\n flex-direction: column;\n gap: 0.5rem;\n }\n\n button {\n width: 100%;\n padding: 0.8rem;\n }\n\n .patient-list {\n gap: 0.6rem;\n }\n\n .patient-card {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n }\n}\n","isMain":false}]}]