{"id":15269,"date":"2024-12-06T08:15:09","date_gmt":"2024-12-06T08:15:09","guid":{"rendered":"https:\/\/shareddocs.net\/?page_id=15269"},"modified":"2025-01-04T17:55:07","modified_gmt":"2025-01-04T17:55:07","slug":"nasa-collection","status":"publish","type":"page","link":"https:\/\/shareddocs.net\/index.php\/nasa-collection\/","title":{"rendered":"NASA &#8211; Collection"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"15269\" class=\"elementor elementor-15269\" data-elementor-post-type=\"page\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-7e1d579 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"7e1d579\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-6be62ef\" data-id=\"6be62ef\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-b236f55 elementor-widget elementor-widget-heading\" data-id=\"b236f55\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<h2 class=\"elementor-heading-title elementor-size-default\">DutchGreenhouses Climate Fetcher<\/h2>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-75f6f56 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"75f6f56\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-33 elementor-top-column elementor-element elementor-element-fc28ba7\" data-id=\"fc28ba7\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-33 elementor-top-column elementor-element elementor-element-7702bee\" data-id=\"7702bee\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-33 elementor-top-column elementor-element elementor-element-52350f8\" data-id=\"52350f8\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-0665e77 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"0665e77\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-33 elementor-top-column elementor-element elementor-element-848d57a\" data-id=\"848d57a\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-33 elementor-top-column elementor-element elementor-element-b7c487e\" data-id=\"b7c487e\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-33 elementor-top-column elementor-element elementor-element-397044d\" data-id=\"397044d\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-a1ce166 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"a1ce166\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-top-column elementor-element elementor-element-d9d03ae\" data-id=\"d9d03ae\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-017afb8 elementor-widget elementor-widget-html\" data-id=\"017afb8\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\" \/>\n  <title>Greenhouse Yield Predictor<\/title>\n  <link rel=\"stylesheet\" href=\"https:\/\/unpkg.com\/leaflet@1.9.4\/dist\/leaflet.css\" \/>\n  <script src=\"https:\/\/unpkg.com\/leaflet@1.9.4\/dist\/leaflet.js\"><\/script>\n  <style>\n    body {\n      font-family: Arial, sans-serif;\n      margin: 20px;\n    }\n    h1, h2 {\n      color: #2c3e50;\n    }\n    form {\n      margin-bottom: 20px;\n    }\n    label {\n      display: inline-block;\n      width: 220px;\n      vertical-align: top;\n    }\n    input[type=\"number\"],\n    input[type=\"text\"],\n    select {\n      padding: 5px;\n      margin-bottom: 10px;\n      width: 200px;\n    }\n    button {\n      padding: 10px 15px;\n      background-color: #2980b9;\n      color: white;\n      border: none;\n      cursor: pointer;\n      margin-top: 10px;\n      margin-right: 10px;\n    }\n    button:hover {\n      background-color: #1c5980;\n    }\n    table {\n      width: 100%;\n      border-collapse: collapse;\n      margin-bottom: 20px;\n    }\n    table, th, td {\n      border: 1px solid #bdc3c7;\n    }\n    th, td {\n      padding: 10px;\n      text-align: center;\n    }\n    #loadingFetch,\n    #loadingCalculate {\n      display: none;\n      margin-bottom: 10px;\n      color: #e74c3c;\n    }\n    textarea {\n      width: 100%;\n      padding: 10px;\n      resize: vertical;\n    }\n  <\/style>\n<\/head>\n\n<body>\n  <h1>Greenhouse Yield Predictor<\/h1>\n\n  <h2>Location Selector<\/h2>\n  <div id=\"map\" style=\"width: 100%; height: 400px;\"><\/div>\n\n  <form id=\"dataForm\">\n    <!-- Lat\/Lon -->\n    <div style=\"display: flex; align-items: center; gap: 10px; margin-bottom: 15px;\">\n      <label for=\"latitude\">Latitude:<\/label>\n      <input type=\"number\" id=\"latitude\" name=\"latitude\" step=\"0.01\" readonly \/>\n      <label for=\"longitude\">Longitude:<\/label>\n      <input type=\"number\" id=\"longitude\" name=\"longitude\" step=\"0.01\" readonly \/>\n    <\/div>\n\n    <!-- Start\/End Dates -->\n    <div style=\"display: flex; align-items: center; gap: 10px; margin-bottom: 15px;\">\n      <label for=\"startDate\">Start Date (YYYYMMDD):<\/label>\n      <input type=\"text\" id=\"startDate\" name=\"startDate\" readonly \/>\n      <label for=\"endDate\">End Date (YYYYMMDD):<\/label>\n      <input type=\"text\" id=\"endDate\" name=\"endDate\" readonly \/>\n    <\/div>\n\n    <!-- Light Interception -->\n    <label for=\"lightInterception\">Light Interception (%):<\/label>\n    <input\n      type=\"number\"\n      id=\"lightInterception\"\n      name=\"lightInterception\"\n      step=\"1\"\n      min=\"0\"\n      max=\"100\"\n      value=\"25\"\n      required\n    \/><br \/><br \/>\n\n    <!-- Required DLI -->\n    <label for=\"requiredDLI\">Required DLI (mol\/m\u00b2\/day):<\/label>\n    <input\n      type=\"number\"\n      id=\"requiredDLI\"\n      name=\"requiredDLI\"\n      step=\"0.1\"\n      value=\"20\"\n      required\n    \/><br \/><br \/>\n\n    <!-- Grow Light Intensity -->\n    <label for=\"growLightIntensity\">Grow Light Intensity (\u00b5mol\/s):<\/label>\n    <input\n      type=\"number\"\n      id=\"growLightIntensity\"\n      name=\"growLightIntensity\"\n      step=\"1\"\n      value=\"180\"\n      required\n    \/><br \/><br \/>\n\n    <!-- Max Supplemental Hours -->\n    <label for=\"maxSupplementalHours\">Max Supplemental Hours per Day:<\/label>\n    <input\n      type=\"number\"\n      id=\"maxSupplementalHours\"\n      name=\"maxSupplementalHours\"\n      step=\"0.1\"\n      min=\"0\"\n      max=\"24\"\n      value=\"18\"\n      required\n    \/><br \/><br \/>\n\n    <!-- Crop Selection -->\n    <label for=\"cropSelection\">Crop Selection:<\/label>\n    <select id=\"cropSelection\" name=\"cropSelection\" required>\n      <option value=\"\">--Select Crop--<\/option>\n      <option value=\"Tomato Cherry\">Tomato Cherry<\/option>\n      <option value=\"Tomato Cocktail\">Tomato Cocktail<\/option>\n      <option value=\"Tomato Large Vine\">Tomato Large Vine<\/option>\n      <option value=\"Tomato Beef\">Tomato Beef<\/option>\n    <\/select><br \/><br \/>\n\n    <!-- Planting Week -->\n    <label for=\"plantingWeek\">Planting Week (1-52):<\/label>\n    <input\n      type=\"number\"\n      id=\"plantingWeek\"\n      name=\"plantingWeek\"\n      min=\"1\"\n      max=\"52\"\n      required\n    \/><br \/><br \/>\n\n    <!-- DLI Threshold -->\n    <label for=\"dliThreshold\">DLI Threshold to Add Plants (mol\/m\u00b2\/day):<\/label>\n    <input\n      type=\"number\"\n      id=\"dliThreshold\"\n      name=\"dliThreshold\"\n      step=\"1\"\n      min=\"0\"\n      value=\"25\"\n      required\n    \/><br \/><br \/>\n\n    <!-- Plant Increment -->\n    <label for=\"plantIncrement\">Plant Increment per m\u00b2:<\/label>\n    <input\n      type=\"number\"\n      id=\"plantIncrement\"\n      name=\"plantIncrement\"\n      step=\"0.1\"\n      min=\"0\"\n      value=\"0.5\"\n      required\n    \/><br \/><br \/>\n\n    <!-- Plants per m\u00b2 -->\n    <label for=\"plantsPerSqM\">Plants per m\u00b2:<\/label>\n    <input\n      type=\"number\"\n      id=\"plantsPerSqM\"\n      name=\"plantsPerSqM\"\n      step=\"0.1\"\n      min=\"0\"\n      value=\"2.5\"\n      required\n    \/><br \/><br \/>\n\n    <!-- Buttons -->\n    <button type=\"button\" id=\"fetchButton\" onclick=\"fetchData()\">Fetch Data<\/button>\n    <button\n      type=\"button\"\n      id=\"calculateButton\"\n      onclick=\"calculateYield()\"\n      disabled\n    >\n      Calculate Yield\n    <\/button>\n  <\/form>\n\n  <!-- Loading Indicators -->\n  <div id=\"loadingFetch\">\n    <p>Fetching data, please wait...<\/p>\n  <\/div>\n  <div id=\"loadingCalculate\">\n    <p>Calculating yields, please wait...<\/p>\n  <\/div>\n\n  <h2>Response:<\/h2>\n  <textarea id=\"response\" rows=\"10\" readonly><\/textarea>\n\n  <!-- Monthly Summary -->\n  <h2>Monthly Summary<\/h2>\n  <table>\n    <thead>\n      <tr>\n        <th>Month<\/th>\n        <th>Avg Temp (\u00b0C)<\/th>\n        <th>Min Temp (\u00b0C)<\/th>\n        <th>Max Temp (\u00b0C)<\/th>\n        <th>Avg RH (%)<\/th>\n        <th>Avg DLI (mol\/m\u00b2\/day)<\/th>\n      <\/tr>\n    <\/thead>\n    <tbody id=\"summaryTable\"><\/tbody>\n  <\/table>\n\n  <!-- Heating and Daylight Requirement -->\n  <h2>Heating and Daylight Requirement<\/h2>\n  <table>\n    <thead>\n      <tr>\n        <th>Month<\/th>\n        <th>Gas Usage (m\u00b3\/m\u00b2)<\/th>\n        <th>Natural Sunlight Hours<\/th>\n        <th>Grow Light Duration (hours\/day)<\/th>\n      <\/tr>\n    <\/thead>\n    <tbody id=\"heatingTable\"><\/tbody>\n    <tfoot>\n      <tr>\n        <td>Total<\/td>\n        <td id=\"totalGasUsage\"><\/td>\n        <td id=\"totalSunlightHours\"><\/td>\n        <td id=\"totalGrowLightHours\"><\/td>\n      <\/tr>\n    <\/tfoot>\n  <\/table>\n\n  <!-- Expected Yield Table -->\n  <h2>Expected Yield<\/h2>\n  <table>\n    <thead>\n      <tr>\n        <th>Crop Type<\/th>\n        <th>Expected Yield per Truss (kg)<\/th>\n        <th>Total Trusses Harvested<\/th>\n        <th>Total Expected Yield (kg\/m\u00b2)<\/th>\n      <\/tr>\n    <\/thead>\n    <tbody id=\"yieldTable\"><\/tbody>\n  <\/table>\n\n  <!-- Weekly Yield Table -->\n  <h2>Weekly Yield Summary<\/h2>\n  <table id=\"weeklyYieldTable\">\n    <thead>\n      <tr>\n        <th>Harvest Week<\/th>\n        <th>ISO Week Number<\/th>\n        <th>Sunlight (kg\/m\u00b2)<\/th>\n        <th>Grow Light (kg\/m\u00b2)<\/th>\n        <th>Total (kg\/m\u00b2)<\/th>\n      <\/tr>\n    <\/thead>\n    <tbody><\/tbody>\n    <tfoot>\n      <tr>\n        <td colspan=\"2\"><strong>Q1 Total<\/strong><\/td>\n        <td colspan=\"3\" id=\"Q1Total\"><\/td>\n      <\/tr>\n      <tr>\n        <td colspan=\"2\"><strong>Q2 Total<\/strong><\/td>\n        <td colspan=\"3\" id=\"Q2Total\"><\/td>\n      <\/tr>\n      <tr>\n        <td colspan=\"2\"><strong>Q3 Total<\/strong><\/td>\n        <td colspan=\"3\" id=\"Q3Total\"><\/td>\n      <\/tr>\n      <tr>\n        <td colspan=\"2\"><strong>Q4 Total<\/strong><\/td>\n        <td colspan=\"3\" id=\"Q4Total\"><\/td>\n      <\/tr>\n      <tr>\n        <td colspan=\"2\"><strong>Overall Total<\/strong><\/td>\n        <td colspan=\"3\" id=\"overallTotal\"><\/td>\n      <\/tr>\n    <\/tfoot>\n  <\/table>\n\n  <button type=\"button\" onclick=\"downloadResults()\">Download Results<\/button>\n\n  <script>\n    \/\/ Crop yield mapping\n    const cropYieldMapping = {\n      \"Tomato Cherry\": 120,\n      \"Tomato Cocktail\": 400,\n      \"Tomato Large Vine\": 660,\n      \"Tomato Beef\": 1200\n    };\n\n    \/\/ Trusses per plant mapping\n    const trussesPerPlantMapping = {\n      \"Tomato Cherry\": 5,\n      \"Tomato Cocktail\": 6,\n      \"Tomato Large Vine\": 7,\n      \"Tomato Beef\": 8\n    };\n\n    let map, marker;\n    let fetchedData = \"\";\n    let weeklyYields = [];\n\n    \/**************************************************************\n     * 1. Leaflet + Geolocation\n     **************************************************************\/\n    document.addEventListener(\"DOMContentLoaded\", () => {\n      initializeMap();\n      getUserLocation();\n    });\n\n    function initializeMap() {\n      const defaultLoc = { lat: 52.0, lng: 5.0 };\n      map = L.map(\"map\").setView([defaultLoc.lat, defaultLoc.lng], 10);\n\n      L.tileLayer(\"https:\/\/{s}.tile.openstreetmap.org\/{z}\/{x}\/{y}.png\", {\n        maxZoom: 19,\n        attribution: \"&copy; OpenStreetMap contributors\"\n      }).addTo(map);\n\n      marker = L.marker(defaultLoc, { draggable: true }).addTo(map);\n\n      marker.on(\"dragend\", () => {\n        const pos = marker.getLatLng();\n        document.getElementById(\"latitude\").value = pos.lat.toFixed(2);\n        document.getElementById(\"longitude\").value = pos.lng.toFixed(2);\n      });\n\n      map.on(\"click\", (e) => {\n        const pos = e.latlng;\n        marker.setLatLng(pos);\n        document.getElementById(\"latitude\").value = pos.lat.toFixed(2);\n        document.getElementById(\"longitude\").value = pos.lng.toFixed(2);\n      });\n    }\n\n    function getUserLocation() {\n      if (navigator.geolocation) {\n        navigator.geolocation.getCurrentPosition(\n          (pos) => {\n            setMapLocation({ lat: pos.coords.latitude, lng: pos.coords.longitude });\n          },\n          () => {\n            console.warn(\"Geolocation blocked. Using IP fallback...\");\n            getLocationFromIP();\n          }\n        );\n      } else {\n        console.warn(\"No geolocation. Using IP fallback.\");\n        getLocationFromIP();\n      }\n    }\n\n    function getLocationFromIP() {\n      fetch(\"https:\/\/ipapi.co\/json\/\")\n        .then((resp) => resp.json())\n        .then((data) => {\n          if (data.latitude && data.longitude) {\n            setMapLocation({ lat: data.latitude, lng: data.longitude });\n          } else {\n            console.error(\"IP-based location data incomplete.\");\n          }\n        })\n        .catch((err) => console.error(\"IP-based location error:\", err));\n    }\n\n    function setMapLocation(loc) {\n      map.setView([loc.lat, loc.lng], 10);\n      marker.setLatLng(loc);\n      document.getElementById(\"latitude\").value = loc.lat.toFixed(2);\n      document.getElementById(\"longitude\").value = loc.lng.toFixed(2);\n    }\n\n    \/**************************************************************\n     * 2. NASA Data Fetch\n     **************************************************************\/\n    function fetchData() {\n      const latitude = parseFloat(document.getElementById(\"latitude\").value);\n      const longitude = parseFloat(document.getElementById(\"longitude\").value);\n\n      if (isNaN(latitude) || isNaN(longitude)) {\n        alert(\"Select a valid location on the map first.\");\n        return;\n      }\n\n      const startDate = \"20230101\";\n      const endDate = \"20231231\";\n      document.getElementById(\"startDate\").value = startDate;\n      document.getElementById(\"endDate\").value = endDate;\n\n      const baseUrl = \"https:\/\/power.larc.nasa.gov\/api\/temporal\/hourly\/point\";\n      const parameters = \"ALLSKY_SFC_SW_DNI,T2M,RH2M\";\n      const community = \"AG\";\n      const format = \"csv\";\n\n      const url = `${baseUrl}?parameters=${parameters}&community=${community}&latitude=${latitude}&longitude=${longitude}&start=${startDate}&end=${endDate}&format=${format}`;\n      console.log(\"Fetching from:\", url);\n\n      document.getElementById(\"loadingFetch\").style.display = \"block\";\n      document.getElementById(\"fetchButton\").disabled = true;\n      document.getElementById(\"calculateButton\").disabled = true;\n      document.getElementById(\"response\").value = \"Fetching data...\";\n\n      clearPreviousResults();\n\n      fetch(url)\n        .then((resp) => {\n          if (!resp.ok) {\n            throw new Error(`HTTP error! status: ${resp.status}`);\n          }\n          return resp.text();\n        })\n        .then((data) => {\n          console.log(\"Data fetched successfully from NASA.\");\n          const stripped = removeHeaders(data);\n          fetchedData = stripped;\n          document.getElementById(\"response\").value = stripped;\n          \/\/ Populate monthly tables now\n          populateMonthlyAndHeatingTables(stripped);\n          document.getElementById(\"calculateButton\").disabled = false;\n        })\n        .catch((err) => {\n          document.getElementById(\"response\").value = `Error: ${err.message}`;\n          console.error(\"Fetch Data Error:\", err);\n          alert(`Error fetching data: ${err.message}`);\n        })\n        .finally(() => {\n          document.getElementById(\"loadingFetch\").style.display = \"none\";\n          document.getElementById(\"fetchButton\").disabled = false;\n        });\n    }\n\n    function removeHeaders(data) {\n      const lines = data.split(\"\\n\");\n      let inHeader = false;\n      const filtered = lines.filter((line) => {\n        if (line.includes(\"-BEGIN HEADER-\")) {\n          inHeader = true;\n          return false;\n        } else if (line.includes(\"-END HEADER-\")) {\n          inHeader = false;\n          return false;\n        }\n        return !inHeader;\n      });\n      return filtered.join(\"\\n\");\n    }\n\n    function clearPreviousResults() {\n      document.getElementById(\"summaryTable\").innerHTML = \"\";\n      document.getElementById(\"heatingTable\").innerHTML = \"\";\n      document.getElementById(\"yieldTable\").innerHTML = \"\";\n      document.getElementById(\"weeklyYieldTable\").querySelector(\"tbody\").innerHTML = \"\";\n      document.getElementById(\"Q1Total\").textContent = \"\";\n      document.getElementById(\"Q2Total\").textContent = \"\";\n      document.getElementById(\"Q3Total\").textContent = \"\";\n      document.getElementById(\"Q4Total\").textContent = \"\";\n      document.getElementById(\"overallTotal\").textContent = \"\";\n    }\n\n    \/**************************************************************\n     * 3. Populate Monthly Summaries\n     **************************************************************\/\n    function populateMonthlyAndHeatingTables(csvData) {\n      const rows = csvData.split(\"\\n\").slice(1).filter((r) => r.trim() !== \"\");\n      if (!rows.length) {\n        console.warn(\"No data rows for monthly summary.\");\n        return;\n      }\n\n      const dailyData = rows.map((row) => {\n        const [year, month, day, hour, dniMJhr, temp, rh] = row\n          .split(\",\")\n          .map((val) => parseFloat(val));\n        return { year, month, day, hour, dniMJhr, temp, rh };\n      });\n\n      let totalGasUsage = 0;\n      let totalGrowLightHours = 0;\n      let totalSunlightHours = 0;\n\n      const monthlyData = {};\n\n      dailyData.forEach((entry) => {\n        const { month, temp, rh, dniMJhr } = entry;\n        if (!monthlyData[month]) {\n          monthlyData[month] = {\n            temps: [],\n            rhs: [],\n            dailyDLI: {},\n            gasUsage: 0,\n            growLightHours: 0,\n            sunlightHours: 0\n          };\n        }\n        monthlyData[month].temps.push(temp);\n        monthlyData[month].rhs.push(rh);\n\n        \/\/ Convert from MJ\/hr -> sunlight DLI (mol\/m\u00b2\/hr)\n        \/\/ with (1 - lightInterception)\n        const fraction = 1 - parseFloat(document.getElementById(\"lightInterception\").value) \/ 100;\n        const hourDLI = fraction * dniMJhr * 1e6 * 0.48 * 4.57 \/ 1e6; \/\/ mol\/m\u00b2\/hour\n\n        const dayKey = `${entry.year}-${entry.month}-${entry.day}`;\n        if (!monthlyData[month].dailyDLI[dayKey]) {\n          monthlyData[month].dailyDLI[dayKey] = 0;\n        }\n        monthlyData[month].dailyDLI[dayKey] += hourDLI;\n\n        \/\/ Pseudo sunlight hour check\n        if (dniMJhr * (1e6 \/ 3600) > 10) {\n          monthlyData[month].sunlightHours++;\n        }\n\n        \/\/ Gas usage if T < 18\n        if (temp < 18) {\n          const heatLoss = 5.6 * (18 - temp);\n          monthlyData[month].gasUsage += heatLoss \/ 10550;\n        }\n      });\n\n      \/\/ Summaries\n      Object.entries(monthlyData).forEach(([m, data]) => {\n        const dayKeys = Object.keys(data.dailyDLI);\n        const daysInMonth = dayKeys.length;\n\n        let monthlyGrowLightHours = 0;\n        dayKeys.forEach((dk) => {\n          const dailyDLI = data.dailyDLI[dk];\n          const requiredDLI = parseFloat(document.getElementById(\"requiredDLI\").value);\n          const growLightIntensity = parseFloat(\n            document.getElementById(\"growLightIntensity\").value\n          );\n          const supDLIperHour = (growLightIntensity * 3600) \/ 1e6; \/\/ mol\/hour\n\n          const needed = Math.max(0, requiredDLI - dailyDLI);\n          const hrsNeeded = needed \/ supDLIperHour;\n          const maxSupplementalHours = parseFloat(\n            document.getElementById(\"maxSupplementalHours\").value\n          );\n          monthlyGrowLightHours += Math.min(hrsNeeded, maxSupplementalHours);\n        });\n\n        data.growLightHours = monthlyGrowLightHours;\n        totalGrowLightHours += monthlyGrowLightHours;\n        totalGasUsage += data.gasUsage;\n        totalSunlightHours += data.sunlightHours;\n\n        const avgTemp = data.temps.reduce((a, b) => a + b, 0) \/ data.temps.length;\n        const avgRH = data.rhs.reduce((a, b) => a + b, 0) \/ data.rhs.length;\n\n        const totalDLI = Object.values(data.dailyDLI).reduce((a, b) => a + b, 0);\n        const avgDLI = (totalDLI \/ daysInMonth).toFixed(2);\n\n        \/\/ Summaries\n        document.getElementById(\"summaryTable\").innerHTML += `\n          <tr>\n            <td>${m}<\/td>\n            <td>${avgTemp.toFixed(2)}<\/td>\n            <td>${Math.min(...data.temps).toFixed(2)}<\/td>\n            <td>${Math.max(...data.temps).toFixed(2)}<\/td>\n            <td>${avgRH.toFixed(2)}<\/td>\n            <td>${avgDLI}<\/td>\n          <\/tr>`;\n        \n        document.getElementById(\"heatingTable\").innerHTML += `\n          <tr>\n            <td>${m}<\/td>\n            <td>${data.gasUsage.toFixed(2)}<\/td>\n            <td>${(data.sunlightHours \/ daysInMonth).toFixed(2)}<\/td>\n            <td>${(monthlyGrowLightHours \/ daysInMonth).toFixed(2)}<\/td>\n          <\/tr>`;\n      });\n\n      document.getElementById(\"totalGasUsage\").textContent = totalGasUsage.toFixed(2);\n      document.getElementById(\"totalSunlightHours\").textContent = (totalSunlightHours \/ 365).toFixed(2);\n      document.getElementById(\"totalGrowLightHours\").textContent = totalGrowLightHours.toFixed(2);\n    }\n\n    \/**************************************************************\n     * 4. Multi-Harvest Calculate\n     **************************************************************\/\n    function calculateYield() {\n      console.log(\"calculateYield() triggered.\");\n\n      if (!fetchedData) {\n        alert(\"Please fetch NASA data first.\");\n        return;\n      }\n\n      document.getElementById(\"loadingCalculate\").style.display = \"block\";\n      document.getElementById(\"calculateButton\").disabled = true;\n\n      try {\n        const cropSelection = document.getElementById(\"cropSelection\").value;\n        if (!cropSelection) {\n          alert(\"Please select a crop.\");\n          throw new Error(\"Crop not selected.\");\n        }\n\n        const plantingWeek = parseInt(document.getElementById(\"plantingWeek\").value, 10);\n        if (isNaN(plantingWeek) || plantingWeek < 1 || plantingWeek > 52) {\n          alert(\"Please enter a valid planting week (1-52).\");\n          throw new Error(\"Invalid planting week.\");\n        }\n\n        const dliThreshold = parseFloat(document.getElementById(\"dliThreshold\").value);\n        const plantIncrement = parseFloat(document.getElementById(\"plantIncrement\").value);\n        const plantsPerSqMInitial = parseFloat(document.getElementById(\"plantsPerSqM\").value);\n        const requiredDLI = parseFloat(document.getElementById(\"requiredDLI\").value);\n        const growLightIntensity = parseFloat(document.getElementById(\"growLightIntensity\").value);\n        const maxSupplementalHours = parseFloat(document.getElementById(\"maxSupplementalHours\").value);\n        const gramsPerTruss = cropYieldMapping[cropSelection];\n        const trussesPerPlant = trussesPerPlantMapping[cropSelection] || 6; \/\/ Default to 6\n\n        if (isNaN(dliThreshold) || dliThreshold < 0) {\n          alert(\"Please enter a valid DLI threshold.\");\n          throw new Error(\"Invalid DLI threshold.\");\n        }\n\n        if (isNaN(plantIncrement) || plantIncrement < 0) {\n          alert(\"Please enter a valid plant increment.\");\n          throw new Error(\"Invalid plant increment.\");\n        }\n\n        if (isNaN(plantsPerSqMInitial) || plantsPerSqMInitial < 0) {\n          alert(\"Please enter a valid number of plants per m\u00b2.\");\n          throw new Error(\"Invalid plants per m\u00b2.\");\n        }\n\n        \/\/ Parse CSV\n        const rows = fetchedData.split(\"\\n\").slice(1).filter(r => r.trim() !== \"\");\n        if (!rows.length) {\n          console.warn(\"No CSV rows => yield = 0\");\n          alert(\"No data available for yield calculation.\");\n          throw new Error(\"No data available.\");\n        }\n        const dailyData = rows.map(row => {\n          const [year, month, day, hour, dniMJhr, temp, rh] = row\n            .split(\",\")\n            .map(val => parseFloat(val));\n          return { year, month, day, hour, dniMJhr, temp, rh };\n        });\n\n        \/\/ Adjust plant density if first 3 days above threshold\n        let adjustedPlantsPerSqM = plantsPerSqMInitial;\n        const plantingDate = getDateOfISOWeek(plantingWeek, 2023);\n        let consecutiveDaysAbove = 0;\n\n        const firstThreeDaysData = dailyData.filter(entry => {\n          const eDate = new Date(entry.year, entry.month - 1, entry.day);\n          return eDate >= plantingDate && eDate < new Date(plantingDate.getTime() + 3 * 24 * 60 * 60 * 1000);\n        });\n\n        \/\/ Aggregate daily DLI\n        const dailyDLIMap = {};\n        firstThreeDaysData.forEach(entry => {\n          const dayKey = `${entry.year}-${entry.month}-${entry.day}`;\n          if (!dailyDLIMap[dayKey]) {\n            dailyDLIMap[dayKey] = 0;\n          }\n          const hourDLI_Sun = entry.dniMJhr * 1e6 * 0.48 * 4.57 \/ 1e6;\n          dailyDLIMap[dayKey] += hourDLI_Sun;\n        });\n\n        const sortedDays = Object.keys(dailyDLIMap).sort();\n        for (let day of sortedDays) {\n          const dailyDLI = dailyDLIMap[day];\n          if (dailyDLI > dliThreshold) {\n            consecutiveDaysAbove++;\n            if (consecutiveDaysAbove >= 3) {\n              adjustedPlantsPerSqM += plantIncrement;\n              console.log(\"Incrementing plants to:\", adjustedPlantsPerSqM);\n              break; \/\/ Increment only once after 3 consecutive days\n            }\n          } else {\n            consecutiveDaysAbove = 0;\n          }\n        }\n        const finalPlantsPerSqM = parseFloat(adjustedPlantsPerSqM.toFixed(1));\n\n        \/\/ Harvest weeks\n        const harvestWeeks = calculateHarvestWeeks(plantingWeek, 2023);\n\n        \/\/ Now do the splitted yield logic\n        const results = calculateDLIAndYield_SeparateSunArtificial(dailyData, {\n          requiredDLI,\n          growLightIntensity,\n          maxSupplementalHours,\n          gramsPerTruss,\n          harvestWeeks,\n          maxTotalDLI: 1200,\n          adjustedPlantsPerSqM: finalPlantsPerSqM,\n          trussesPerPlant \/\/ Added parameter\n        });\n\n        console.log(\"Final splitted yield results:\", results);\n\n        \/\/ Calculate total trusses harvested\n        const totalTrussesHarvested = finalPlantsPerSqM * trussesPerPlant;\n\n        \/\/ Calculate average yield per truss\n        const overall = results.overallTotalYield;\n        const avgTrussYield = overall \/ totalTrussesHarvested;\n\n        \/\/ Populate Expected Yield Table\n        document.getElementById(\"yieldTable\").innerHTML = `\n          <tr>\n            <td>${cropSelection}<\/td>\n            <td>${(avgTrussYield).toFixed(2).replace(\".\",\",\")}<\/td>\n            <td>${totalTrussesHarvested}<\/td>\n            <td>${overall.toFixed(2).replace(\".\",\",\")}<\/td>\n          <\/tr>\n        `;\n\n        \/\/ Fill Weekly splitted yield table\n        populateWeeklyYieldTable_Separate(results.weeklyYields);\n\n      } catch (err) {\n        console.error(\"Yield Calc Error:\", err);\n        \/\/ Alert already shown where necessary\n      } finally {\n        document.getElementById(\"loadingCalculate\").style.display = \"none\";\n        document.getElementById(\"calculateButton\").disabled = false;\n      }\n    }\n\n    \/**\n     * Splitted sun vs. artificial yield logic\n     * Each harvest window => sums daily sunlight DLI + needed artificial, up to requiredDLI\n     *\/\n    function calculateDLIAndYield_SeparateSunArtificial(dailyData, settings) {\n      const {\n        requiredDLI,\n        growLightIntensity,\n        maxSupplementalHours,\n        gramsPerTruss,\n        harvestWeeks,\n        maxTotalDLI,\n        adjustedPlantsPerSqM,\n        trussesPerPlant \/\/ New parameter\n      } = settings;\n\n      const PARFraction = 0.48;\n      const \u00b5molPerJ = 4.57;\n      const MJtoJ = 1e6;\n      const \u00b5molToMol = 1e6;\n      const weeklyYields = [];\n      let overallTotalYield = 0;\n\n      const trussesPerSqM = adjustedPlantsPerSqM * trussesPerPlant;\n\n      harvestWeeks.forEach(hw => {\n        \/\/ 49 day window\n        const startDate = new Date(hw.date);\n        startDate.setDate(startDate.getDate() - 49);\n        const endDate = new Date(hw.date);\n        endDate.setDate(endDate.getDate() -1);\n\n        let sumSunlightDLI = 0;\n        let sumArtificialDLI = 0;\n\n        const windowData = dailyData.filter(entry => {\n          const eDate = new Date(entry.year, entry.month -1, entry.day);\n          return eDate >= startDate && eDate <= endDate;\n        });\n\n        \/\/ Aggregate daily DLI\n        const dailyDLIMap = {};\n        windowData.forEach(entry => {\n          const dayKey = `${entry.year}-${entry.month}-${entry.day}`;\n          if (!dailyDLIMap[dayKey]) {\n            dailyDLIMap[dayKey] = 0;\n          }\n          const hourDLI_Sun = entry.dniMJhr * MJtoJ * PARFraction * \u00b5molPerJ \/ \u00b5molToMol;\n          dailyDLIMap[dayKey] += hourDLI_Sun;\n        });\n\n        const daysInWindow = Object.keys(dailyDLIMap).length;\n\n        Object.values(dailyDLIMap).forEach(dailyDLI => {\n          sumSunlightDLI += dailyDLI;\n          const neededDLI = Math.max(0, requiredDLI - dailyDLI);\n          const growLightMolPerHour = (growLightIntensity * 3600) \/ 1e6; \/\/ mol\/hour\n\n          const hrsNeeded = neededDLI \/ growLightMolPerHour;\n          const hrsSupplemented = Math.min(hrsNeeded, maxSupplementalHours);\n          const artiDLI = hrsSupplemented * growLightMolPerHour;\n\n          sumArtificialDLI += artiDLI;\n        });\n\n        \/\/ average daily DLI\n        const avgSunDLI = sumSunlightDLI \/ daysInWindow;\n        const avgArtiDLI = sumArtificialDLI \/ daysInWindow;\n        const totalDLI = avgSunDLI + avgArtiDLI;\n\n        \/\/ If totalDLI > maxTotalDLI => cap\n        const totalPct = (totalDLI \/ requiredDLI) * 100;\n        const maxPct = (maxTotalDLI \/ requiredDLI) * 100;\n        let finalPct = Math.min(totalPct, maxPct);\n\n        \/\/ Percentages from sun and artificial\n        let sunPct = (avgSunDLI \/ requiredDLI) * 100;\n        let artiPct = (avgArtiDLI \/ requiredDLI) * 100;\n\n        \/\/ Ensure percentages don't exceed 100%\n        sunPct = Math.min(sunPct, 100);\n        artiPct = Math.min(artiPct, 100 - sunPct);\n\n        \/\/ Yield per truss from sun vs. artificial\n        const yieldSunTruss_kg = (gramsPerTruss * (sunPct \/ 100)) \/ 1000;\n        const yieldArtiTruss_kg = (gramsPerTruss * (artiPct \/ 100)) \/ 1000;\n        const yieldTotalTruss_kg = yieldSunTruss_kg + yieldArtiTruss_kg;\n\n        \/\/ Total yield per square meter\n        const yieldSun_kgm2 = yieldSunTruss_kg * trussesPerSqM;\n        const yieldArti_kgm2 = yieldArtiTruss_kg * trussesPerSqM;\n        const yieldTotal_kgm2 = yieldSun_kgm2 + yieldArti_kgm2;\n\n        weeklyYields.push({\n          week: hw.week,\n          weekNumber: hw.weekNumber,\n          yieldSun: yieldSun_kgm2,\n          yieldArti: yieldArti_kgm2,\n          yieldTotal: yieldTotal_kgm2\n        });\n        overallTotalYield += yieldTotal_kgm2;\n      });\n\n      return { weeklyYields, overallTotalYield };\n    }\n\n    \/**\n     * We create 41 harvest windows from plantingWeek\n     *\/\n    function calculateHarvestWeeks(plantingWeek, year) {\n      const list = [];\n      for (let i = 0; i < 41; i++) {\n        let wNum = plantingWeek + i + 9;\n        if (wNum > 52) wNum -= 52;\n        const dateForWeek = getDateOfISOWeek(wNum, year);\n        list.push({\n          week: i + 1,\n          weekNumber: wNum,\n          date: dateForWeek\n        });\n      }\n      return list;\n    }\n\n    function getDateOfISOWeek(w, y) {\n      const simple = new Date(y, 0, 1 + (w - 1) * 7);\n      const dow = simple.getDay();\n      const isoStart = new Date(simple);\n      if (dow <= 4) {\n        isoStart.setDate(simple.getDate() - simple.getDay() + 1);\n      } else {\n        isoStart.setDate(simple.getDate() + 8 - simple.getDay());\n      }\n      return isoStart;\n    }\n\n    \/**************************************************************\n     * 5. Populate Weekly Table\n     **************************************************************\/\n    function populateWeeklyYieldTable_Separate(weeklyYields) {\n      const tbody = document.getElementById(\"weeklyYieldTable\").querySelector(\"tbody\");\n      let tableHTML = \"\";\n\n      let Q1Total = 0, Q2Total = 0, Q3Total = 0, Q4Total = 0, overallTotal = 0;\n\n      weeklyYields.forEach(hw => {\n        const s = hw.yieldSun.toFixed(3).replace(\".\", \",\");\n        const a = hw.yieldArti.toFixed(3).replace(\".\", \",\");\n        const t = hw.yieldTotal.toFixed(3).replace(\".\", \",\");\n\n        tableHTML += `<tr>\n          <td>${hw.week}<\/td>\n          <td>${hw.weekNumber}<\/td>\n          <td>${s}<\/td>\n          <td>${a}<\/td>\n          <td>${t}<\/td>\n        <\/tr>`;\n\n        if (hw.weekNumber >= 1 && hw.weekNumber <= 13) {\n          Q1Total += hw.yieldTotal;\n        } else if (hw.weekNumber >= 14 && hw.weekNumber <= 26) {\n          Q2Total += hw.yieldTotal;\n        } else if (hw.weekNumber >= 27 && hw.weekNumber <= 39) {\n          Q3Total += hw.yieldTotal;\n        } else {\n          Q4Total += hw.yieldTotal;\n        }\n        overallTotal += hw.yieldTotal;\n      });\n\n      tbody.innerHTML = tableHTML;\n\n      document.getElementById(\"Q1Total\").textContent = Q1Total.toFixed(3).replace(\".\", \",\");\n      document.getElementById(\"Q2Total\").textContent = Q2Total.toFixed(3).replace(\".\", \",\");\n      document.getElementById(\"Q3Total\").textContent = Q3Total.toFixed(3).replace(\".\", \",\");\n      document.getElementById(\"Q4Total\").textContent = Q4Total.toFixed(3).replace(\".\", \",\");\n      document.getElementById(\"overallTotal\").textContent = overallTotal.toFixed(3).replace(\".\", \",\");\n    }\n\n    \/**************************************************************\n     * 6. Download Results\n     **************************************************************\/\n    function downloadResults() {\n      let csvContent = \"data:text\/csv;charset=utf-8,\";\n\n      \/\/ Monthly Summary\n      csvContent += \"Monthly Summary\\n\";\n      csvContent += \"Month,Avg Temp (\u00b0C),Min Temp (\u00b0C),Max Temp (\u00b0C),Avg RH (%),Avg DLI (mol\/m\u00b2\/day)\\n\";\n      const summaryRows = document.querySelectorAll(\"#summaryTable tr\");\n      summaryRows.forEach(row => {\n        const cols = row.querySelectorAll(\"td\");\n        const rowData = Array.from(cols).map(col => `\"${col.innerText}\"`).join(\",\");\n        csvContent += rowData + \"\\n\";\n      });\n\n      \/\/ Heating\n      csvContent += \"\\nHeating and Daylight Requirement\\n\";\n      csvContent += \"Month,Gas Usage (m\u00b3\/m\u00b2),Natural Sunlight Hours,Grow Light Duration (hours\/day)\\n\";\n      const heatingRows = document.querySelectorAll(\"#heatingTable tr\");\n      heatingRows.forEach(row => {\n        const cols = row.querySelectorAll(\"td\");\n        const rowData = Array.from(cols).map(col => `\"${col.innerText}\"`).join(\",\");\n        csvContent += rowData + \"\\n\";\n      });\n\n      \/\/ Expected Yield\n      csvContent += \"\\nExpected Yield\\n\";\n      csvContent += \"Crop Type,Expected Yield per Truss (kg),Total Trusses Harvested,Total Expected Yield (kg\/m\u00b2)\\n\";\n      const yieldRows = document.querySelectorAll(\"#yieldTable tr\");\n      yieldRows.forEach(row => {\n        const cols = row.querySelectorAll(\"td\");\n        const rowData = Array.from(cols).map(col => `\"${col.innerText}\"`).join(\",\");\n        csvContent += rowData + \"\\n\";\n      });\n\n      \/\/ Weekly Yields\n      csvContent += \"\\nWeekly Yield Summary\\n\";\n      csvContent += \"Harvest Week,ISO Week Number,Sunlight (kg\/m\u00b2),Grow Light (kg\/m\u00b2),Total (kg\/m\u00b2)\\n\";\n      const weeklyRows = document.querySelectorAll(\"#weeklyYieldTable tbody tr\");\n      weeklyRows.forEach(row => {\n        const cols = row.querySelectorAll(\"td\");\n        const rowData = Array.from(cols).map(col => `\"${col.innerText}\"`).join(\",\");\n        csvContent += rowData + \"\\n\";\n      });\n\n      \/\/ Q1..Q4\n      csvContent += \"\\nQuarterly Totals\\n\";\n      csvContent += \"Q1 Total,Q2 Total,Q3 Total,Q4 Total\\n\";\n      const q1Total = document.getElementById(\"Q1Total\").textContent;\n      const q2Total = document.getElementById(\"Q2Total\").textContent;\n      const q3Total = document.getElementById(\"Q3Total\").textContent;\n      const q4Total = document.getElementById(\"Q4Total\").textContent;\n      csvContent += `\"${q1Total}\",\"${q2Total}\",\"${q3Total}\",\"${q4Total}\"\\n`;\n\n      \/\/ Overall\n      csvContent += \"\\nOverall Total\\n\";\n      csvContent += `\"${document.getElementById(\"overallTotal\").textContent}\"\\n`;\n\n      const encodedUri = encodeURI(csvContent);\n      const link = document.createElement(\"a\");\n      link.setAttribute(\"href\", encodedUri);\n      link.setAttribute(\"download\", \"climate_summary.csv\");\n      document.body.appendChild(link);\n      link.click();\n      document.body.removeChild(link);\n    }\n  <\/script>\n<\/body>\n<\/html>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-top-column elementor-element elementor-element-5a674cf\" data-id=\"5a674cf\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap\">\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-e8fe613 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"e8fe613\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-f98f094\" data-id=\"f98f094\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>DutchGreenhouses Climate Fetcher Greenhouse Yield Predictor Greenhouse Yield Predictor Location Selector Latitude: Longitude: Start Date (YYYYMMDD): End Date (YYYYMMDD): Light Interception (%): Required DLI (mol\/m\u00b2\/day): Grow Light Intensity (\u00b5mol\/s): Max Supplemental Hours per Day: Crop Selection: &#8211;Select Crop&#8211;Tomato CherryTomato CocktailTomato Large VineTomato Beef Planting Week (1-52): DLI Threshold to Add Plants (mol\/m\u00b2\/day): Plant Increment per [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"class_list":["post-15269","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/shareddocs.net\/index.php\/wp-json\/wp\/v2\/pages\/15269","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/shareddocs.net\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/shareddocs.net\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/shareddocs.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/shareddocs.net\/index.php\/wp-json\/wp\/v2\/comments?post=15269"}],"version-history":[{"count":169,"href":"https:\/\/shareddocs.net\/index.php\/wp-json\/wp\/v2\/pages\/15269\/revisions"}],"predecessor-version":[{"id":15475,"href":"https:\/\/shareddocs.net\/index.php\/wp-json\/wp\/v2\/pages\/15269\/revisions\/15475"}],"wp:attachment":[{"href":"https:\/\/shareddocs.net\/index.php\/wp-json\/wp\/v2\/media?parent=15269"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}