User Tools

Site Tools


handleiding_nieuw:sub_spacematrix

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
handleiding_nieuw:sub_spacematrix [2025/05/07 08:46] supporthandleiding_nieuw:sub_spacematrix [2025/05/19 10:26] (current) – external edit 127.0.0.1
Line 2: Line 2:
 <html lang="nl"> <html lang="nl">
 <head> <head>
 +<script src="https://unpkg.com/pizzip@3.1.5/dist/pizzip.min.js"></script>
 +<script src="https://unpkg.com/docxtemplater@3.29.1/build/docxtemplater.js"></script>
 +<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
   <meta charset="UTF-8">   <meta charset="UTF-8">
-  <title>Spacematrix Tool</title>+  <title>Spacematrix Rekenblok + Voorzieningen + Parkeren</title>
   <style>   <style>
     body { font-family: sans-serif; margin: 20px; }     body { font-family: sans-serif; margin: 20px; }
-    .tabs { display: flex; border-bottom2px solid #ccc; margin-bottom: 10px; } +    .tabs { display: flex; gap10px; margin-bottom: 15px; } 
-    .tab { padding: 10px 20px; cursor: pointer; border: 1px solid #ccc; border-bottom: none; background: #f9f9f9margin-right5px; border-radius: 5px 5px 0 0; } +    .tab { padding: 10px 15px; background: #dddcursorpointer; border-radius: 5px 5px 0 0; } 
-    .tab.active { background: white; border-bottom: 2px solid white; font-weight: bold; } +    .tab.active { background: #f0f0f0; font-weight: bold; } 
-    .tabcontent { display: none; border: 1px solid #ccc; padding: 20px; border-radius: 0 5px 5px 5px; background: white; }+    .tabcontent { display: none; border: 1px solid #ccc; padding: 15px; border-radius: 0 5px 5px 5px; }
     .tabcontent.active { display: block; }     .tabcontent.active { display: block; }
     .inputrow { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }     .inputrow { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
-    .inputrow label { width: 220px; }+    .inputrow label { width: 240px; }
     .inputrow input { width: 80px; }     .inputrow input { width: 80px; }
-    table.rekenblok { border-collapse: collapse; margin-top: 20px; width: 100%; font-size0.9em; } +    table { border-collapse: collapse; width: 100%; margin-top10px; } 
-    table.rekenblok th, table.rekenblok td { border: 1px solid #ccc; padding: 4px 6px; text-align: right; } +    th, td { border: 1px solid #ccc; padding: 5px; text-align: right; } 
-    table.rekenblok th { background: #f0f0f0; } +    th { background: #f0f0f0; } 
-    .scheiding td { border-top2px solid #666; background: #fafafa; } +    td:first-child, th:first-child { text-align: left; } 
-    .resultblock { margin-left40px; min-width: 200px; text-align: right; font-size: 0.9em; } +    .kaartcontainer { position: relative; max-width: 350px; margin-top: 20px; }
-    .kaartcontainer { position: relative; width: 320px; margin-top: 20px; }+
     .kaartcontainer img { width: 100%; display: block; }     .kaartcontainer img { width: 100%; display: block; }
     .stipje { position: absolute; width: 14px; height: 14px; background: red; border-radius: 50%; transform: translate(-50%, -50%); border: 2px solid white; }     .stipje { position: absolute; width: 14px; height: 14px; background: red; border-radius: 50%; transform: translate(-50%, -50%); border: 2px solid white; }
   </style>   </style>
   <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>   <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
-  <script> 
-    function switchTab(tabId) { 
-      document.querySelectorAll(".tabcontent").forEach(el => el.classList.remove("active")); 
-      document.querySelectorAll(".tab").forEach(el => el.classList.remove("active")); 
-      document.getElementById(tabId).classList.add("active"); 
-      document.querySelector(`.tab[onclick*='${tabId}']`).classList.add("active"); 
-    } 
-  </script> 
 </head> </head>
 <body> <body>
  
-<h1>Spacematrix Rekenhulp</h1>+<h1>Spacematrix & Voorzieningen</h1>
 <div class="tabs"> <div class="tabs">
-  <div class="tab active" onclick="switchTab('spacematrix')">Spacematrix</div>+  <div class="tab active" onclick="switchTab('rekenblok')">Spacematrix Rekenblok</div>
   <div class="tab" onclick="switchTab('voorzieningen')">Voorzieningen</div>   <div class="tab" onclick="switchTab('voorzieningen')">Voorzieningen</div>
   <div class="tab" onclick="switchTab('parkeren')">Parkeren</div>   <div class="tab" onclick="switchTab('parkeren')">Parkeren</div>
-  <div class="tab" onclick="switchTab('openbareruimte')">Openbare ruimte</div>+  <div class="tab" onclick="switchTab('openbareruimte')">Openbare Ruimte</div>
 </div> </div>
  
-<div id="spacematrix" class="tabcontent active"> +<div id="rekenblok" class="tabcontent active"> 
-  <h2>Spacematrix</h2+  <div class="bovenblok" style="display: flex; gap: 20px; align-items: flex-start;"> 
-  <div class="kaartcontainer"> +    <div class="inputvelden" style="flex: 1;"> 
-    <img src="https://www.sumsonite.nl/wiki/lib/exe/fetch.php?media=handleiding_nieuw:spacematrix:SPACEMATE1.png" alt="Spacematrix kaart"> +      <div class="inputrow"> 
-    <div class="stipje" id="stipje"></div>+        <label for="opp">Oppervlak projectgebied (m²):</label
 +        <input id="opp" type="number" value="10000" oninput="updateLaadvermogen()"> 
 +      </div> 
 +      <div class="inputrow"
 +        <label for="fsi">FSI:</label> 
 +        <input id="fsi" type="number" step="0.01" value="1.6" oninput="updateLaadvermogen()"> 
 +      </div> 
 +      <div class="inputrow"> 
 +        <label for="gsi">GSI:</label> 
 +        <input id="gsi" type="number" step="0.01" value="0.3" oninput="updateLaadvermogen()"> 
 +      </div> 
 +      <div class="inputrow"> 
 +        <label>Voorzieningenruimte per woning (m²):</label> 
 +        <span id="voorzieningenruimte_display">-</span> 
 +        <input type="hidden" id="voorzieningenruimte_waarde" value="0"> 
 +   </div
 +    </div> 
 +    <div class="kaartcontainer" style="max-width: 500px;"> 
 +      <img src="https://www.sumsonite.nl/wiki/lib/exe/fetch.php?media=handleiding_nieuw:spacematrix:SPACEMATE1.png" alt="Spacematrix kaart"> 
 +      <div class="stipje" id="stipje"></div> 
 +    </div>
   </div>   </div>
-  <div class="inputrow"> + 
-    <label for="opp">Oppervlak projectgebied (m²):</label+  <div class="onderblok"> 
-    <input id="opptype="numbervalue="10000oninput="updateAll()"> +    <table> 
-    <div class="resultblock" id="lv1"></div>+      <thead> 
 +        <tr><th>Type</th><th>%</th><th>m²/won</th><th>Aantal</th><th>Tot. BVO</th></tr> 
 +      </thead> 
 +      <tbody id="woningtypes"></tbody> 
 +      <tfoot> 
 +        <tr><th>Totaal</th><th id="totaal_perc">-</th><th id="totaal_gewbvo">-</th><th id="totaal_won">-</th><th id="totaal_bvo">-</th></tr> 
 +      </tfoot> 
 +    </table> 
 + 
 +    <div style="margin-top: 10px; font-size: 0.9em; color: #555;"> 
 +  <strong>Let op:</strongde voorzieningenruimte zoals weergegeven in deze samenvatting kan iets afwijken van de berekening op het tabblad <em>Voorzieningen</em>
 +  Dit komt doordat het aantal woningen iteratief wordt bepaald op basis van de beschikbare ruimte, inclusief ruimte voor voorzieningen en parkeren.  
 +  Bij het toepassen van voorzieningen wordt eerst een schatting gemaakt op basis van een voorlopig aantal woningen. Daarna wordt het aantal woningen opnieuw berekend met de benodigde ruimte per woning.  
 +  Hierdoor ontstaat een klein verschil tussen het oorspronkelijk berekende totaal en de daadwerkelijk ingepaste voorzieningenruimte. 
 +</div> 
 + 
 +    <div id="output"></div> 
 +    <div id="summary"
 +      <h3>Samenvatting</h3> 
 +      <table> 
 +        <tr><td><strong>Totaal laadvermogen (BVO)</strong></td><td id="summary_bvo_tot">-</td></tr> 
 +        <tr><td>Woonruimte (BVO)</td><td id="summary_wonen_bvo">-</td></tr> 
 +        <tr><td>Voorzieningenruimte (BVO)</td><td id="summary_voorz_tot">-</td></tr
 +        <tr><td>Parkeerruimte bovengronds (BVO)</td><td id="summary_parkeren_tot">-</td></tr> 
 +  
 + <tr> 
 +          <td colspan="2" style="background: #e0e0e0; font-weight: bold; text-transform: uppercase; letter-spacing: 0.5px; font-size: 0.9rem; border-top: 2px solid #999; border-bottom: 1px solid #ccc; color: #333;"> 
 +          Kengetallen 
 +          </td> 
 +        </tr> 
 +  
 +        <tr><td>Voorzieningenruimte per woning (m²)</td><td id="summary_voorz_per_won">-</td></tr> 
 +        <tr><td>Parkeerruimte per woning (m²)</td><td id="summary_parkeren_per_won">-</td></tr> 
 +        <tr><td>Totaal aantal parkeerplaatsen</td><td id="summary_pp_tot">-</td></tr> 
 +        <tr><td>Totale woonruimte incl. voorzieningen en parkeren</td><td id="summary_wonen">-</td></tr> 
 +        <tr><td>Totaal aantal woningen</td><td id="summary_woningen">-</td></tr> 
 +      </table> 
 +    </div>
   </div>   </div>
 +  
 +  <div style="margin-top: 20px;">
 +  <button onclick="downloadKickstartDump()" style="padding: 10px 20px; font-size: 1rem; background-color: #0074d9; color: black; border: none; border-radius: 5px; cursor: pointer;">
 +    📄 Kickstart Dump downloaden
 +  </button>
 +</div>
 +  
 +</div>
 +
 +<div id="voorzieningen" class="tabcontent">
   <div class="inputrow">   <div class="inputrow">
-    <label for="fsi">FSI:</label> +    <label>Aantal bewoners per woning:</label> 
-    <input id="fsi" type="number" step="0.01" value="1.6oninput="updateAll()"> +    <input id="bewoners_per_woning" type="number" step="0.1" value="2.2">
-    <div class="resultblock" id="lv2"></div>+
   </div>   </div>
-  <div class="inputrow"> +  <table>
-    <label for="gsi">GSI:</label> +
-    <input id="gsi" type="number" step="0.01" value="0.3" oninput="updateAll()"> +
-    <div class="resultblock" id="lv3"></div> +
-  </div> +
-  <div class="inputrow"> +
-    <label for="voorziening">% BVO voor voorzieningen:</label> +
-    <input id="voorziening" type="number" step="1" value="10" oninput="updateAll()"> +
-    <div class="resultblock" id="lv4"></div> +
-  </div> +
- +
-  <table class="rekenblok">+
     <thead>     <thead>
-      <tr> +      <tr><th>Voorziening</th><th>Norm (m² per 1000)</th><th>Selecteer</th></tr>
-        <th>Type</th> +
-        <th>%</th> +
-        <th>/won</th> +
-        <th>Aantal</th> +
-        <th>Tot. BVO</th> +
-      </tr>+
     </thead>     </thead>
-    <tbody id="woningtypes"></tbody+    <tbody id="voorzieningentabel"></tbody>
-    <tfoot> +
-      <tr class="scheiding"> +
-        <td><b>Totaal</b></td> +
-        <td id="totaal_perc">-</td> +
-        <td id="totaal_gewbvo">-</td> +
-        <td id="totaal_won">-</td> +
-        <td id="totaal_bvo">-</td> +
-      </tr> +
-    </tfoot>+
   </table>   </table>
 +  <div class="inputrow">
 +    <button id="btn_voorzieningen" onclick="berekenVoorzieningenruimte()">Toepassen in rekenblok</button>
 +    <div id="voorziening_resultaat" style="margin-left: 10px;"></div>
 +  </div>
 +  <h3>Overzicht geselecteerde voorzieningen</h3>
 +<table id="voorzieningen_totaal">
 +  <thead>
 +    <tr><th>Voorziening</th><th>Berekend m²</th></tr>
 +  </thead>
 +  <tbody id="voorziening_summary_tabel"></tbody>
 +  <tfoot>
 +    <tr><th>Totaal</th><th id="voorziening_summary_totaal">-</th></tr>
 +  </tfoot>
 +</table>
  
-  <h3>Resultaat</h3> 
-  <div id="output"></div> 
-</div> 
  
-<div id="voorzieningen" class="tabcontent"> +<div style="margin-top: 10px; font-size: 0.9em; color: #555;"> 
-  <h2>Voorzieningen</h2> +  <strong>Toelichting:</stronghet weergegeven totaal van de voorzieningenruimte is gebaseerd op een schatting op basis van het huidige aantal woningen. 
-  <label>Gem. huishoudgrootte: +  Nadat dit oppervlak per woning is berekend, wordt het aantal woningen in het rekenblok opnieuw doorgerekend. Hierdoor kan het werkelijke totaal afwijken. 
-    <input id="hhgrootte" type="number" step="0.1" value="2.2" oninput="updateAll()"> +  Deze iteratieve aanpak is nodig omdat de benodigde ruimte per woning invloed heeft op hoeveel woningen uiteindelijk in het plan passen. 
-  </label> + </div>
-  <div id="voorzieningenlijst" style="columns: 2; max-width: 600px; margin-top: 10px;"></div> +
-  <div id="voorzieningresultaat" style="margin-top: 10px; font-size: 0.9em;"></div+
-  <div style="margin-top: 10px;"><b>Totaal BVO voorzieningen:</b<span id="voorziening_totaal">0</span></div>+
 </div> </div>
  
 <div id="parkeren" class="tabcontent"> <div id="parkeren" class="tabcontent">
-  <h2>Parkeren</h2>+  <h3>Parkeren</h3>
   <div class="inputrow">   <div class="inputrow">
-    <label for="pp_per_woning">Parkeerplaatsen per woning:</label> +    <label>Parkeerplaatsen per woning:</label> 
-    <input id="pp_per_woning" type="number" value="1.2" step="0.1" oninput="updateAll()">+    <input id="pp_per_woning" type="number" step="0.1" value="1.0">
   </div>   </div>
   <div class="inputrow">   <div class="inputrow">
-    <label for="m2_per_pp">Ruimtebeslag per pp (m²):</label> +    <label>BVO per parkeerplaats (m²):</label> 
-    <input id="m2_per_pp" type="number" value="25" step="1" oninput="updateAll()">+    <input id="bvo_per_pp" type="number" step="1" value="25">
   </div>   </div>
   <div class="inputrow">   <div class="inputrow">
-    <label for="perc_bovengronds">% Bovengronds parkeren:</label> +    <label>Ondergronds:</label> 
-    <input id="perc_bovengronds" type="number" value="100" step="1" oninput="updateAll()">+    <input id="pp_ondergronds" type="number" step="1" value="50">
   </div>   </div>
-  <div style="margin-top: 10px;"><b>Totale bovengrondse parkeeroppervlakte:</b> <span id="parkeren_totaal">0</span> m²</div> 
-</div> 
- 
-<div id="openbareruimte" class="tabcontent"> 
-  <h2>Openbare ruimte</h2> 
-  <p>Geef aan welk deel van de overblijvende ruimte je wilt reserveren voor groen, water en bestrating:</p> 
   <div class="inputrow">   <div class="inputrow">
-    <label for="pct_groen">% Groen:</label> +    <label>Bovengronds:</label> 
-    <input id="pct_groen" type="number" value="40" step="1" oninput="updateAll()">+    <input id="pp_bovengronds" type="number" step="1" value="50">
   </div>   </div>
   <div class="inputrow">   <div class="inputrow">
-    <label for="pct_water">% Water:</label> +    <button id="btn_parkerenonclick="berekenParkeerruimte()">Toepassen in rekenblok</button
-    <input id="pct_watertype="number" value="20" step="1" oninput="updateAll()"> +    <div id="parkeer_resultaat" style="margin-left: 10px;"></div>
-  </div+
-  <div class="inputrow"> +
-    <label for="pct_verharding">% Verharding:</label> +
-    <input id="pct_verhardingtype="number" value="40" step="1" oninput="updateAll()"> +
-  </div> +
-  <div style="margin-top: 10px;"> +
-    <b>Verdeling binnen resterende ruimte:</b><br> +
-    - Groen: <span id="oppervlak_groen">0</span> m²<br> +
-    - Water: <span id="oppervlak_water">0</span> m²<br> +
-    - Verharding: <span id="oppervlak_verharding">0</span+
   </div>   </div>
-  <canvas id="ruimteTaart" width="300" height="300" style="margin-top: 20px;"></canvas>+  <h3>Overzicht parkeerplaatsen</h3> 
 +<table> 
 +  <tbody> 
 +    <tr><td>Aantal parkeerplaatsen totaal</td><td id="pp_totaal">-</td></tr> 
 +    <tr><td>Bovengronds (% / aantal)</td><td id="pp_boven">-</td></tr> 
 +    <tr><td>Ondergronds (% / aantal)</td><td id="pp_onder">-</td></tr> 
 +  </tbody> 
 +</table> 
 +</div> 
 + 
 +<div id="openbareruimte" class="tabcontent"> 
 +  <h3>Openbare Ruimte</h3> 
 +  <p>Verdeling van de onbebouwde ruimte (oppervlak projectgebied minus bebouwde oppervlak volgens GSI):</p> 
 +  <table> 
 +    <label>Stedelijkheidstype:</label> 
 +    <select id="stedelijkheidstype" onchange="setVerdelingStedelijkheid()"> 
 +      <option value="auto">Afhankelijk van FSI/GSI</option> 
 +      <option value="centrum">Centrumstedelijk</option> 
 +      <option value="gemengd">Gemengd</option> 
 +      <option value="suburbaan">Suburbaan</option> 
 +    </select> 
 + <thead> 
 +      <tr> 
 +        <th>Oppervlaktetype</th> 
 +        <th>Standaard (%)</th> 
 +        <th>Aanpassing (%)</th> 
 +        <th>Oppervlak (m²)</th> 
 +      </tr> 
 +    </thead> 
 +    <tbody> 
 +      <tr><td>Groen</td><td>30</td><td><input type="number" id="perc_groen" value="30" oninput="updateOpenbareRuimte()"></td><td id="m2_groen">-</td></tr> 
 +      <tr><td>Water</td><td>10</td><td><input type="number" id="perc_water" value="10" oninput="updateOpenbareRuimte()"></td><td id="m2_water">-</td></tr> 
 +      <tr><td>Tuinen</td><td>15</td><td><input type="number" id="perc_tuinen" value="15" oninput="updateOpenbareRuimte()"></td><td id="m2_tuinen">-</td></tr> 
 +      <tr><td>Rijbanen</td><td>15</td><td><input type="number" id="perc_rijbanen" value="15" oninput="updateOpenbareRuimte()"></td><td id="m2_rijbanen">-</td></tr> 
 +      <tr><td>Trottoirs</td><td>10</td><td><input type="number" id="perc_trottoirs" value="10" oninput="updateOpenbareRuimte()"></td><td id="m2_trottoirs">-</td></tr> 
 +      <tr><td>Parkeren (bovengronds)</td><td>10</td><td><input type="number" id="perc_parkeren" value="10" oninput="updateOpenbareRuimte()"></td><td id="m2_parkeren">-</td></tr> 
 +      <tr><td>Pleinen</td><td>10</td><td><input type="number" id="perc_pleinen" value="10" oninput="updateOpenbareRuimte()"></td><td id="m2_pleinen">-</td></tr> 
 +    </tbody> 
 + <tfoot> 
 +     <tr><th colspan="3">Totaal</th><th id="m2_totaal_onbebouwd">-</th></tr> 
 +    </tfoot> 
 +  </table> 
 +  <p style="margin-top:10px;"><button onclick="updateOpenbareRuimte()">Herbereken verdeling</button></p> 
 +  <div id="warning_openbareruimte" style="color: red; font-weight: bold;"></div> 
 +  <canvas id="openbareRuimteChart" width="150" height="150" style="margin-top:20px;"></canvas>
 </div> </div>
  
 <script> <script>
 +const types = ["egw sociaal", "egw goedkoop", "egw midden", "egw duur", "egw top", "mgw sociaal", "mgw goedkoop", "mgw midden", "mgw duur", "mgw top"];
 +const voorzieningen = [
 +  { naam: "Huisarts", norm: 56 },
 +  { naam: "Fysiotherapie", norm: 54 },
 +  { naam: "Tandarts", norm: 57 },
 +  { naam: "Kinderopvang", norm: 2025 },
 +  { naam: "Basisschool", norm: 5800 },
 +  { naam: "Bibliotheek", norm: 60 },
 +  { naam: "Buurtcentrum", norm: 70 },
 +  { naam: "Sporthal", norm: 165 },
 +  { naam: "Zwemmen (overdekt)", norm: 45 },
 +  { naam: "Winkels dagelijkse goederen", norm: 420 }
 +];
 +
 +function switchTab(tabId) {
 +  document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
 +  document.querySelectorAll('.tabcontent').forEach(c => c.classList.remove('active'));
 +  document.querySelector(`.tab[onclick*="${tabId}"]`).classList.add('active');
 +  document.getElementById(tabId).classList.add('active');
 +}
 +
 +function renderWoningtypes() {
 +  const tbody = document.getElementById("woningtypes");
 +  tbody.innerHTML = "";
 +  types.forEach((type, i) => {
 +    const row = document.createElement("tr");
 +    row.innerHTML = `
 +      <td>${type}</td>
 +      <td><input type="number" id="perc_${i}" value="10" step="0.1" oninput="updateLaadvermogen()"></td>
 +      <td><input type="number" id="bvo_${i}" value="${i < 5 ? 130 : 90}" step="1" oninput="updateLaadvermogen()"></td>
 +      <td id="aantal_${i}">-</td>
 +      <td id="totbvo_${i}">-</td>
 +    `;
 +    tbody.appendChild(row);
 +  });
 +}
 +
 +function updateStipje(fsi, gsi) {
 +  const stip = document.getElementById("stipje");
 +  const x = Math.min(100, Math.max(0, gsi * 190));
 +  const y = Math.max(0, Math.min(100, (3 - fsi) * 35));
 +  stip.style.left = `${x}%`;
 +  stip.style.top = `${y}%`;
 +}
 +
 +function updateSummary(bvoTot, voorzTot, voorzPerWoning, woonruimte, woningen) {
 +  const pp = parseFloat(document.getElementById("pp_per_woning").value) || 0;
 +  const pp_bvo = parseFloat(document.getElementById("bvo_per_pp").value) || 0;
 +  const pp_bovengronds = parseFloat(document.getElementById("pp_bovengronds").value) || 0;
 +  const parkerenruimtePerWoning = pp * pp_bvo * (pp_bovengronds / 100);
 +  const parkerenTot = woningen * parkerenruimtePerWoning;
 +
 +  const wonenBVO = bvoTot - voorzTot - parkerenTot;
 +  const parkeerplaatsenTotaal = woningen * pp;
 +
 +  document.getElementById("summary_bvo_tot").innerText = `${bvoTot.toFixed(0)} m²`;
 +  document.getElementById("summary_wonen_bvo").innerText = `${wonenBVO.toFixed(0)} m²`;
 +  document.getElementById("summary_voorz_tot").innerText = `${voorzTot.toFixed(0)} m²`;
 +  document.getElementById("summary_parkeren_tot").innerText = `${parkerenTot.toFixed(0)} m²`;
 +
 +  document.getElementById("summary_voorz_per_won").innerText = `${voorzPerWoning.toFixed(1)} m²`;
 +  document.getElementById("summary_parkeren_per_won").innerText = `${parkerenruimtePerWoning.toFixed(1)} m²`;
 +  document.getElementById("summary_pp_tot").innerText = `${parkeerplaatsenTotaal.toFixed(0)}`;
 +
 +  document.getElementById("summary_wonen").innerText = `${woonruimte.toFixed(0)} m²`;
 +  document.getElementById("summary_woningen").innerText = `${woningen}`;
 +}
 +
 +function updateLaadvermogen() {
 +  const opp = parseFloat(document.getElementById("opp").value);
 +  const fsi = parseFloat(document.getElementById("fsi").value);
 +  const gsi = parseFloat(document.getElementById("gsi").value);
 +  const bvoTot = opp * fsi;
 +  const voorzieningenruimte = parseFloat(document.getElementById("voorzieningenruimte_display").innerText) || 0;
 +
 +  // Nieuw: parkeerinput ophalen
 +  const pp = parseFloat(document.getElementById("pp_per_woning").value) || 0;
 +  const pp_bvo = parseFloat(document.getElementById("bvo_per_pp").value) || 0;
 +  const pp_bovengronds = parseFloat(document.getElementById("pp_bovengronds").value) || 0;
 +  const parkerenruimte = pp * pp_bvo * (pp_bovengronds / 100);
 +
 +  updateStipje(fsi, gsi);
 +
 +  let gewogenBVO = 0;
 +  let totalPerc = 0;
 +  const details = [];
 +  for (let i = 0; i < types.length; i++) {
 +    const perc = parseFloat(document.getElementById(`perc_${i}`).value) || 0;
 +    const bvo = parseFloat(document.getElementById(`bvo_${i}`).value) || 0;
 +    gewogenBVO += (perc / 100) * bvo;
 +    totalPerc += perc;
 +    details.push({ i, perc, bvo });
 +  }
 +  if (gewogenBVO === 0) return;
 +
 +  // Nieuwe berekening met voorzieningen én parkeren
 +  let woningen = Math.floor(bvoTot / (gewogenBVO + voorzieningenruimte + parkerenruimte));
 +  let sumWon = 0;
 +  let sumBVO = 0;
 +  let wonPerType = [];
 +  let restant = woningen;
 +
 +  for (let i = 0; i < details.length; i++) {
 +    const { perc } = details[i];
 +    let aant = (perc / 100) * woningen;
 +    let afgerond = Math.floor(aant);
 +    wonPerType.push(afgerond);
 +    restant -= afgerond;
 +  }
 +  const decimaalSort = details.map((d, i) => ({ i, rest: ((d.perc / 100) * woningen) % 1 }))
 +    .sort((a, b) => b.rest - a.rest);
 +  for (let j = 0; j < restant; j++) {
 +    wonPerType[decimaalSort[j].i]++;
 +  }
 +
 +  for (let i = 0; i < details.length; i++) {
 +    const aant = wonPerType[i];
 +    const bvoTot = aant * details[i].bvo;
 +    document.getElementById(`aantal_${i}`).innerText = aant;
 +    document.getElementById(`totbvo_${i}`).innerText = bvoTot.toFixed(0);
 +    sumWon += aant;
 +    sumBVO += bvoTot;
 +  }
 +
 +  document.getElementById("totaal_perc").innerText = `${totalPerc.toFixed(1)}%`;
 +  document.getElementById("totaal_gewbvo").innerText = `${gewogenBVO.toFixed(1)} m²`;
 +  document.getElementById("totaal_won").innerText = sumWon;
 +  document.getElementById("totaal_bvo").innerText = sumBVO.toFixed(0);
 +
 +  document.getElementById("output").innerHTML =
 +    `<p><b>Gewogen BVO/ehd:</b> ${gewogenBVO.toFixed(1)} m²<br><b>Totaal aantal woningen:</b> ${sumWon}</p>`;
 +
 +  const voorzieningenTot = sumWon * voorzieningenruimte;
 +  const wonenRuimte = bvoTot - voorzieningenTot - (sumWon * parkerenruimte);
 +  updateSummary(bvoTot, voorzieningenTot, voorzieningenruimte, wonenRuimte, sumWon);
 +
 +  // Extra update voor parkeren per woning
 +  document.getElementById("summary_parkeren_per_won").innerText = `${parkerenruimte.toFixed(1)} m²`;
 +}
 +
 +function maakVoorzieningentabel() {
 +  const tbody = document.getElementById("voorzieningentabel");
 +  voorzieningen.forEach((v, i) => {
 +    const row = document.createElement("tr");
 +    row.innerHTML = `
 +      <td>${v.naam}</td>
 +      <td>${v.norm}</td>
 +      <td><input type="checkbox" id="vchk_${i}" checked></td>
 +    `;
 +    tbody.appendChild(row);
 +  });
 +}
 +
 +function berekenVoorzieningenruimte() {
 +  updateLaadvermogen(); // om actuele woningaantal op te halen
 +
 +  const bewonersPerWoning = parseFloat(document.getElementById("bewoners_per_woning").value);
 +  const woningen = parseFloat(document.getElementById("totaal_won").innerText.replace(/[^0-9]/g, "")) || 0;
 +  const totaalBewoners = woningen * bewonersPerWoning;
 +
 +  const resultDiv = document.getElementById("voorziening_resultaat");
 +  const btn = document.getElementById("btn_voorzieningen");
 +
 +  if (woningen === 0) {
 +    resultDiv.innerHTML = `<span style="color:red; font-weight:bold;">✖</span> Geen woningen gevonden. Vul eerst FSI/GSI en woningpercentages in.`;
 +    btn.style.border = "1px solid #a00";
 +    btn.style.background = "#ffe6e6";
 +    return;
 +  }
 +
 +  let totaal_m2 = 0;
 +  voorzieningen.forEach((v, i) => {
 +    const checked = document.getElementById(`vchk_${i}`).checked;
 +    if (checked) {
 +      totaal_m2 += v.norm * totaalBewoners / 1000;
 +    }
 +  });
 +
 +  const m2_per_woning = totaal_m2 / woningen;
 +
 +  document.getElementById("voorzieningenruimte_display").innerText = `${m2_per_woning.toFixed(1)} m²`;
 +  document.getElementById("voorzieningenruimte_waarde").value = m2_per_woning.toFixed(1);
 +
 +  resultDiv.innerHTML = `<span style="color:green; font-weight:bold;">✔</span> ${totaal_m2.toFixed(1)} m² totaal → ${m2_per_woning.toFixed(1)} m² per woning`;
 +  btn.style.border = "1px solid #0a0";
 +  btn.style.background = "#e6ffe6";
 +
 +  updateLaadvermogen(); // herberekenen met nieuwe voorzieningenruimte
 +
 + // Toon tabel met voorzieningen en m2
 +  const summaryBody = document.getElementById("voorziening_summary_tabel");
 +  const summaryTotal = document.getElementById("voorziening_summary_totaal");
 +  summaryBody.innerHTML = "";
 +  let subtotal = 0;
 +
 +  voorzieningen.forEach((v, i) => {
 +    const checked = document.getElementById(`vchk_${i}`).checked;
 +    if (checked) {
 +      const v_m2 = v.norm * totaalBewoners / 1000;
 +      subtotal += v_m2;
 +      const row = document.createElement("tr");
 +      row.innerHTML = `<td>${v.naam}</td><td>${v_m2.toFixed(1)} m²</td>`;
 +      summaryBody.appendChild(row);
 +    }
 +  });
 +  summaryTotal.innerText = `${subtotal.toFixed(1)} m²`;
 +
 +}
 +
 +function berekenParkeerruimte() {
 +  const pp = parseFloat(document.getElementById("pp_per_woning").value) || 0;
 +  const bvo_per_pp = parseFloat(document.getElementById("bvo_per_pp").value) || 0;
 +  const bovengronds = parseFloat(document.getElementById("pp_bovengronds").value) || 0;
 +  const woningen = parseFloat(document.getElementById("totaal_won").innerText.replace(/[^0-9]/g, "")) || 0;
 +
 +  const ruimte_per_woning = pp * bvo_per_pp * (bovengronds / 100);
 +  const totaal_ruimte = ruimte_per_woning * woningen;
 +
 +  // Toon het resultaat en vinkje
 +  const resultDiv = document.getElementById("parkeer_resultaat");
 +  resultDiv.innerHTML = `<span style="color:green; font-weight:bold;">✔</span> ${totaal_ruimte.toFixed(1)} m² totaal → ${ruimte_per_woning.toFixed(1)} m² per woning`;
 +
 +  // Visuele feedback op de knop
 +  const btn = document.getElementById("btn_parkeren");
 +  btn.style.border = "1px solid #0a0";
 +  btn.style.background = "#e6ffe6";
 +
 +  // Update berekening
 +  updateLaadvermogen();
 +
 +const totaal_pp = woningen * pp;
 +  const pp_boven_aantal = totaal_pp * (bovengronds / 100);
 +  const ondergronds = parseFloat(document.getElementById("pp_ondergronds").value) || 0;
 +  const pp_onder_aantal = totaal_pp * (ondergronds / 100);
 +
 +  document.getElementById("pp_totaal").innerText = `${totaal_pp.toFixed(0)}`;
 +  document.getElementById("pp_boven").innerText = `${bovengronds.toFixed(0)}% / ${pp_boven_aantal.toFixed(0)}`;
 +  document.getElementById("pp_onder").innerText = `${ondergronds.toFixed(0)}% / ${pp_onder_aantal.toFixed(0)}`;
 +
 +}
 +
 +function updateOpenbareRuimte() {
 +  const opp = parseFloat(document.getElementById("opp").value);
 +  const gsi = parseFloat(document.getElementById("gsi").value);
 +  const bebouwd = opp * gsi;
 +  const onbebouwd = opp - bebouwd;
 +
   const types = [   const types = [
-    "egw sociaal", "egw goedkoop", "egw midden", "egw duur", "egw top", +    { id: "groen", label: "Groen}, 
-    "mgw sociaal", "mgw goedkoop", "mgw midden", "mgw duur", "mgw top"+    { id: "water", label: "Water}, 
 +    { id: "tuinen", label: "Tuinen" }
 +    { id: "rijbanen", label: "Rijbanen}, 
 +    { id: "trottoirs", label: "Trottoirs" }, 
 +    { id: "parkeren", label: "Parkeren" }, 
 +    { id: "pleinen", label: "Pleinen}
   ];   ];
  
-  const voorzieningenData [ +  let totaal = 0; 
-    ["huisarts", 56], ["fysio", 54], ["tandarts", 57], ["verloskundige", 40], +  types.forEach(type => { 
-    ["consultatiebureau", 195], ["apotheken", 31], ["verpleeghuizen", 1760], +    const perc parseFloat(document.getElementById(`perc_${type.id}`).value) || 0; 
-    ["verzorgingstehuis", 2440], ["basisonderwijs", 5800], ["speciaal basisonderwijs", 1000], +    totaal += perc; 
-    ["voortgezet onderwijs", 5200], ["buurthuis", 70], ["jongerencentrum", 110]+  }); 
-    ["peuterspeelzaal", 2650], ["kinderdagverblijf", 2025], ["bso", 585]+ 
-    ["maatschappelijk werk", 25], ["bibliotheek", 60], ["muziekschool", 140]+  if (totaal !== 100) { 
-    ["gymzalen", 45], ["zwembad", 165], ["sporthal", 165], ["speelvelden", 100]+    document.getElementById("warning_openbareruimte").innerText = `⚠️ Totaal is ${totaal}%. Dit moet 100% zijn.`; 
-    ["kleine speelplek", 1225], ["grote speelplek", 6400], ["voetbalveld", 4000]+    return; 
-    ["tennisbaan", 200], ["sportvelden", 1800], ["park", 4000], ["volkstuin", 2400]+  } else { 
-    ["winkels/dagelijks", 420], ["horeca", 39]+    document.getElementById("warning_openbareruimte").innerText = ""
 +  } 
 + 
 +  types.forEach(type => { 
 +    const perc = parseFloat(document.getElementById(`perc_${type.id}`).value) || 0; 
 +    const m2 = (perc / 100) * onbebouwd; 
 +    document.getElementById(`m2_${type.id}`).innerText = `${m2.toFixed(0)} m²`; 
 +  }); 
 +
 + 
 +let openbareRuimteChart = null; 
 + 
 +function updateOpenbareRuimte() { 
 +  const opp = parseFloat(document.getElementById("opp").value); 
 +  const gsi = parseFloat(document.getElementById("gsi").value); 
 +  const bebouwd = opp * gsi; 
 +  const onbebouwd = opp - bebouwd; 
 + 
 +  const types = 
 +    { id: "groen", label: "Groen}
 +    { id: "water", label: "Water}
 +    { id: "tuinen", label: "Tuinen}
 +    { id: "rijbanen", label: "Rijbanen}
 +    { id: "trottoirs", label: "Trottoirs}
 +    { id: "parkeren", label: "Parkeren}
 +    { id: "pleinen", label: "Pleinen}
   ];   ];
  
-  function formatGetal(n) { +  let totaal = 0; 
-    return n.toLocaleString("nl-NL");+  let data = []; 
 + 
 +  types.forEach(type => { 
 +    const perc = parseFloat(document.getElementById(`perc_${type.id}`).value) || 0; 
 +    totaal += perc; 
 +  }); 
 + 
 +  if (totaal !== 100) { 
 +    document.getElementById("warning_openbareruimte").innerText = `⚠️ Totaal is ${totaal}%. Dit moet 100% zijn.`; 
 +    document.getElementById("m2_totaal_onbebouwd").innerText = "-"; 
 +    return; 
 +  } else { 
 +    document.getElementById("warning_openbareruimte").innerText = "";
   }   }
  
-  function updateStipje(fsi, gsi) +  // Bereken oppervlak per type en vul tabel 
-    const stip = document.getElementById("stipje"); +  types.forEach(type => 
-    const Math.min(100, Math.max(0, gsi * 190)); +    const perc parseFloat(document.getElementById(`perc_${type.id}`).value) || 0
-    const Math.max(0Math.min(100(3 - fsi) * 35)); +    const m2 = (perc / 100) * onbebouwd; 
-    stip.style.left = `${x}%`; +    document.getElementById(`m2_${type.id}`).innerText = `${m2.toFixed(0)} m²`; 
-    stip.style.top = `${y}%`;+    data.push({ label: type.labelvalue: m2 })
 +  }); 
 + 
 +  // Totaal m² 
 +  const totaal_m2 data.reduce((sumd) => sum + d.value0); 
 +  document.getElementById("m2_totaal_onbebouwd").innerText = `${totaal_m2.toFixed(0)`; 
 + 
 +  // Vergelijking met onbebouwd oppervlak 
 +  const verschil = Math.abs(totaal_m2 - onbebouwd); 
 +  const totaalCell = document.getElementById("m2_totaal_onbebouwd"); 
 +  if (verschil > 1) { 
 +    totaalCell.style.color = "red"; 
 +    totaalCell.title = `Let op: verschil van ${verschil.toFixed(1)m² met onbebouwde ruimte`
 +  } else { 
 +    totaalCell.style.color = ""; 
 +    totaalCell.title = "";
   }   }
  
-  function renderWoningtypes() { +  // Chart.js bijwerken 
-    const tbody = document.getElementById("woningtypes"); +  const ctx = document.getElementById("openbareRuimteChart").getContext("2d"); 
-    types.forEach((type, i) => { +  const labels = data.map(=> d.label); 
-      const row document.createElement("tr"); +  const values data.map(d => d.value); 
-      if (i === 5row.className "scheiding"+ 
-      row.innerHTML ` +  if (openbareRuimteChart
-        <td style="text-align: left;">${type}</td> +    openbareRuimteChart.data.labels labels
-        <td><input type="number" id="perc_${i}" value="10" step="0.1" oninput="updateLaadvermogen()"></td> +    openbareRuimteChart.data.datasets[0].data values; 
-        <td><input type="number" id="bvo_${i}" value="${i < 5 ? 130 90}" step="1" oninput="updateLaadvermogen()"></td> +    openbareRuimteChart.update(); 
-        <td id="aantal_${i}">-</td> +  } else { 
-        <td id="totbvo_${i}">-</td> +    openbareRuimteChart = new Chart(ctx, { 
-      `; +      type: 'pie', 
-      tbody.appendChild(row);+      data: { 
 +        labels: labels, 
 +        datasets: [{ 
 +          data: values, 
 +          backgroundColor:
 +            '#66bb6a', '#42a5f5', '#ffee58', '#8d6e63', 
 +            '#bdbdbd', '#90caf9', '#ff7043' 
 +          ] 
 +        }
 +      }, 
 +      options: { 
 +        plugins: { 
 +          legend: { position: 'right' }
 +          title: { 
 +            displaytrue, 
 +            text: 'Verdeling onbebouwde ruimte ()' 
 +          
 +        } 
 +      }
     });     });
   }   }
 +}
  
-  function renderVoorzieningenlijst() { + 
-    const lijst = document.getElementById("voorzieningenlijst"); +function setVerdelingStedelijkheid() { 
-    lijst.innerHTML voorzieningenData.map(([naam, norm], i) => ` +  const type = document.getElementById("stedelijkheidstype").value
-      <label><input type="checkbox" class="voorChkdata-index="${i}" checked> ${naam}</label><br> +  let waarden {}; 
-    `).join("");+ 
 +  if (type === "centrum"
 +    waarden { groen: 18, water: 4, tuinen: 8, rijbanen: 25, trottoirs: 20, parkeren: 10, pleinen: 15 }; 
 +  } else if (type === "gemengd") { 
 +    waarden = { groen: 20, water: 10, tuinen: 10, rijbanen: 20, trottoirs: 15, parkeren: 15, pleinen: 10 }
 +  } else if (type === "suburbaan"{ 
 +    waarden = { groen: 30, water: 15, tuinen: 25, rijbanen: 15, trottoirs: 8, parkeren: 5, pleinen: 2 }
 +  } else { 
 +    updateOpenbareRuimte(); // Laat FSI/GSI zelf beslissen 
 +    return;
   }   }
  
-  function updateLaadvermogen() +  Object.keys(waarden).forEach(id => { 
-    const opp = parseFloat(document.getElementById("opp").value); +    document.getElementById(`perc_${id}`).value = waarden[id]
-    const fsi = parseFloat(document.getElementById("fsi").value); +  });
-    const gsi parseFloat(document.getElementById("gsi").value)+
-    const voorzieningPerc = parseFloat(document.getElementById("voorziening").value/ 100;+
  
-    const laadvermogen = Math.round(opp * fsi); +  updateOpenbareRuimte(); 
-    const bvoVoorzieningen = Math.round(laadvermogen * voorzieningPerc); +}
-    const bvoWonen = laadvermogen - bvoVoorzieningen;+
  
-    document.getElementById("lv1").innerText = `Oppervlak: ${formatGetal(opp)} m²`; +// 👇 Bouw de volledige woningtype + parkeren-tabel met eerste kolom labels, geschikt voor Kladblok 
-    document.getElementById("lv2").innerText = `Laadvermogen: ${formatGetal(laadvermogen)} m² BVO`+function buildWoningtypesTableTXT() { 
-    document.getElementById("lv3").innerText = `Voorzieningen: ${formatGetal(bvoVoorzieningen)} m²`+  const types = ["egw sociaal", "egw goedkoop", "egw midden", "egw duur", "egw top", 
-    document.getElementById("lv4").innerText `Wonen: ${formatGetal(bvoWonen)} m²`;+                 "mgw sociaal", "mgw goedkoop", "mgw midden", "mgw duur", "mgw top"]
 +  const parkeerkolommen = ["Park. bov.""Parkond."]
 +  const kolommen = [...types, ...parkeerkolommen]; 
 +  const colWidth 13; 
 +  const labelWidth = 18;
  
-    updateStipje(fsi, gsi); +  const pad = (val) => val.toString().padStart(colWidth); 
-    bereken(opp, fsi, voorzieningPerc); +  const head = (val) => val.toString().padEnd(colWidth); 
-  }+  const label = (txt) => `| ${txt}`.padEnd(labelWidth);
  
-  function bereken(oppfsivoorzieningPerc) { +  // DATA per woningtype (alleen typesdus zonder parkeren) 
-    const laadvermogen opp fsi+  const perc = types.map((_i=> document.getElementById(`perc_${i}`)?.value || "0"); 
-    const woonBVO laadvermogen * (1 - voorzieningPerc);+  const bvo types.map((_, i) => parseFloat(document.getElementById(`bvo_${i}`)?.value || "0")); 
 +  const aantallen = types.map((_, i) => parseInt(document.getElementById(`aantal_${i}`)?.innerText || "0")); 
 +  const vormfactor = types.map((_, i) => i < 5 ? 0.9 : 0.75); 
 +  const bvo_tot = bvo.map((b, i) => b aantallen[i])
 +  const gbo bvo.map((b, i) => (b vormfactor[i]).toFixed(1));
  
-    let gewogenBVO 0+  // PARKEERREGELS berekenen 
-    let totalPerc = 0; +  const pp parseFloat(document.getElementById("pp_per_woning")?.value || 1)
-    const details [];+  const woningen aantallen.reduce((acc, val) => acc + (val || 0), 0); // alleen woningtypes 
 +  const bvo_pp = parseFloat(document.getElementById("bvo_per_pp")?.value || 25); 
 +  const perc_boven = parseFloat(document.getElementById("pp_bovengronds")?.value || 70); 
 +  const perc_onder = parseFloat(document.getElementById("pp_ondergronds")?.value || 30); 
 +  const pp_boven = Math.round(woningen * pp * (perc_boven / 100)); 
 +  const pp_onder = Math.round(woningen * pp * (perc_onder / 100)); 
 +  const bvo_boven = pp_boven * bvo_pp
 +  const bvo_onder pp_onder * bvo_pp;
  
-    for (let i = 0; i < types.length; i++) { +  // PARKEERGEGEVENS toevoegen 
-      const perc = parseFloat(document.getElementById(`perc_${i}`).value) || 0+  perc.push("-", "-"); 
-      const bvo = parseFloat(document.getElementById(`bvo_${i}`).value|| 0+  bvo.push(bvo_pp, bvo_pp)
-      gewogenBVO += (perc / 100* bvo+  aantallen.push(pp_boven, pp_onder); 
-      totalPerc += perc+  bvo_tot.push(bvo_boven, bvo_onder); 
-      details.push({ iperc, bvo }); +  vormfactor.push(1.00, 1.00)
-    }+  gbo.push((bvo_pp * 1.00).toFixed(1)(bvo_pp * 1.00).toFixed(1));
  
-    if (gewogenBVO === 0) return;+  // TABEL opbouwen 
 +  const r = []; 
 +  r.push(label("Type") + kolommen.map(head).join("|") + "|"); 
 +  r.push("".padEnd(labelWidth, " ") + kolommen.map(() => "-".repeat(colWidth)).join("|") + "|"); 
 +  r.push(label("% totaal") + perc.map(pad).join("|") + "|"); 
 +  r.push(label("Aantal woningen") + aantallen.map(pad).join("|") + "|"); 
 +  r.push(label("Totaal BVO") + bvo_tot.map(b => pad(b.toFixed(0))).join("|") + "|"); 
 +  r.push(label("m² BVO/woning") + bvo.map(b => pad(b.toFixed(0))).join("|") + "|"); 
 +  r.push(label("m² GBO/woning") + gbo.map(pad).join("|") + "|"); 
 +  r.push(label("Vormfactor") + vormfactor.map(f => pad(f.toFixed(2))).join("|") + "|");
  
-    const totaalWoningenExact woonBVO / gewogenBVO+  // GEMIDDELDES (alleen woningtypes, dus index 0 t/m 9) 
-    let sumWon = 0; +  const woningtypes [...Array(10).keys()]
-    let sumBVO = 0; +  const totale_bvo woningtypes.reduce((sum, i) => sum + bvo[i] * aantallen[i], 0)
-    let wonPerType = [];+  const totale_gbo woningtypes.reduce((sum, i) => sum + parseFloat(gbo[i]) * aantallen[i], 0)
 +  const totaal_woningen woningtypes.reduce((sum, i) => sum + aantallen[i], 0);
  
-    let restant Math.round(totaalWoningenExact)+  const gemiddelde_bvo totaal_woningen > 0 ? (totale_bvo / totaal_woningen).toFixed(1: "0"
-    for (let i = 0; i < details.length; i++) { +  const gemiddelde_gbo totaal_woningen > 0 ? (totale_gbo totaal_woningen).toFixed(1: "0";
-      const { perc } = details[i]; +
-      let aant = (perc 100* totaalWoningenExact; +
-      let afgerond = Math.floor(aant); +
-      wonPerType.push(afgerond); +
-      restant -= afgerond; +
-    }+
  
-    const decimaalSort = details.map((d, i=> ({ +  r.push(""); 
-      i, rest: ((d.perc / 100) * totaalWoningenExact) % 1 +  r.push(`Totale aantal woningen: ${totaal_woningen}`)
-    })).sort((a, b=> b.rest - a.rest);+  r.push(`Gemiddelde BVO per woning: ${gemiddelde_bvo}`)
 +  r.push(`Gemiddelde GBO per woning: ${gemiddelde_gbo}`);
  
-    for (let j = 0; j < restant; j+++  return r.join("\n"); 
-      wonPerType[decimaalSort[j].i]+++}
-    }+
  
-    for (let i = 0; i < details.length; i++) { +async function downloadKickstartDump() { 
-      const aant = wonPerType[i]; +  console.log("🔍 Start Kickstart TXT-generatie");
-      const bvoTot = aant * details[i].bvo; +
-      document.getElementById(`aantal_${i}`).innerText = formatGetal(aant); +
-      document.getElementById(`totbvo_${i}`).innerText = formatGetal(bvoTot); +
-      sumWon += aant; +
-      sumBVO += bvoTot; +
-    }+
  
-    document.getElementById("totaal_perc").innerText `${totalPerc.toFixed(1)}%`+  try { 
-    document.getElementById("totaal_gewbvo").innerText = `${gewogenBVO.toFixed(1)} m²`+    const response = await fetch('https://www.sumsonite.nl/wiki/lib/exe/fetch.php?media=handleiding_nieuw:spacematrix:kickstart_template_final.txt&v=' + Date.now())
-    document.getElementById("totaal_won").innerText = formatGetal(sumWon); +    if (!response.ok) throw new Error(`Bestand niet bereikbaar (${response.status})`);
-    document.getElementById("totaal_bvo").innerText = formatGetal(sumBVO);+
  
-    let waarschuwing ''+    let template await response.text()
-    if (Math.abs(totalPerc - 1000.5) { +    console.log("✅ Template geladen"); 
-      waarschuwing `<p style="color:red;"><b>Let op:</b> het totaalpercentage is ${totalPerc.toFixed(1)}%, dat wijkt af van 100%.</p>`;+ 
 +    const bvo_per_pp = parseFloat(document.getElementById("bvo_per_pp").value) || 0
 +    const pp_bovengronds = parseFloat(document.getElementById("pp_bovengronds").value) || 0; 
 +    const pp_ondergronds = parseFloat(document.getElementById("pp_ondergronds").value) || 0; 
 +    const woningen = parseFloat(document.getElementById("summary_woningen").innerText) || 0; 
 +    const pp = parseFloat(document.getElementById("pp_per_woning").value) || 0; 
 + 
 +    const bvo_per_pp_boven = bvo_per_pp.toFixed(1); 
 +    const bvo_per_pp_onder = bvo_per_pp.toFixed(1); 
 + 
 +    const parkeeropp_totaal = woningen * pp * bvo_per_pp; 
 +    const parkeeropp_boven = parkeeropp_totaal * (pp_bovengronds / 100); 
 +    const parkeeropp_onder = parkeeropp_totaal * (pp_ondergronds / 100); 
 + 
 +    const data = 
 +      datum: new Date().toISOString().slice(0, 10), 
 +      aantal_woningen: woningen, 
 +      bvo_per_woning: "110.0", 
 +      pp_boven: document.getElementById("pp_boven")?.innerText || "–", 
 +      pp_onder: document.getElementById("pp_onder")?.innerText || "–", 
 +      bvo_boven: document.getElementById("summary_parkeren_tot")?.innerText || "–", 
 +      bvo_onder: "–", 
 +      bvo_per_pp_boven: bvo_per_pp_boven, 
 +      bvo_per_pp_onder: bvo_per_pp_onder, 
 +      totbvo_boven: parkeeropp_boven.toFixed(0), 
 +      totbvo_onder: parkeeropp_onder.toFixed(0), 
 +      woningtypes_table: buildWoningtypesTableTXT(), 
 +   voorzieningen_table: buildVoorzieningenTableTXT(), 
 +      plankaart_table: buildPlankaartTableTXT(), 
 +      grex_table: buildGrexTableTXT() 
 +    }; 
 + 
 +    for (let i 0; i 10; i++) { 
 +      data[`perc_${i}`] document.getElementById(`perc_${i}`)?.value || "0"; 
 +      data[`bvo_${i}`] = document.getElementById(`bvo_${i}`)?.value || "0"; 
 +      data[`aantal_${i}`] = document.getElementById(`aantal_${i}`)?.innerText || "0"; 
 +      data[`totbvo_${i}`] = document.getElementById(`totbvo_${i}`)?.innerText || "0";
     }     }
  
-    document.getElementById("output").innerHTML +    Object.entries(data).forEach(([key, val]) =
-      ${waarschuwing} +      template = template.replaceAll(`{{${key}}}`, val)
-      <p><b>Gewogen BVO/ehd:</b> ${gewogenBVO.toFixed(1)} m²<br> +    });
-      <b>Totaal aantal woningen:</b> ${formatGetal(sumWon)}</p> +
-    `; +
-  }+
  
-  function init(+    const blob = new Blob([template], type: 'text/plain;charset=utf-8' }); 
-    renderWoningtypes(); +    saveAs(blob, 'kickstart_dump.txt'); 
-    renderVoorzieningenlijst(); +    alert("✅ Kickstart Dump is succesvol gegenereerd en gedownload"); 
-    updateLaadvermogen();+  } catch (error) { 
 +    console.error("❌ Fout bij genereren:", error); 
 +    alert("❌ Fout: " + error.message);
   }   }
 +}
  
-  window.onload = init;+function buildVoorzieningenTableTXT() { 
 +  let output = ""; 
 +  const rows = document.querySelectorAll("#voorziening_summary_tabel tr"); 
 +  rows.forEach(row => { 
 +    const cells = row.querySelectorAll("td"); 
 +    if (cells.length === 2) { 
 +      const naam = cells[0].innerText.trim(); 
 +      const m2 = cells[1].innerText.trim(); 
 +      output += `| ${naam.padEnd(25)} | ${m2.padStart(14)} |\n`; 
 +    } 
 +  }); 
 +  return output || "| Geen voorzieningen geselecteerd | – |"; 
 +
 + 
 +function buildPlankaartTableTXT() { 
 +  const opp = parseFloat(document.getElementById("opp").value) || 0; 
 +  const gsi = parseFloat(document.getElementById("gsi").value) || 0; 
 +  const footprint = gsi * opp; 
 +  const tuin = getVal("m2_tuinen"); 
 +  const uitgeefbaar = tuin + footprint; 
 + 
 +  return `Omschrijving                | Oppervlak (m²) 
 +----------------------------|---------------- 
 +Totaal bruto plangebied     | ${opp} 
 +----------------------------|---------------- 
 +Tuinen                      | ${tuin} 
 +Footprint (GSI x opp)       | ${footprint.toFixed(0)} 
 +----------------------------|---------------- 
 +Totaal uitgeefbaar          | ${uitgeefbaar.toFixed(0)} 
 +Rijbanen                    | ${getVal("m2_rijbanen")} 
 +Trottoirs                   | ${getVal("m2_trottoirs")} 
 +Parkeren (bovengr.)         | ${getVal("m2_parkeren")} 
 +Pleinen                     | ${getVal("m2_pleinen")} 
 +----------------------------|---------------- 
 +Totaal verharding           | ${(getVal("m2_rijbanen") + getVal("m2_trottoirs") + getVal("m2_parkeren") + getVal("m2_pleinen")).toFixed(0)} 
 +Groen                       | ${getVal("m2_groen")} 
 +Water                       | ${getVal("m2_water")}`; 
 +
 + 
 +function buildGrexTableTXT() { 
 +  return `Categorie           | Omschrijving                           | Oppervlak (m²) 
 +--------------------|----------------------------------------|---------------- 
 +Verwerving          | Percelen te verwerven of in te brengen | ${document.getElementById("opp").value} 
 +Grondwerk           | Graven watergangen                     | ${getVal("m2_water")} 
 +Bouwrijp maken      | Bouwstraten                            | ${getVal("m2_rijbanen")} 
 +Woonrijp maken      | Rijbanen                               | ${getVal("m2_rijbanen")} 
 +Woonrijp maken      | Trottoirs                              | ${getVal("m2_trottoirs")} 
 +Woonrijp maken      | Parkeren                               | ${getVal("m2_parkeren")} 
 +Woonrijp maken      | Pleinen                                | ${getVal("m2_pleinen")} 
 +Woonrijp maken      | Groen                                  | ${getVal("m2_groen")} 
 +Woonrijp maken      | Bomen en groenstructuur                |  
 +Woonrijp maken      | Verdere aankleding openbare ruimte     |  
 +Nazorg              | Herstraten bestratingen (10% rijbanen) | ${(getVal("m2_rijbanen") * 0.10).toFixed(0)} 
 +Onvoorzien          | Onvoorzien (5-15%)                     | `; 
 +
 + 
 +function getVal(id) { 
 +  const el = document.getElementById(id); 
 +  return el ? parseFloat(el.innerText.replace(" m²", "")) || 0 : 0; 
 +
 + 
 + 
 + 
 +window.onload = () => { 
 +  renderWoningtypes(); 
 +  maakVoorzieningentabel(); 
 +  updateLaadvermogen(); 
 +};
 </script> </script>
 +
 </body> </body>
 </html> </html>
- 
handleiding_nieuw/sub_spacematrix.1746607569.txt.gz · Last modified: 2025/05/07 08:46 by support