Kurumların siber güvenlik tatbikatlarını planlı, ölçülebilir ve izlenebilir bir yapıda yönetebilmesi amacıyla hazırlanmıştır.
Bu Form; Tatbikat senaryosunun oluşturulması, kapsam ve hedeflerin belirlenmesi, katılımcıların ve rollerin tanımlanması, senaryo akışlarının ve karar noktalarının kaydedilmesi, gözlemci notlarının toplanması ve tatbikat sırasında ortaya çıkan bulguların sistematik biçimde değerlendirilmesini sağlar.
Böylece teknik ekipler, yöneticiler ve gözlemciler aynı yapı üzerinden tatbikatın nasıl ilerlediğini, hangi kararların alındığını ve süreçlerin beklenen şekilde çalışıp çalışmadığını takip edebilir.
Temel hedef, siber tatbikatları yalnızca gerçekleştirilen bir faaliyet olmaktan çıkararak kurumsal siber dayanıklılığı geliştiren sürekli iyileştirme sürecine dönüştürmektir. Tatbikat sonunda tespit edilen eksikliklerin sorumlu kişi veya birim, öncelik, hedef tarih ve tamamlanma durumu ile aksiyona dönüştürülmesi sayesinde bulguların takip edilmeden kalması önlenir.
Bu yapı; müdahale sürelerinin, karar alma süreçlerinin, iletişim ve eskalasyon kabiliyetlerinin, teknik kontrollerin ve ekip koordinasyonunun değerlendirilmesine yardımcı olur; yönetimin mevcut durum, açık riskler ve iyileştirme ihtiyaçları hakkında ölçülebilir ve doğrulanabilir bilgiye ulaşmasını sağlar.
Bir Not defteri açarak, aşağıdaki (Mavi satırlar) html kodu içine kaydedin. Not defteri uzantısını .txt yerine ".html" olarak değiştirip kaydedin. Ör: "Siber Tatbikat Tasarım ve Aksiyon Takip Formu.html" sayfayı kapatıp tekrar açtığınızda, web browser üzerinden sayfanız açılacaktır.
Sol tarafta görünen logo için, html dosyanız nerede ise, masaüstü veya oluşturulan bir klasör. Logonuzda aynı yerde olursa forma yansır. Logo ismi "logo.jpg" olmalı. Çift tıklayarak açtığınızda, browser üzerinde form açılışı gerçekleşir. Veya alanına 5 kez peş peşe tıklayarak çalışma esnasında logo değişimi de yapılabilir.
Başlık, başlığın altındaki, başlığın sağındaki ve alttaki yazıları, not defteri içinde "Ctrl + F" tuşları ile kelime yazarak bulabilir, ilgili metinleri kendinize göre uyarlayarak kaydederek kullanabilirsiniz. Başlık alanındaki "OLGUN BAŞKANLIĞI" alanına 5 kez peş peşe tıklayarak; Departman, Müdürlük veya Başkanlığınıza ait bilgiyi manuel girebilirsiniz.
Formun boş hali;
Formun dolu hali:
PDF / Yazdır
Dışarı Aktarılan Excel Verisi:
HTML Kod:
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Siber Tatbikat Tasarım ve Aksiyon Takip Formu</title>
<style>
:root{
--bg:#f8fafc;--panel:#fff;--line:#d7dee8;--text:#0f172a;--muted:#64748b;
--blue:#0284c7;--blue-soft:#e0f2fe;--blue-deep:#075985;--green-soft:#dcfce7;--green:#166534;
--amber-soft:#fef3c7;--amber:#92400e;--red-soft:#fee2e2;--red:#991b1b;--violet-soft:#f3e8ff;--violet:#6b21a8;
--shadow:0 2px 8px rgba(15,23,42,.06);--radius:6px;
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
body{margin:0;background:var(--bg);color:var(--text);font-family:"Segoe UI",Arial,sans-serif;font-size:13px}
.app{width:calc(100% - 28px);max-width:1540px;margin:14px auto;padding:10px;background:#fff;border:1px solid #cbd5e1;border-radius:8px;box-shadow:0 3px 14px rgba(15,23,42,.07)}
.top-frame{width:100%;background:#fff;border:1px solid #cbd5e1;border-radius:7px;box-shadow:var(--shadow);overflow:hidden;margin-bottom:10px}
.header{
width:100%;display:grid;grid-template-columns:60px minmax(0,1fr);align-items:center;gap:12px;position:relative;
background:#fff;border:0;border-left:5px solid var(--blue);border-bottom:1px solid var(--line);
padding:10px clamp(240px,34vw,540px) 10px 14px;box-shadow:none;margin:0
}
.logo-box{width:60px;height:60px;display:flex;align-items:center;justify-content:center;overflow:hidden;cursor:pointer;padding:0}
.logo-box:hover{outline:1px dashed #94a3b8;border-radius:4px}.logo-box:focus-visible{outline:2px solid var(--blue);outline-offset:2px}
.logo-box img{width:100%;height:100%;object-fit:contain;display:block}.logo-fallback{font-weight:700;color:var(--blue);font-size:11px;text-align:center;line-height:1.15}
.headerTitleBlock{min-width:0;align-self:center}.title-main{font-size:21px;font-weight:750;line-height:1.15;color:#0f172a}.title-sub{margin-top:4px;color:var(--muted);font-size:11.5px;line-height:1.35}
.org-title{position:absolute;right:14px;top:50%;transform:translateY(-50%);display:block;width:max-content;max-width:calc(clamp(240px,34vw,540px) - 28px);text-align:right;color:#000;font-size:15px;font-weight:700;line-height:1;white-space:nowrap;overflow:visible;text-overflow:clip;outline:none;writing-mode:horizontal-tb}
.org-title.editing{right:14px;top:50%;transform:translateY(-50%);min-width:180px;width:max-content;max-width:calc(clamp(240px,34vw,540px) - 28px);margin:0;overflow:visible;text-overflow:clip;outline:1px dashed var(--blue);background:#f0f9ff;border-radius:3px;padding:3px 5px;cursor:text}
.toolbar{
display:flex;align-items:center;gap:8px;overflow-x:auto;width:100%;max-width:none;
margin:0;background:#fff;border:0;box-shadow:none;padding:9px 14px
}
button,.button-like{height:36px;display:inline-flex;flex:0 0 auto;align-items:center;justify-content:center;border:1px solid #cbd5e1;border-radius:6px;padding:8px 12px;background:#f1f5f9;color:#334155;font:700 12px "Segoe UI",Arial,sans-serif;cursor:pointer;white-space:nowrap}
button:hover,.button-like:hover{filter:brightness(.97)}
button.primary,button.excel-export{background:var(--blue-soft);border-color:#bae6fd;color:var(--blue-deep)}
.button-like.excel-import{background:var(--green-soft);border-color:#bbf7d0;color:var(--green)}
button.add{background:#f0f9ff;border-color:#bae6fd;color:#075985}button.danger{background:#fff1f2;border-color:#fecdd3;color:#9f1239;height:30px;padding:5px 9px;font-size:11px}
.toolbar .spacer{flex:1}.statusline{flex:0 0 auto;color:var(--muted);font-size:11px;white-space:nowrap}.hidden{display:none!important}
.section{width:100%;background:#fff;border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow);margin-bottom:10px;overflow:hidden}
.section-title{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:8px 10px 8px 12px;background:#f8fbfd;border-bottom:1px solid #dbe3ea;border-left:4px solid var(--blue);color:var(--blue-deep);font-weight:700;font-size:13px;line-height:1.2}
.section-title small{font-weight:500;color:#64748b;font-size:11px;text-align:right;line-height:1.25}.section-body{padding:10px}
.grid{display:grid;gap:8px}.g2{grid-template-columns:repeat(2,minmax(0,1fr))}.g3{grid-template-columns:repeat(3,minmax(0,1fr))}.g4{grid-template-columns:repeat(4,minmax(0,1fr))}.g5{grid-template-columns:repeat(5,minmax(0,1fr))}.span2{grid-column:span 2}.span3{grid-column:span 3}.span4{grid-column:span 4}.field{min-width:0}
label{display:block;font-size:11.5px;font-weight:650;color:#334155;margin:0 0 4px}input,select,textarea{width:100%;border:1px solid #cbd5e1;border-radius:5px;background:#fff;color:#0f172a;padding:7px 8px;font:12.5px "Segoe UI",Arial,sans-serif;outline:none}
input:focus,select:focus,textarea:focus{border-color:#38bdf8;box-shadow:0 0 0 2px rgba(14,165,233,.10)}textarea{min-height:66px;resize:none;overflow:hidden;line-height:1.45}.tall{min-height:94px}.readonly{background:#f8fafc;color:#334155}.hint{font-size:10.5px;color:var(--muted);margin-top:4px;line-height:1.35}
.section-tools{display:flex;align-items:center;gap:8px;margin-bottom:8px}.section-tools .note{color:var(--muted);font-size:10.5px}.section-tools .spacer{flex:1}
.repeat-list{display:grid;gap:8px}.repeat-empty{border:1px dashed #cbd5e1;border-radius:6px;padding:16px;text-align:center;color:#64748b;background:#f8fafc;font-size:11.5px}
.repeat-card{border:1px solid #dbe3ea;border-radius:6px;background:#fff;overflow:hidden;break-inside:avoid}.repeat-head{display:flex;align-items:center;gap:8px;padding:7px 9px;background:#f8fafc;border-bottom:1px solid #e2e8f0}.repeat-title{font-size:12px;font-weight:750;color:#334155}.repeat-code{font-size:11px;font-weight:700;color:#075985;background:#e0f2fe;border:1px solid #bae6fd;border-radius:999px;padding:3px 7px}.repeat-head .spacer{flex:1}.repeat-body{padding:9px}
.kpis{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:8px;margin-bottom:9px}.kpi{border:1px solid #dbe3ea;border-radius:6px;padding:9px;background:#f8fafc;text-align:center}.kpi .v{font-size:20px;font-weight:800;line-height:1.05;color:#0f172a}.kpi .l{margin-top:4px;font-size:10.5px;color:#64748b}.kpi.warn{background:var(--amber-soft);border-color:#fcd34d}.kpi.danger{background:var(--red-soft);border-color:#fecaca}.kpi.good{background:var(--green-soft);border-color:#bbf7d0}
.badge{display:inline-flex;align-items:center;border-radius:999px;padding:3px 7px;font-size:10.5px;font-weight:700;border:1px solid #cbd5e1;background:#f8fafc}.badge.blue{background:#e0f2fe;border-color:#bae6fd;color:#075985}.badge.green{background:#dcfce7;border-color:#bbf7d0;color:#166534}.badge.amber{background:#fef3c7;border-color:#fde68a;color:#92400e}.badge.red{background:#fee2e2;border-color:#fecaca;color:#991b1b}
.metric-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}.metric{border:1px solid #e2e8f0;border-radius:6px;padding:8px;background:#f8fafc}.metric label{font-size:10.5px}.metric .unit{display:grid;grid-template-columns:1fr 60px;gap:6px;align-items:center}.metric .unit span{font-size:10.5px;color:#64748b;text-align:center}
.summary-box{border:1px solid #bae6fd;background:#f0f9ff;border-radius:6px;padding:9px;margin-top:8px}.summary-box strong{color:#075985}
.footer-note{margin:10px 2px 2px;color:#64748b;font-size:10.5px;line-height:1.45;text-align:center}
@media(max-width:1100px){.app{width:calc(100% - 20px);margin:10px auto;padding:8px}.header{grid-template-columns:52px minmax(0,1fr);padding-right:clamp(210px,35vw,380px)}.org-title{right:12px;max-width:calc(clamp(210px,35vw,380px) - 24px)}.org-title.editing{right:12px;max-width:calc(clamp(210px,35vw,380px) - 24px)}.logo-box{width:52px;height:52px}.g4,.g5{grid-template-columns:repeat(2,minmax(0,1fr))}.g3{grid-template-columns:repeat(2,minmax(0,1fr))}.kpis{grid-template-columns:repeat(2,minmax(0,1fr))}.metric-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.span3,.span4{grid-column:span 2}}
@media(max-width:680px){.app{width:calc(100% - 12px);margin:6px auto;padding:6px}.header{padding-right:170px;gap:8px}.org-title{right:10px;max-width:150px;font-size:11.5px}.org-title.editing{right:10px;min-width:120px;max-width:150px;font-size:11.5px}.g2,.g3,.g4,.g5,.kpis,.metric-grid{grid-template-columns:1fr}.span2,.span3,.span4{grid-column:span 1}.title-main{font-size:17px}.title-sub{font-size:10.5px}.toolbar{padding:8px 10px}}
@page{size:A4 landscape;margin:7mm 7mm 10mm 7mm;@bottom-right{content:"Sayfa " counter(page) " / " counter(pages);font:8pt "Segoe UI";color:#64748b;text-align:right}}
@media print{
*{-webkit-print-color-adjust:exact!important;print-color-adjust:exact!important}
html,body{width:100%;background:#fff!important}
body{font-size:9.6pt;line-height:1.35}
.app{width:100%;max-width:none;margin:0;padding:2.2mm;border:1px solid #94a3b8;border-radius:0;box-shadow:none}
.top-frame{margin-bottom:3mm;border:1px solid #94a3b8;border-radius:0;box-shadow:none;break-inside:avoid}
.toolbar,.no-print,.danger,.section-tools button{display:none!important}
.header{width:100%;margin:0;box-shadow:none;border-radius:0;grid-template-columns:15mm minmax(0,1fr);padding:2.7mm 80mm 2.7mm 3.2mm;gap:3mm;border-bottom:0;position:relative}
.logo-box{width:15mm;height:15mm}.title-main{font-size:15pt}.title-sub{font-size:8.4pt}.org-title{position:absolute;right:3.2mm;top:50%;transform:translateY(-50%);font-size:10.5pt;line-height:1;max-width:73mm;white-space:nowrap;overflow:visible;text-overflow:clip;text-align:right}.org-title.editing{right:3.2mm;top:50%;transform:translateY(-50%);max-width:73mm;padding:0;outline:none;background:transparent}
.section{box-shadow:none;margin-bottom:3mm;border-color:#cbd5e1;overflow:visible;break-inside:auto;page-break-inside:auto}
.section-title{padding:2.1mm 2.6mm;font-size:9.4pt}.section-title small{font-size:7.7pt;max-width:48%;line-height:1.2}.section-body{padding:2.5mm}
.grid{gap:2.1mm}.g5{grid-template-columns:repeat(5,minmax(0,1fr))}.g4{grid-template-columns:repeat(4,minmax(0,1fr))}.g3{grid-template-columns:repeat(3,minmax(0,1fr))}.g2{grid-template-columns:repeat(2,minmax(0,1fr))}.span2{grid-column:span 2}.span3{grid-column:span 3}.span4{grid-column:span 4}
.field{min-width:0;break-inside:avoid;page-break-inside:avoid}
label{font-size:7.8pt;margin-bottom:1mm;line-height:1.2}
input,select,textarea{display:none!important}
.print-value{display:block!important;width:100%;min-height:7mm;border:1px solid #cbd5e1;border-radius:2px;background:#fff;color:#0f172a;padding:1.5mm 1.7mm;font:8.5pt/1.32 "Segoe UI",Arial,sans-serif;white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-word}
.print-value.empty{min-height:7mm;color:transparent}
.repeat-list{gap:2.2mm}.repeat-card{break-inside:avoid;page-break-inside:avoid;margin-bottom:2.2mm;border-color:#cbd5e1}.repeat-head{padding:1.6mm 2.1mm}.repeat-body{padding:2.1mm}.repeat-title,.repeat-code{font-size:7.7pt}.repeat-empty{display:none!important}
.kpis{grid-template-columns:repeat(5,minmax(0,1fr));gap:2mm}.kpi{padding:2mm}.kpi .v{font-size:12.2pt}.kpi .l{font-size:7.2pt}.metric-grid{grid-template-columns:repeat(4,minmax(0,1fr));gap:2mm}.metric{padding:2mm}.metric label,.metric .unit span{font-size:7.2pt}
.summary-box{break-inside:avoid;page-break-inside:avoid;padding:2mm}.footer-note{font-size:7.2pt;margin-top:3mm}
}
.print-value{display:none}
</style>
<script src="https://cdn.sheetjs.com/xlsx-0.20.3/package/dist/xlsx.full.min.js"></script>
</head>
<body>
<div class="app">
<div class="top-frame">
<header class="header">
<div id="logoBox" class="logo-box" role="button" tabindex="0" aria-label="Logoyu değiştirmek için beş kez tıklayın" title="logo.jpg varsa gösterilir. Değiştirmek için 5 kez art arda tıklayın.">
<img id="headerLogo" src="logo.jpg" alt="Logo" onerror="this.style.display='none';document.getElementById('logoFallback').style.display='block'">
<div id="logoFallback" class="logo-fallback" style="display:none">KURUM<br>LOGOSU</div>
</div>
<div class="headerTitleBlock">
<div class="title-main">Siber Tatbikat Tasarım ve Aksiyon Takip Formu</div>
<div class="title-sub">(Senaryo, katılımcılar, karar noktaları, gözlemci notları ve tatbikat sonrası sorumlu/tarihli aksiyonların yönetimi)</div>
</div>
<div id="orgTitle" class="org-title" title="Düzenlemek için art arda 5 kez tıklayın">OLGUN BAŞKANLIĞI</div>
</header>
<nav class="toolbar no-print" aria-label="Form işlemleri">
<button type="button" class="excel-export" onclick="exportExcel()">Excel Dışarı Aktar</button>
<label class="button-like excel-import" for="excelFile">Excel İçeri Aktar</label>
<input id="excelFile" type="file" accept=".xlsx,.xls,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel" class="hidden" onchange="importExcel(event)">
<button type="button" onclick="window.print()" title="PDF olarak kaydetmek veya yazdırmak için kullanın.">PDF / Yazdır</button>
<div class="spacer"></div>
<div id="saveState" class="statusline">Form hazır</div>
</nav>
</div>
<input id="logoFile" type="file" accept="image/png,image/jpeg,image/webp" class="hidden" onchange="changeLogo(event)">
<section class="section">
<div class="section-title"><span>1. Tatbikat Kimlik ve Planlama Bilgileri</span><small>Tatbikatın kimliği, takvimi, yönetimi ve temel sınıflandırması</small></div>
<div class="section-body">
<div class="grid g5">
<div class="field"><label>Tatbikat No</label><input id="exerciseNo" placeholder="Örn. ST-2026-001"></div>
<div class="field span2"><label>Tatbikat Adı</label><input id="exerciseName" placeholder="Tatbikatın kısa ve ayırt edici adı"></div>
<div class="field"><label>Tatbikat Türü</label><select id="exerciseType"><option value=""></option><option>Masa Başı / Tabletop</option><option>Teknik Tatbikat</option><option>Red Team / Blue Team</option><option>Purple Team</option><option>Kriz Yönetimi</option><option>İş Sürekliliği / Felaket Kurtarma</option><option>Sosyal Mühendislik</option><option>Karma Tatbikat</option></select></div>
<div class="field"><label>Durum</label><select id="exerciseStatus"><option value=""></option><option>Taslak</option><option>Planlandı</option><option>Devam Ediyor</option><option>Tamamlandı</option><option>İptal</option></select></div>
<div class="field"><label>Gizlilik Derecesi</label><select id="classification"><option value=""></option><option>Kurum İçi</option><option>Hizmete Özel</option><option>Gizli</option><option>Diğer</option></select></div>
<div class="field"><label>Planlanan Tarih / Saat</label><input id="plannedDateTime" type="datetime-local"></div>
<div class="field"><label>Başlangıç Tarihi / Saati</label><input id="actualStart" type="datetime-local"></div>
<div class="field"><label>Bitiş Tarihi / Saati</label><input id="actualEnd" type="datetime-local"></div>
<div class="field"><label>Tatbikat Süresi</label><input id="exerciseDuration" class="readonly" readonly placeholder="Otomatik hesaplanır"></div>
<div class="field"><label>Uygulama Şekli</label><select id="exerciseMode"><option value=""></option><option>Fiziksel</option><option>Çevrim İçi</option><option>Hibrit</option></select></div>
<div class="field span2"><label>Lokasyon / Ortam</label><input id="location" placeholder="Yer, toplantı alanı, laboratuvar veya çevrim içi ortam"></div>
<div class="field"><label>Tatbikat Yöneticisi</label><input id="exerciseManager" placeholder="Ad-soyad / unvan"></div>
<div class="field"><label>Koordinatör</label><input id="coordinator" placeholder="Ad-soyad / birim"></div>
<div class="field"><label>Kontrol Ekibi Sorumlusu</label><input id="controlLead" placeholder="Ad-soyad / birim"></div>
</div>
</div>
</section>
<section class="section">
<div class="section-title"><span>2. Amaç, Kapsam ve Başarı Çerçevesi</span><small>Neyi test edeceğinizi, neyi ölçmeyeceğinizi ve başarıyı nasıl değerlendireceğinizi tanımlayın</small></div>
<div class="section-body">
<div class="grid g3">
<div class="field"><label>Tatbikatın Amacı</label><textarea id="purpose" class="tall" placeholder="Ana amaç ve beklenen kurumsal fayda"></textarea></div>
<div class="field"><label>Ölçülecek Kabiliyetler</label><textarea id="capabilities" class="tall" placeholder="Tespit, analiz, izolasyon, kriz yönetimi, iletişim vb."></textarea></div>
<div class="field"><label>Beklenen Çıktılar</label><textarea id="expectedOutputs" class="tall" placeholder="Beklenen rapor, karar, iyileştirme veya doğrulamalar"></textarea></div>
<div class="field"><label>Test Edilecek Süreç / Prosedürler</label><textarea id="processes" placeholder="Olay müdahale, eskalasyon, BCP/DR, iletişim vb."></textarea></div>
<div class="field"><label>Dahil Edilen Birim / Ekipler</label><textarea id="includedUnits" placeholder="SOC, CSIRT, sistem, ağ, hukuk, iletişim vb."></textarea></div>
<div class="field"><label>Kapsam Dışı Alanlar</label><textarea id="outOfScope" placeholder="Tatbikatta test edilmeyecek sistem, süreç veya birimler"></textarea></div>
<div class="field"><label>Dahil Edilen Sistem / Hizmetler</label><textarea id="includedSystems" placeholder="Kritik sistem, uygulama, sunucu, ağ, bulut servisleri"></textarea></div>
<div class="field"><label>Üçüncü Taraf / Tedarikçiler</label><textarea id="thirdParties" placeholder="Tatbikata dahil edilen veya bağımlı dış taraflar"></textarea></div>
<div class="field"><label>Genel Başarı Kriterleri</label><textarea id="successFramework" placeholder="Tatbikat genelinde başarılı sayılma ölçütleri"></textarea></div>
</div>
</div>
</section>
<section class="section">
<div class="section-title"><span>3. Ana Senaryo Tasarımı</span><small>Tehdit aktörü, saldırı vektörü, başlangıç durumu ve beklenen etki</small></div>
<div class="section-body">
<div class="grid g4">
<div class="field span2"><label>Senaryo Başlığı</label><input id="scenarioTitle" placeholder="Senaryonun kısa başlığı"></div>
<div class="field"><label>Tehdit Aktörü / Profil</label><input id="threatActor" placeholder="İç tehdit, suç grubu, APT, bilinmeyen vb."></div>
<div class="field"><label>Tehdit Aktörünün Amacı</label><input id="threatObjective" placeholder="Veri sızdırma, kesinti, finansal kazanç vb."></div>
<div class="field span2"><label>Senaryo Özeti</label><textarea id="scenarioSummary" class="tall" placeholder="Tatbikat senaryosunun uçtan uca özeti"></textarea></div>
<div class="field"><label>Başlangıç Durumu</label><textarea id="initialState" placeholder="Tatbikat başlarken sistemlerin ve ekiplerin durumu"></textarea></div>
<div class="field"><label>İlk Erişim Yöntemi</label><textarea id="initialAccess" placeholder="Kimlik avı, zafiyet istismarı, üçüncü taraf vb."></textarea></div>
<div class="field"><label>Saldırı Vektörü</label><textarea id="attackVector" placeholder="Kullanılacak teknik/yöntemler"></textarea></div>
<div class="field"><label>Etkilenen Sistem / Hizmet</label><textarea id="affectedServices" placeholder="Öncelikli hedefler ve bağımlılıklar"></textarea></div>
<div class="field"><label>Olası İş Etkisi</label><textarea id="businessImpact" placeholder="Operasyonel, finansal, itibari, hukuki etki"></textarea></div>
<div class="field"><label>Veri Kaybı / Sızıntı Senaryosu</label><textarea id="dataLossScenario" placeholder="Varsa veri etkisi ve kapsamı"></textarea></div>
<div class="field"><label>Servis Kesintisi Senaryosu</label><textarea id="serviceLossScenario" placeholder="Varsa hizmet kesintisi ve kritik eşikler"></textarea></div>
<div class="field"><label>Senaryo Varsayımları</label><textarea id="assumptions" placeholder="Tatbikatın kabul ettiği varsayımlar"></textarea></div>
<div class="field"><label>Senaryo Kısıtları</label><textarea id="constraints" placeholder="Güvenlik, zaman, erişim, üretim etkisi vb."></textarea></div>
<div class="field span2"><label>Gerçek Olay / Tatbikat Ayrım Yöntemi</label><textarea id="realEventSeparation" placeholder="Gerçek bir olay yaşanırsa tatbikatın nasıl durdurulacağı ve ayrıştırılacağı"></textarea></div>
</div>
</div>
</section>
<section class="section">
<div class="section-title"><span>4. Katılımcılar ve Roller</span><small>Katılımcı, birim, tatbikat rolü ve karar yetkisini kayıt altına alın</small></div>
<div class="section-body">
<div class="section-tools no-print"><button class="add" type="button" onclick="addItem('participants')">+ Katılımcı Ekle</button><span class="note">Katılımcı sayısı ihtiyaca göre artırılabilir.</span></div>
<div id="participantsList" class="repeat-list"></div>
</div>
</section>
<section class="section">
<div class="section-title"><span>5. Senaryo Akışı / Inject Yönetimi</span><small>Planlanan gelişmeleri, hedeflenen davranışı ve gerçekleşen tepkiyi zaman çizgisinde yönetin</small></div>
<div class="section-body">
<div class="section-tools no-print"><button class="add" type="button" onclick="addItem('injects')">+ Inject Ekle</button><span class="note">Her inject için benzersiz numara otomatik üretilir.</span></div>
<div id="injectsList" class="repeat-list"></div>
</div>
</section>
<section class="section">
<div class="section-title"><span>6. Karar Noktaları</span><small>Hangi bilginin hangi kararı tetiklediğini, kararı kimin verdiğini ve gerekçesini kaydedin</small></div>
<div class="section-body">
<div class="section-tools no-print"><button class="add" type="button" onclick="addItem('decisions')">+ Karar Noktası Ekle</button></div>
<div id="decisionsList" class="repeat-list"></div>
</div>
</section>
<section class="section">
<div class="section-title"><span>7. Gözlemci Notları</span><small>Olumlu uygulamaları, eksiklikleri, riskleri ve önerileri kanıtlarıyla kaydedin</small></div>
<div class="section-body">
<div class="section-tools no-print"><button class="add" type="button" onclick="addItem('observations')">+ Gözlem Ekle</button></div>
<div id="observationsList" class="repeat-list"></div>
</div>
</section>
<section class="section">
<div class="section-title"><span>8. Performans Ölçümleri ve Başarı Kriterleri</span><small>Zaman metriklerini ve ölçülebilir başarı kriterlerini birlikte izleyin</small></div>
<div class="section-body">
<div class="metric-grid">
<div class="metric"><label>Olayı Fark Etme Süresi</label><div class="unit"><input id="detectTime" type="number" min="0" step="1" placeholder="0"><span>dakika</span></div></div>
<div class="metric"><label>İlk Bildirim Süresi</label><div class="unit"><input id="notifyTime" type="number" min="0" step="1" placeholder="0"><span>dakika</span></div></div>
<div class="metric"><label>Eskalasyon Süresi</label><div class="unit"><input id="escalationTime" type="number" min="0" step="1" placeholder="0"><span>dakika</span></div></div>
<div class="metric"><label>Karar Alma Süresi</label><div class="unit"><input id="decisionTime" type="number" min="0" step="1" placeholder="0"><span>dakika</span></div></div>
<div class="metric"><label>Müdahaleye Başlama</label><div class="unit"><input id="responseStartTime" type="number" min="0" step="1" placeholder="0"><span>dakika</span></div></div>
<div class="metric"><label>İzolasyon Süresi</label><div class="unit"><input id="containmentTime" type="number" min="0" step="1" placeholder="0"><span>dakika</span></div></div>
<div class="metric"><label>Kurtarma Süresi</label><div class="unit"><input id="recoveryTime" type="number" min="0" step="1" placeholder="0"><span>dakika</span></div></div>
<div class="metric"><label>Toplam Müdahale Süresi</label><div class="unit"><input id="totalResponseTime" type="number" min="0" step="1" placeholder="0"><span>dakika</span></div></div>
</div>
<div class="section-tools no-print" style="margin-top:9px"><button class="add" type="button" onclick="addItem('criteria')">+ Başarı Kriteri Ekle</button></div>
<div id="criteriaList" class="repeat-list"></div>
</div>
</section>
<section class="section">
<div class="section-title"><span>9. Tespit Edilen Bulgular</span><small>Teknik, süreç, insan, organizasyon, iletişim ve dokümantasyon bulgularını aksiyonlara bağlayın</small></div>
<div class="section-body">
<div class="section-tools no-print"><button class="add" type="button" onclick="addItem('findings')">+ Bulgu Ekle</button></div>
<div id="findingsList" class="repeat-list"></div>
</div>
</section>
<section class="section">
<div class="section-title"><span>10. Tatbikat Sonrası Aksiyon Takibi</span><small>Her aksiyon için sorumlu, hedef tarih, ilerleme, kanıt ve kapanış bilgisini yönetin</small></div>
<div class="section-body">
<div class="kpis">
<div class="kpi"><div id="kpiOpen" class="v">0</div><div class="l">Açık / Devam Eden</div></div>
<div class="kpi danger"><div id="kpiHigh" class="v">0</div><div class="l">Kritik / Yüksek Öncelik</div></div>
<div class="kpi warn"><div id="kpiOverdue" class="v">0</div><div class="l">Hedef Tarihi Geçen</div></div>
<div class="kpi good"><div id="kpiClosed" class="v">0</div><div class="l">Tamamlanan</div></div>
<div class="kpi"><div id="kpiProgress" class="v">0%</div><div class="l">Ortalama İlerleme</div></div>
</div>
<div class="section-tools no-print"><button class="add" type="button" onclick="addItem('actions')">+ Aksiyon Ekle</button><span class="note">Gecikme ve kapanış durumu otomatik özetlenir.</span></div>
<div id="actionsList" class="repeat-list"></div>
</div>
</section>
<section class="section">
<div class="section-title"><span>11. Tatbikat Sonuç Değerlendirmesi ve Öğrenilmiş Dersler</span><small>Tatbikattan çıkan güçlü yönleri, iyileştirme alanlarını ve kurumsal öğrenimi kaydedin</small></div>
<div class="section-body">
<div class="grid g3">
<div class="field"><label>Güçlü Yönler</label><textarea id="strengths" class="tall" placeholder="İyi çalışan süreç, ekip, iletişim veya teknik kontroller"></textarea></div>
<div class="field"><label>İyileştirme Alanları</label><textarea id="improvementAreas" class="tall" placeholder="Süreç, teknik, insan, yetki, eğitim veya dokümantasyon eksikleri"></textarea></div>
<div class="field"><label>Öğrenilmiş Dersler</label><textarea id="lessonsLearned" class="tall" placeholder="Ne iyi çalıştı, ne çalışmadı, ne farklı yapılmalıydı?"></textarea></div>
<div class="field"><label>Güncellenecek Doküman / Prosedürler</label><textarea id="documentsToUpdate" placeholder="IR planı, kriz planı, iletişim planı, playbook vb."></textarea></div>
<div class="field"><label>Eğitim / Farkındalık İhtiyacı</label><textarea id="trainingNeeds" placeholder="Rol bazlı eğitim veya tatbikat ihtiyacı"></textarea></div>
<div class="field"><label>Yeni Araç / Teknoloji İhtiyacı</label><textarea id="technologyNeeds" placeholder="SIEM, EDR, SOAR, iletişim, yedekleme vb."></textarea></div>
<div class="field span3"><label>Genel Değerlendirme</label><textarea id="overallAssessment" class="tall" placeholder="Tatbikat amacı, süreçler, teknik kabiliyetler, iletişim ve karar mekanizmalarının genel değerlendirmesi"></textarea></div>
</div>
</div>
</section>
<section class="section">
<div class="section-title"><span>12. Yönetici Özeti, Onay ve Kapanış</span><small>Tatbikat sonucunu karar verilebilir kısa özete dönüştürün ve kapanışı kayıt altına alın</small></div>
<div class="section-body">
<div class="section-tools no-print"><button class="add" type="button" onclick="buildExecutiveSummary()">Yönetici Özetini Oluştur / Güncelle</button><span class="note">Otomatik üretilen metin daha sonra manuel düzenlenebilir.</span></div>
<div class="field"><label>Yönetici Özeti</label><textarea id="executiveSummary" class="tall" style="min-height:145px" placeholder="Tatbikatın kapsamı, önemli bulgular, aksiyon durumu ve yönetim gerektiren konular"></textarea></div>
<div class="grid g4" style="margin-top:8px">
<div class="field"><label>Tatbikat Yöneticisi</label><input id="approvalExerciseManager" placeholder="Ad-soyad / unvan"></div>
<div class="field"><label>Siber Güvenlik Yöneticisi</label><input id="approvalCyberManager" placeholder="Ad-soyad / unvan"></div>
<div class="field"><label>Üst Yönetim / Onay Makamı</label><input id="approvalExecutive" placeholder="Ad-soyad / unvan"></div>
<div class="field"><label>Değerlendirme Tarihi</label><input id="evaluationDate" type="date"></div>
<div class="field"><label>Kapanış Tarihi</label><input id="closureDate" type="date"></div>
<div class="field"><label>Tatbikat Sonuç Durumu</label><select id="finalResult"><option value=""></option><option>Başarılı</option><option>Kısmen Başarılı</option><option>Başarısız</option><option>Ek Çalışma Gerekli</option></select></div>
<div class="field"><label>Sonraki Tatbikat İçin Önerilen Tarih</label><input id="nextExerciseDate" type="date"></div>
<div class="field"><label>Kapanış Onayı / Referansı</label><input id="closureReference" placeholder="Karar, toplantı, doküman veya kayıt referansı"></div>
<div class="field span4"><label>Kapanış Notu</label><textarea id="closureNote" placeholder="Kapanış koşulları, açık kalan hususlar ve takip yöntemi"></textarea></div>
</div>
</div>
</section>
<div class="footer-note">Tatbikat kayıtları gerçek olay kayıtlarından açık şekilde ayrıştırılmalı; üretim sistemlerinde uygulanacak teknik adımlar kurumun değişiklik, olay müdahale ve yetkilendirme prosedürleriyle uyumlu yürütülmelidir.</div>
</div>
<script>
const $=id=>document.getElementById(id);
const fixedFieldIds=[
"exerciseNo","exerciseName","exerciseType","exerciseStatus","classification","plannedDateTime","actualStart","actualEnd","exerciseDuration","exerciseMode","location","exerciseManager","coordinator","controlLead",
"purpose","capabilities","expectedOutputs","processes","includedUnits","outOfScope","includedSystems","thirdParties","successFramework",
"scenarioTitle","threatActor","threatObjective","scenarioSummary","initialState","initialAccess","attackVector","affectedServices","businessImpact","dataLossScenario","serviceLossScenario","assumptions","constraints","realEventSeparation",
"detectTime","notifyTime","escalationTime","decisionTime","responseStartTime","containmentTime","recoveryTime","totalResponseTime",
"strengths","improvementAreas","lessonsLearned","documentsToUpdate","trainingNeeds","technologyNeeds","overallAssessment","executiveSummary",
"approvalExerciseManager","approvalCyberManager","approvalExecutive","evaluationDate","closureDate","finalResult","nextExerciseDate","closureReference","closureNote"
];
const specs={
participants:{prefix:"KAT",title:"Katılımcı",sheet:"Katılımcılar",fields:[
{k:"name",l:"Adı Soyadı",t:"text",c:1},{k:"unit",l:"Birimi",t:"text",c:1},{k:"job",l:"Görevi",t:"text",c:1},{k:"role",l:"Tatbikattaki Rolü",t:"select",o:["","SOC","CSIRT / CERT","Siber Güvenlik","Sistem","Ağ","Uygulama","Veri Tabanı","Hukuk","KVKK / Gizlilik","Kurumsal İletişim","İş Sürekliliği","Üst Yönetim","İnsan Kaynakları","Tedarikçi","Gözlemci","Tatbikat Kontrol Ekibi","Diğer"]},{k:"decisionAuthority",l:"Karar Yetkisi",t:"text",c:1},{k:"contact",l:"İletişim Bilgisi",t:"text",c:1},{k:"attendance",l:"Katılım Durumu",t:"select",o:["","Planlandı","Katıldı","Kısmi Katılım","Katılmadı"]},{k:"notes",l:"Not",t:"textarea",c:4}
]},
injects:{prefix:"INJ",title:"Inject",sheet:"Injectler",fields:[
{k:"plannedTime",l:"Planlanan Zaman",t:"datetime-local"},{k:"actualTime",l:"Gerçekleşen Zaman",t:"datetime-local"},{k:"target",l:"Hedef Ekip / Kişi",t:"text"},{k:"channel",l:"İletim Yöntemi",t:"select",o:["","E-posta","Telefon","Mesajlaşma","Sözlü","SIEM / Alarm","Ticket","Sistem Ekranı","Medya / Haber","Diğer"]},
{k:"event",l:"Olay / Gelişme",t:"textarea",c:2},{k:"givenInfo",l:"Katılımcıya Verilen Bilgi",t:"textarea",c:2},{k:"expectedAction",l:"Beklenen Davranış / Karar",t:"textarea",c:2},{k:"actualResponse",l:"Gerçekleşen Davranış / Karar",t:"textarea",c:2},{k:"nextTrigger",l:"Sonraki Inject Tetikleyicisi",t:"textarea",c:2},{k:"managerNote",l:"Tatbikat Yöneticisi Notu",t:"textarea",c:2}
]},
decisions:{prefix:"KAR",title:"Karar Noktası",sheet:"Karar Noktaları",fields:[
{k:"relatedInject",l:"İlgili Inject No",t:"text"},{k:"decisionDateTime",l:"Tarih / Saat",t:"datetime-local"},{k:"decisionMaker",l:"Kararı Veren Kişi / Makam",t:"text"},{k:"decisionDuration",l:"Karar Süresi (dakika)",t:"number"},
{k:"trigger",l:"Kararı Gerektiren Olay",t:"textarea",c:2},{k:"question",l:"Karar Sorusu",t:"textarea",c:2},{k:"availableInfo",l:"Mevcut Bilgiler",t:"textarea",c:2},{k:"options",l:"Seçenekler",t:"textarea",c:2},{k:"decision",l:"Alınan Karar",t:"textarea",c:2},{k:"rationale",l:"Kararın Gerekçesi",t:"textarea",c:2},{k:"expectedDecision",l:"Beklenen Karar",t:"textarea",c:2},{k:"evaluation",l:"Değerlendirme Notu",t:"textarea",c:2}
]},
observations:{prefix:"GOZ",title:"Gözlem",sheet:"Gözlemler",fields:[
{k:"observer",l:"Gözlemci",t:"text"},{k:"dateTime",l:"Tarih / Saat",t:"datetime-local"},{k:"team",l:"İlgili Ekip",t:"text"},{k:"relatedRef",l:"İlgili Inject / Karar",t:"text"},
{k:"observation",l:"Gözlem",t:"textarea",c:2},{k:"positive",l:"Olumlu Uygulama",t:"textarea",c:2},{k:"deficiency",l:"Problem / Eksiklik",t:"textarea",c:2},{k:"risk",l:"Risk / Etki",t:"textarea",c:2},{k:"recommendation",l:"Öneri",t:"textarea",c:2},{k:"evidence",l:"Kanıt / Açıklama",t:"textarea",c:2}
]},
criteria:{prefix:"KR",title:"Başarı Kriteri",sheet:"Başarı Kriterleri",fields:[
{k:"criterion",l:"Kriter",t:"textarea",c:2},{k:"target",l:"Hedef",t:"text"},{k:"actual",l:"Gerçekleşen",t:"text"},{k:"result",l:"Sonuç",t:"select",o:["","Başarılı","Kısmen Başarılı","Başarısız","Ölçülemedi"]},{k:"evidence",l:"Açıklama / Kanıt",t:"textarea",c:2}
]},
findings:{prefix:"BLG",title:"Bulgu",sheet:"Bulgular",fields:[
{k:"title",l:"Bulgu Başlığı",t:"text",c:2},{k:"type",l:"Bulgu Türü",t:"select",o:["","Teknik","Süreç","İnsan","Organizasyon","İletişim","Dokümantasyon","Tedarikçi"]},{k:"riskLevel",l:"Risk Seviyesi",t:"select",o:["","Kritik","Yüksek","Orta","Düşük","Bilgi"]},{k:"relatedRef",l:"İlgili Inject / Karar / Gözlem",t:"text"},
{k:"description",l:"Açıklama",t:"textarea",c:2},{k:"rootCause",l:"Kök Neden",t:"textarea",c:2},{k:"recommendation",l:"Önerilen İyileştirme",t:"textarea",c:2},{k:"evidence",l:"Kanıt",t:"textarea",c:2}
]},
actions:{prefix:"AKS",title:"Aksiyon",sheet:"Aksiyonlar",fields:[
{k:"relatedFinding",l:"İlgili Bulgu No",t:"text"},{k:"title",l:"Aksiyon Başlığı",t:"text",c:2},{k:"priority",l:"Öncelik",t:"select",o:["","Kritik","Yüksek","Orta","Düşük"]},{k:"owner",l:"Sorumlu Kişi",t:"text"},{k:"unit",l:"Sorumlu Birim",t:"text"},{k:"supportUnit",l:"Destekleyen Birim",t:"text"},
{k:"openDate",l:"Açılış Tarihi",t:"date"},{k:"targetDate",l:"Hedef Tamamlanma Tarihi",t:"date"},{k:"completedDate",l:"Gerçek Tamamlanma Tarihi",t:"date"},{k:"status",l:"Durum",t:"select",o:["","Açık","Devam Ediyor","Beklemede","Tamamlandı","Risk Kabulü","İptal"]},{k:"progress",l:"Tamamlanma Oranı (%)",t:"number",min:0,max:100},{k:"verificationRequired",l:"Tekrar Test",t:"select",o:["","Gerekli","Gerekli Değil","Planlandı","Tamamlandı"]},
{k:"work",l:"Yapılacak İş",t:"textarea",c:2},{k:"evidence",l:"Kapanış Kanıtı / Referansı",t:"textarea",c:2},{k:"delayReason",l:"Gecikme / Bekleme Nedeni",t:"textarea",c:2},{k:"compensatingControl",l:"Telafi Edici Kontrol / Risk Kabul Notu",t:"textarea",c:2},{k:"verifiedBy",l:"Doğrulayan Kişi",t:"text"},{k:"verificationDate",l:"Doğrulama Tarihi",t:"date"},{k:"closureNote",l:"Kapanış Notu",t:"textarea",c:2}
]}
};
const counters={participants:0,injects:0,decisions:0,observations:0,criteria:0,findings:0,actions:0};
function escapeHtml(v){return String(v??"").replace(/[&<>'"]/g,c=>({"&":"&","<":"<",">":">","'":"'",'"':"""}[c]));}
function newCode(name){counters[name]++;return `${specs[name].prefix}-${String(counters[name]).padStart(3,"0")}`;}
function adjustCounterFromCode(name,code){const n=parseInt(String(code||"").split("-").pop(),10);if(Number.isFinite(n)&&n>counters[name])counters[name]=n;}
function fieldHtml(f,value=""){
const span=f.c||1;const cls=`field${span>1?` span${span}`:""}`;const val=value??"";
if(f.t==="textarea")return `<div class="${cls}"><label>${f.l}</label><textarea data-key="${f.k}" placeholder="">${escapeHtml(val)}</textarea></div>`;
if(f.t==="select")return `<div class="${cls}"><label>${f.l}</label><select data-key="${f.k}">${f.o.map(o=>`<option${String(o)===String(val)?" selected":""}>${escapeHtml(o)}</option>`).join("")}</select></div>`;
const min=f.min!==undefined?` min="${f.min}"`:"",max=f.max!==undefined?` max="${f.max}"`:"";
return `<div class="${cls}"><label>${f.l}</label><input data-key="${f.k}" type="${f.t||"text"}" value="${escapeHtml(val)}"${min}${max}></div>`;
}
function addItem(name,data={}){
const spec=specs[name],container=$(name+"List");if(!spec||!container)return;
container.querySelector(".repeat-empty")?.remove();
const code=data.code||newCode(name);adjustCounterFromCode(name,code);
const card=document.createElement("div");card.className="repeat-card";card.dataset.collection=name;card.dataset.code=code;
card.innerHTML=`<div class="repeat-head"><span class="repeat-title">${spec.title}</span><span class="repeat-code">${escapeHtml(code)}</span><div class="spacer"></div><button type="button" class="danger no-print" onclick="removeItem(this)">Kaldır</button></div><div class="repeat-body"><div class="grid g4">${spec.fields.map(f=>fieldHtml(f,data[f.k])).join("")}</div></div>`;
container.appendChild(card);card.querySelectorAll("textarea").forEach(autoGrow);markChanged();updateActionKpis();return card;
}
function removeItem(btn){const card=btn.closest(".repeat-card");const name=card?.dataset.collection;if(!card)return;card.remove();ensureEmpty(name);markChanged();updateActionKpis();}
function ensureEmpty(name){const c=$(name+"List");if(c&&!c.querySelector(".repeat-card"))c.innerHTML=`<div class="repeat-empty">Henüz kayıt eklenmedi.</div>`;}
function collectCollection(name){return [...$(name+"List").querySelectorAll(".repeat-card")].map(card=>{const row={code:card.dataset.code};card.querySelectorAll("[data-key]").forEach(el=>row[el.dataset.key]=el.value);return row;});}
function clearCollection(name){$(name+"List").innerHTML="";counters[name]=0;ensureEmpty(name);}
function applyCollection(name,rows){clearCollection(name);(rows||[]).forEach(r=>addItem(name,r));ensureEmpty(name);}
function autoGrow(el){if(!el||el.tagName!=="TEXTAREA")return;el.style.height="auto";el.style.height=Math.max(el.scrollHeight,66)+"px";}
function markChanged(){if($("saveState"))$("saveState").textContent="Kaydedilmemiş değişiklikler";}
function calcDuration(){const s=$("actualStart").value,e=$("actualEnd").value;if(!s||!e){$("exerciseDuration").value="";return}const ms=new Date(e)-new Date(s);if(ms<0){$("exerciseDuration").value="Bitiş başlangıçtan önce";return}const total=Math.round(ms/60000),h=Math.floor(total/60),m=total%60;$("exerciseDuration").value=`${h} saat ${m} dakika`;}
function todayISO(){const d=new Date();const off=d.getTimezoneOffset();return new Date(d.getTime()-off*60000).toISOString().slice(0,10);}
function updateActionKpis(){
const rows=collectCollection("actions").filter(r=>Object.values(r).some(v=>String(v||"").trim()));
const active=rows.filter(r=>!["Tamamlandı","İptal"].includes(r.status));
const high=active.filter(r=>["Kritik","Yüksek"].includes(r.priority)).length;
const overdue=active.filter(r=>r.targetDate&&r.targetDate<todayISO()).length;
const closed=rows.filter(r=>r.status==="Tamamlandı").length;
const progressVals=rows.map(r=>Number(r.progress)).filter(Number.isFinite);const avg=progressVals.length?Math.round(progressVals.reduce((a,b)=>a+b,0)/progressVals.length):0;
$("kpiOpen").textContent=active.length;$("kpiHigh").textContent=high;$("kpiOverdue").textContent=overdue;$("kpiClosed").textContent=closed;$("kpiProgress").textContent=avg+"%";
}
function formatDateTime(v){if(!v)return"";const d=new Date(v);if(Number.isNaN(d.getTime()))return v;return d.toLocaleString("tr-TR",{dateStyle:"short",timeStyle:"short"});}
function buildExecutiveSummary(){
const findings=collectCollection("findings").filter(r=>r.title||r.description),actions=collectCollection("actions").filter(r=>r.title||r.work);
const crit=findings.filter(r=>r.riskLevel==="Kritik").length,high=findings.filter(r=>r.riskLevel==="Yüksek").length;
const open=actions.filter(r=>!["Tamamlandı","İptal"].includes(r.status)).length,overdue=actions.filter(r=>!["Tamamlandı","İptal"].includes(r.status)&&r.targetDate&&r.targetDate<todayISO()).length;
const criteria=collectCollection("criteria").filter(r=>r.criterion);const successful=criteria.filter(r=>r.result==="Başarılı").length;
const parts=[];
if($("exerciseName").value)parts.push(`Tatbikat: ${$("exerciseName").value}${$("exerciseNo").value?` (${ $("exerciseNo").value })`:""}.`);
if($("purpose").value)parts.push(`Amaç: ${$("purpose").value}`);
if($("scenarioTitle").value)parts.push(`Ana senaryo: ${$("scenarioTitle").value}.`);
if($("actualStart").value||$("plannedDateTime").value)parts.push(`Tarih: ${formatDateTime($("actualStart").value||$("plannedDateTime").value)}${$("exerciseDuration").value?`; süre: ${$("exerciseDuration").value}`:""}.`);
if(findings.length)parts.push(`Toplam ${findings.length} bulgu kaydedildi; ${crit} kritik, ${high} yüksek seviyededir.`);
if(criteria.length)parts.push(`${criteria.length} başarı kriterinin ${successful} adedi "Başarılı" olarak değerlendirildi.`);
if(actions.length)parts.push(`${actions.length} aksiyon tanımlandı; ${open} aksiyon açık/devam eden durumda, ${overdue} aksiyonun hedef tarihi geçmiştir.`);
if($("strengths").value)parts.push(`Güçlü yönler: ${$("strengths").value}`);
if($("improvementAreas").value)parts.push(`Öncelikli iyileştirme alanları: ${$("improvementAreas").value}`);
if($("overallAssessment").value)parts.push(`Genel değerlendirme: ${$("overallAssessment").value}`);
$("executiveSummary").value=parts.join("\n\n");autoGrow($("executiveSummary"));markChanged();
}
function clearPrintValues(){document.querySelectorAll(".print-value").forEach(n=>n.remove());}
function buildPrintValues(){
clearPrintValues();
document.querySelectorAll("input:not([type=hidden]):not([type=file]),select,textarea").forEach(el=>{
if(el.closest(".toolbar"))return;
const pv=document.createElement("div");pv.className="print-value";
let val="";
if(el.tagName==="SELECT"){const opt=el.options[el.selectedIndex];val=opt?opt.text:"";}else{val=el.value||"";}
if(!String(val).trim())pv.classList.add("empty");
pv.textContent=String(val||" ");
el.insertAdjacentElement("afterend",pv);
});
}
window.addEventListener("beforeprint",()=>{buildPrintValues();updateActionKpis();});
window.addEventListener("afterprint",clearPrintValues);
document.addEventListener("input",e=>{if(e.target.tagName==="TEXTAREA")autoGrow(e.target);if(e.target.id==="actualStart"||e.target.id==="actualEnd")calcDuration();if(e.target.closest("#actionsList"))updateActionKpis();markChanged();});
document.addEventListener("change",e=>{if(e.target.id==="actualStart"||e.target.id==="actualEnd")calcDuration();if(e.target.closest("#actionsList"))updateActionKpis();markChanged();});
function fieldCategory(el){const section=el.closest(".section");const title=section?.querySelector(".section-title span");return title?title.textContent.trim():"Genel";}
function fieldLabel(el){const field=el.closest(".field");const label=field?.querySelector("label");return label?label.textContent.trim():(el.id||"Alan");}
function collectFixed(){const d={};fixedFieldIds.forEach(id=>{const el=$(id);if(el)d[id]=el.value});d.orgTitle=$("orgTitle").textContent.trim();return d;}
function applyFixed(data={}){fixedFieldIds.forEach(id=>{if(data[id]!==undefined&&$(id)&&id!=="exerciseDuration")$(id).value=data[id]??""});if(data.orgTitle)$("orgTitle").textContent=data.orgTitle;calcDuration();document.querySelectorAll("textarea").forEach(autoGrow);}
function ensureExcelLibrary(){if(typeof XLSX==="undefined"){alert("Excel kütüphanesi yüklenemedi. Excel içe/dışa aktarma için internet bağlantısını kontrol edip sayfayı yeniden açın.");return false}return true;}
function setSheetPrint(ws){ws["!pageSetup"]={orientation:"landscape",paperSize:9,fitToWidth:1,fitToHeight:0};ws["!margins"]={left:0.25,right:0.25,top:0.35,bottom:0.45,header:0.15,footer:0.2};}
function sheetFromRows(rows,widths){const ws=XLSX.utils.aoa_to_sheet(rows);ws["!cols"]=widths.map(w=>({wch:w}));if(rows.length>1)ws["!autofilter"]={ref:`A1:${XLSX.utils.encode_col(rows[0].length-1)}${rows.length}`};setSheetPrint(ws);return ws;}
function exportExcel(){
if(!ensureExcelLibrary())return;const wb=XLSX.utils.book_new();
const general=[["Kategori","Alan ID","Alan","Değer"],["Başlık","orgTitle","Kurum / Başkanlık Başlığı",$("orgTitle").textContent.trim()]];
fixedFieldIds.forEach(id=>{const el=$(id);if(el)general.push([fieldCategory(el),id,fieldLabel(el),el.value])});
XLSX.utils.book_append_sheet(wb,sheetFromRows(general,[38,28,42,90]),"Genel Form");
Object.entries(specs).forEach(([name,spec])=>{const data=collectCollection(name);const heads=["Kayıt No",...spec.fields.map(f=>f.l)];const rows=[heads,...data.map(r=>[r.code,...spec.fields.map(f=>r[f.k]??"")])];XLSX.utils.book_append_sheet(wb,sheetFromRows(rows,[14,...spec.fields.map(f=>f.t==="textarea"?42:22)]),spec.sheet.slice(0,31));});
XLSX.writeFile(wb,"Siber Tatbikat Tasarım ve Aksiyon Takip.xlsx");$("saveState").textContent="Excel dosyası dışarı aktarıldı";
}
function excelCell(v){if(v===null||v===undefined)return"";if(v instanceof Date){const off=v.getTimezoneOffset();return new Date(v.getTime()-off*60000).toISOString().slice(0,16)}return String(v).trim();}
function parseDynamicSheet(ws,spec){if(!ws)return[];const rows=XLSX.utils.sheet_to_json(ws,{defval:"",raw:false});return rows.map(row=>{const o={code:excelCell(row["Kayıt No"])};spec.fields.forEach(f=>o[f.k]=excelCell(row[f.l]));return o}).filter(r=>r.code||spec.fields.some(f=>r[f.k]));}
function importExcel(e){
const file=e.target.files&&e.target.files[0];if(!file)return;if(!ensureExcelLibrary()){e.target.value="";return}const reader=new FileReader();
reader.onload=ev=>{try{const wb=XLSX.read(new Uint8Array(ev.target.result),{type:"array",cellDates:true});const generalName=wb.SheetNames.includes("Genel Form")?"Genel Form":wb.SheetNames.includes("Risk Kaydı")?"Risk Kaydı":wb.SheetNames[0];const ws=wb.Sheets[generalName];const rows=XLSX.utils.sheet_to_json(ws,{defval:"",raw:true});const fixed={};rows.forEach(row=>{const id=excelCell(row["Alan ID"]),value=row["Değer"];if(id==="orgTitle")fixed.orgTitle=excelCell(value);else if(fixedFieldIds.includes(id))fixed[id]=excelCell(value)});applyFixed(fixed);
Object.entries(specs).forEach(([name,spec])=>{const sname=wb.SheetNames.find(n=>n===spec.sheet.slice(0,31));if(sname)applyCollection(name,parseDynamicSheet(wb.Sheets[sname],spec));else clearCollection(name)});
updateActionKpis();$("saveState").textContent="Excel dosyası içeri aktarıldı";
}catch(err){console.error(err);alert("Excel dosyası okunamadı. Bu formdan dışarı aktarılan .xlsx/.xls yapısını veya Alan ID / Değer kolonlu eski Olgun UI2 yapısını kullanın.");$("saveState").textContent="Excel içeri aktarma başarısız"}finally{e.target.value=""}};reader.readAsArrayBuffer(file);
}
function bindFiveClick(target,action){let count=0,timer=null;target.addEventListener("click",()=>{count++;clearTimeout(timer);timer=setTimeout(()=>count=0,2500);if(count>=5){count=0;clearTimeout(timer);action()}})}
bindFiveClick($("orgTitle"),()=>{$("orgTitle").contentEditable="true";$("orgTitle").classList.add("editing");$("orgTitle").focus();$("saveState").textContent="Kurum başlığı düzenleme açık"});
$("orgTitle").addEventListener("blur",()=>{$("orgTitle").contentEditable="false";$("orgTitle").classList.remove("editing")});$("orgTitle").addEventListener("keydown",e=>{if(e.key==="Enter"){e.preventDefault();$("orgTitle").blur()}});$("orgTitle").addEventListener("input",()=>{const el=$("orgTitle");const clean=el.textContent.replace(/\s*\n+\s*/g," ").replace(/\s{2,}/g," ");if(el.textContent!==clean){el.textContent=clean;const r=document.createRange();r.selectNodeContents(el);r.collapse(false);const s=window.getSelection();s.removeAllRanges();s.addRange(r)}});
bindFiveClick($("logoBox"),()=>{$("logoFile").click();$("saveState").textContent="Logo seçimi açıldı"});$("logoBox").addEventListener("keydown",e=>{if(e.key==="Enter"||e.key===" "){e.preventDefault();$("logoBox").click()}});
function changeLogo(e){const file=e.target.files&&e.target.files[0];if(!file)return;if(!file.type.startsWith("image/")){alert("Lütfen PNG, JPG/JPEG veya WEBP türünde bir logo seçin.");e.target.value="";return}const reader=new FileReader();reader.onload=()=>{const img=$("headerLogo");img.src=reader.result;img.style.display="block";$("logoFallback").style.display="none";try{localStorage.setItem("olgunHeaderLogo",reader.result)}catch(err){}$("saveState").textContent="Logo güncellendi"};reader.readAsDataURL(file);e.target.value="";}
try{const savedLogo=localStorage.getItem("olgunHeaderLogo");if(savedLogo){$("headerLogo").src=savedLogo;$("headerLogo").style.display="block";$("logoFallback").style.display="none"}}catch(err){}
Object.keys(specs).forEach(ensureEmpty);document.querySelectorAll("textarea").forEach(autoGrow);calcDuration();updateActionKpis();$("saveState").textContent="Form hazır";
</script>
</body>
</html>







































