diff --git a/public/udigit4icity/index.html b/public/udigit4icity/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..a17e0b824a857768e9e047c9b5c0d3ab2c7698aa
--- /dev/null
+++ b/public/udigit4icity/index.html
@@ -0,0 +1,1164 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>Integrated Web Map and ECharts</title>
+
+  <link rel="stylesheet" href="https://js.arcgis.com/4.28/esri/css/main.css">
+
+  <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
+  <script src="https://api.mapbox.com/mapbox.js/v3.3.1/mapbox.js"></script>
+  <link href="https://api.mapbox.com/mapbox.js/v3.3.1/mapbox.css" rel="stylesheet" />
+  <!-- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/echarts@5.0.0/dist/echarts.min.css">
+  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/echarts-gl@5.0.0/dist/echarts-gl.min.css"> -->
+  <link rel="stylesheet" href="https://js.arcgis.com/4.28/esri/themes/dark/main.css" />
+
+  <style>
+     body {
+         font-size: 16px
+        }
+
+        #chartControls label,
+        #chartControls select,
+        #chartControls button {
+            font-size: 16px; 
+            margin-bottom: 15px
+        }
+
+    html {
+      margin: 0;
+      padding: 0;
+      height: 100%;
+      overflow: hidden;
+    }
+
+    #usage-pie-chart-container {
+      z-index: 1; 
+      position: absolute;
+      top:10px; 
+      right: 0px; 
+      width: 20%; 
+      height: 0.2px;
+      bottom:10%;
+    }
+
+    #mainMenu {
+      position: absolute;
+      top: 10px;
+      left: 60px;
+      z-index: 4;
+      background-color: rgba(53, 51, 51, 0.8);
+      padding: 8px;
+      border-radius: 5px;
+      display: flex;
+      flex-direction: column;
+    }
+
+    #mainMenu label {
+      margin-bottom: 5px;
+    }
+
+    #mainMenu button {
+      margin-top: 10px;
+      padding: 5px 10px;
+      cursor: pointer;
+    }
+
+    #main-menu {
+      width: 20%; 
+      height: 100%;
+      background-color: #2c3e50; 
+      color: rgb(91, 89, 89);
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      padding-top: 20px;
+    }
+
+    #container {
+      display: flex;
+      width: 100%;
+      height: 100vh;
+      flex-direction: row; 
+    }
+
+    #main {
+
+      width: 36%;
+      height: 65%;
+      position:relative;
+      top:35%;
+      right:0;
+      z-index: 1;
+
+    }
+
+    #viewDiv {
+
+      width: 100%;
+      height: 100%;
+      position: absolute;
+      top:0;
+      right:0;
+
+    }
+
+    #spaceTimeCubeContainer {
+      display: none;
+    }
+
+    .legend-building {
+      position: absolute;
+      bottom: 10px;
+      right: 10px;
+      padding: 5px;
+      background-color: rgba(255, 255, 255, 0.8);
+      border-radius: 5px;
+      z-index: 1;
+      display: flex;
+      flex-direction: column;
+    }
+
+    .legend {
+    position: absolute;
+    top: 90%;
+    left: 36%;
+    padding: 5px;
+    background-color: rgba(255, 255, 255, 0.8);
+    border-radius: 5px;
+    z-index: 1;
+    display: flex;
+    flex-direction: column;
+    }
+
+    .legend-item {
+      display: flex;
+      align-items: center;
+      margin-bottom: 5px;
+      cursor: pointer;
+    }
+
+    .legend-item div {
+      align-items: relative;
+      width: 20px;
+      height: 20px;
+      margin-right: 10px;
+    }
+
+    #chartControls {
+      position: absolute;
+      top: 34px;
+      left: 20px;
+      z-index: 3;
+    }
+#plotlyContainer {
+  height: 100vh;
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  top: 2%;
+  right:100;
+  width: 100%; 
+  z-index: 3;
+}
+
+.dark-popup-content {
+  color: #232020; 
+  background-color: #171515; /* to dark gray */
+}
+
+  </style>
+</head>
+
+<body>
+  <div id="container">
+    <div id="usage-pie-chart-container" style="width: 300px; height: 300px; ">
+      <canvas id="usage-pie-chart" style="width: 100%; height: 100%;"></canvas>
+    </div>
+
+    <div id="main"></div>
+    <div id="viewDiv"></div>
+    <div id="timeSlider"></div>
+
+    <div class="legend"></div>
+    <div class="legend-building"></div>
+    <div id="spaceTimeCubeContainer">
+      <div id="plotlyContainer"></div>
+
+    </div>
+  </div>
+
+    </div>
+  </div>
+  </div>
+
+    
+  </div>
+  <div id="mainMenu">
+    <label for="measurementType">Select Measurement Type:</label>
+    <select id="measurementType">
+      <option value="temperature">Temperature °C</option>
+      <option value="humidity">Humidity %</option>
+      <option value="illuminance">Illuminance in Lux</option>
+    </select>
+
+    <label for="chartType">Select Chart Type:</label>
+    <select id="chartType">
+      <option value="line">Line Chart</option>
+      <option value="bar">Bar Chart</option>
+    </select>
+
+    <button id="loadDatastream">Load Datastream</button>
+    <button id="toggleSpaceTime">Bus Space-Time Visualization</button>
+
+    <button id="toggle3DButton">3D City Building</button>
+
+  </div>
+
+  <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
+  <script src="https://api.mapbox.com/mapbox.js/v3.3.1/mapbox.js"></script>
+  <!-- <script src="https://cdn.jsdelivr.net/npm/echarts@5.0.0/dist/echarts.min.js"></script>
+  <script src="https://cdn.jsdelivr.net/npm/echarts-gl@5.0.0/dist/echarts-gl.min.js"></script> -->
+  <script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.5.0/echarts.min.js" integrity="sha512-k37wQcV4v2h6jgYf5IUz1MoSKPpDs630XGSmCaCCOXxy2awgAWKHGZWr9nMyGgk3IOxA1NxdkN8r1JHgkUtMoQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
+  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
+  <script src="https://code.highcharts.com/highcharts.js"></script>
+
+  <script src="https://js.arcgis.com/4.28/"></script>
+<script>
+
+    const data = [
+      
+    ];
+
+    //to ensure if plotly and mapbox are loaded
+    if (window.Plotly && window.L) {
+
+    document.getElementById("loadDatastream").addEventListener("click", function () {
+      var selectedMeasurementType = document.getElementById("measurementType").value;
+      var selectedChartType = document.getElementById("chartType").value;
+
+      // Mapping from sensor location to their corresponding Datastream id
+      var datastreamIds = {
+        "Co-working": {
+          illuminance: 7,
+          temperature: 8,
+          humidity: 9
+        },
+        "Eaves": {
+          illuminance: 1,
+          temperature: 2,
+          humidity: 3
+        },
+        "Cafeteria": {
+          illuminance: 4,
+          temperature: 5,
+          humidity: 6
+        }
+      };
+
+      //adding color for each
+      var locationColors = {
+        "Co-working": 'orange',
+        "Eaves": '#229954',
+        "Cafeteria": '#355EC2'
+      };
+
+      var resultData = [];
+
+      Object.entries(datastreamIds).forEach(([location, types]) => {
+        var datastreamId = types[selectedMeasurementType];
+        var datastreamUrl = "https://ogcapi.hft-stuttgart.de/sta/udigit4icity/v1.1/Datastreams(" + datastreamId + ")/Observations?$select=result,phenomenonTime&$top=10000";
+
+        fetch(datastreamUrl)
+          .then(response => response.json())
+          .then(data => {
+            var locationData = data.value
+              .filter(item => item.result !== null && item.result >= 1)
+              .map(item => ({
+                phenomenonTime: new Date(item.phenomenonTime),
+                result: item.result
+              }));
+
+            resultData.push({
+              location: location,
+              data: locationData
+            });
+
+            if (resultData.length === Object.keys(datastreamIds).length) {
+              createChart(resultData, selectedMeasurementType, selectedChartType, locationColors);
+            }
+          })
+          .catch(error => {
+            console.error("Error loading data:", error);
+          });
+      });
+    });
+
+    function createChart(resultData, selectedMeasurementType, selectedChartType, locationColors) {
+      var chartDom = document.getElementById('main');
+      var myChart = echarts.init(chartDom);
+
+      myChart.setOption({
+        backgroundColor: 'dark-gray',
+        title: {
+          text: selectedMeasurementType.charAt(0).toUpperCase() + selectedMeasurementType.slice(1) +
+            ' Results at Different Sensor Locations',
+          left: 'center',
+          textStyle: {
+            color: 'white',
+            fontSize: 20,
+          },
+
+        },
+        tooltip: {
+          trigger: 'axis',
+          backgroundColor: 'rgba(0, 0, 0, 0.7)',
+          formatter: function (params) {
+            var timestamp = new Date(params[0].value[0]);
+            var formattedTime = timestamp.toLocaleString();
+            var tooltip = 'Timestamp: ' + formattedTime + '<br>';
+            params.forEach(function (item) {
+              tooltip += item.seriesName + ': ' + item
+                .value[1] + '<br>';
+            });
+            return tooltip;
+          },
+        },
+        grid: {
+          left: '5%',
+          right: '15%',
+          top: '10%',
+          bottom: '10%',
+
+        },
+        xAxis: {
+          name: 'Phenomenon Time',
+          type: 'time',
+          boundaryGap: false,
+          axisLabel: {
+            color: 'green',
+            fontSize: 18,
+          },
+        },
+        yAxis: {
+          name: selectedMeasurementType.charAt(0).toUpperCase() + selectedMeasurementType.slice(1),
+          axisLabel: {
+            color: 'red',
+            fontSize: 18,
+          },
+        },
+        series: resultData.map(locationData => ({
+          name: locationData.location,
+          type: selectedChartType,
+          data: locationData.data.map(item => [item.phenomenonTime, item.result]),
+          itemStyle: {
+            color: locationColors[locationData.location],
+            emphasis: {
+              color: 'white',
+              fontWeight: 'bold',
+            },
+          },
+        })),
+        legend: {
+          data: resultData.map(locationData => locationData.location),
+          right: 10,
+          bottom: 10,
+          textStyle: {
+            fontSize: 14,
+            color: 'white',
+          },
+          emphasis: {
+            textStyle: {
+              fontSize: 14,
+              color: 'black',
+              fontWeight: 'bold',
+            },
+            backgroundColor: 'white',
+          },
+        },
+        dataZoom: [
+          {
+            type: 'slider',
+            xAxisIndex: [0],
+            startValue: resultData[0].data[0].phenomenonTime,
+            endValue: resultData[0].data[resultData[0].data.length - 1].phenomenonTime,
+            zoomLock: false,
+            showDetail: false,
+            top:'92%'
+          },
+          {
+            type: 'inside',
+            xAxisIndex: [0],
+          },
+        ],
+        toolbox: {
+          feature: {
+            dataZoom: {
+              show: true,
+            },
+            dataView: {
+              show: true,
+            },
+            saveAsImage: {
+              show: true,
+            },
+          },
+        },
+      });
+
+      // adding legend items dynamically
+      var legend = document.querySelector('.legend');
+      legend.innerHTML = '';
+      Object.keys(locationColors).forEach(location => {
+        var color = locationColors[location];
+        var legendItem = createLegendItem(color, location, location);
+        legend.appendChild(legendItem);
+      });
+    }
+
+    function createLegendItem(color, label, id) {
+      const legendItem = document.createElement("div");
+      legendItem.className = "legend-item";
+      legendItem.id = id;
+      legendItem.innerHTML = `
+        <div style="background-color: ${color};"></div>
+        <span>${label}</span>
+      `;
+      return legendItem;
+    }
+
+    function createBuildingLegendItem(color, label, id) {
+   const legendItem = document.createElement("div");
+   legendItem.className = "legend-item";
+   legendItem.id = id;
+   legendItem.innerHTML = `
+      <div style="background-color: ${color};"></div>
+      <span>${label}</span>
+   `;
+   return legendItem;
+    }
+
+    // To animating space-time routes directly
+    animateSpaceTimeRoutes('https://ogcapi.hft-stuttgart.de/ogc_api_moving_features/collections/bus_1/items');
+       function animateSpaceTimeRoutes(url) {
+      fetch(url)
+        .then(response => response.json())
+        .then(data => {
+          if (!data || !data.features) {
+            console.error('Invalid data format:', data);
+            return;
+          }
+
+          const frames = data.features.map((feature, index) => {
+            const coordinates = feature.geometry.coordinates;
+            const timestamps = feature.properties.datetimes;
+
+            if (!Array.isArray(coordinates) || !Array.isArray(timestamps)) {
+              console.error('Invalid feature format:', feature);
+              return;
+            }
+
+            return {
+              data: [
+                {
+                  type: 'scattermapbox',
+                  lat: coordinates.map(coord => coord[1]),
+                  lon: coordinates.map(coord => coord[0]),
+                  mode: 'lines+markers',
+                  marker: { size: 6, color: 'black' },
+                  line: { color: 'black' },
+                  name: 'Bus route',
+                },
+                {
+                  type: 'scatter3d',
+                  x: coordinates.map(coord => coord[0]),
+                  y: coordinates.map(coord => coord[1]),
+                  z: timestamps.map((time, i) => new Date(time).toISOString()), 
+
+                  mode: 'lines+markers',
+                  line: { color: 'dark' },
+                  name: 'Bus trajectory line',
+                },
+              ],
+              name: `frame${index + 1}`,
+            };
+          });
+
+                    // to set the layout with mapbox _ access token
+          
+const layout = {
+  mapbox: {
+    style: 'light', 
+    center: { lon: frames[0].data[0].lon[0], lat: frames[0].data[0].lat[0] },
+    zoom: 10,
+    accesstoken: 'pk.eyJ1IjoicmVkaWV0OTk2MyIsImEiOiJjbHJ1cmk5aGUwaDRvMmpuYWM4Z2NqcmZuIn0.c11HYT-5ucd6g6mL03bp3Q', // Mapbox access token
+  },
+  margin: { t: 0, b: 0, l: 0, r: 0 },
+  scene: {
+    xaxis: {
+      title: 'X Axis',
+      titlefont: {
+        family: 'Arial, sans-serif',
+        size: 15, 
+        color: 'black'
+      },
+      tickfont: {
+        family: 'Arial, sans-serif',
+        size: 15,
+        color: 'black',
+        bold: true
+      }
+    },
+    yaxis: {
+      title: 'Y Axis',
+      titlefont: {
+        family: 'Arial, sans-serif',
+        size: 15, 
+        color: 'black'
+      },
+      tickfont: {
+        family: 'Arial, sans-serif',
+        size: 15,
+        color: 'black',
+        bold: true
+      }
+    },
+    zaxis: {
+      title: 'Time',
+      titlefont: {
+        family: 'Arial, sans-serif',
+        size: 16, 
+        color: 'black'
+      },
+      tickfont: {
+        family: 'Arial, sans-serif',
+        size: 15,
+        color: 'black',
+        bold: true
+      }
+    },
+    // Common font settings for both 
+    font: {
+      family: 'Arial, sans-serif',
+      size: 12,
+      color: 'black',
+      bold: true
+    }
+  }
+};
+
+          // Initialize Plotly container
+          Plotly.newPlot('plotlyContainer', frames[0].data, layout);
+          Plotly.addFrames('plotlyContainer', frames);
+        })
+        .catch(error => {
+          console.error('Error fetching data:', error);
+        });
+    }
+
+    // Function to toggle space-time visualization
+      document.getElementById("toggleSpaceTime").addEventListener("click", function () {
+        const plotlyContainer = document.getElementById("plotlyContainer");
+        plotlyContainer.style.display = plotlyContainer.style.display === "none" ? "block" : "none";
+      });
+    } else {
+      console.error("Plotly or Mapbox not loaded. Check if the libraries are loaded correctly.");
+    }
+
+function loadHistoricalRoutes() {
+  // to fetch historical data and update the scene layer
+  animateHistoricalMovingFeatures('https://ogcapi.hft-stuttgart.de/ogc_api_moving_features/collections/bus_1/items', [226, 119, 40], 'Bus', 'Bus', 'busLegend');
+}
+
+</script>
+
+  <script>
+    require([
+  "esri/Map",
+  "esri/views/SceneView",
+  "esri/layers/SceneLayer",
+  "esri/layers/FeatureLayer",
+  "esri/Graphic",
+  "esri/geometry/Polyline",
+  "esri/geometry/Point",
+  "esri/symbols/WebStyleSymbol",
+  "esri/symbols/SimpleLineSymbol",
+  "esri/layers/GraphicsLayer",
+  "esri/request",
+  "esri/renderers/UniqueValueRenderer",
+  "esri/renderers/SimpleRenderer",
+  "esri/symbols/SimpleMarkerSymbol",
+  "esri/PopupTemplate"
+], function (Map, SceneView, SceneLayer, FeatureLayer, Graphic, Polyline, Point, WebStyleSymbol, SimpleLineSymbol, GraphicsLayer, esriRequest, UniqueValueRenderer, SimpleRenderer, SimpleMarkerSymbol, PopupTemplate) {
+
+      const map = new Map({
+        basemap: "dark-gray-vector"
+      });
+
+      const view = new SceneView({
+        container: "viewDiv",
+        map: map,
+        camera: {
+          position: {
+            x: 130.5180055250,
+            y: 33.7766570370,
+            z: 25000,
+            spatialReference: {
+              wkid: 4326
+            }
+          },
+          heading: 0,
+          tilt: 0
+        },
+        environment: {
+          atmosphereEnabled: false, // clearer view
+          lighting: {
+            directShadowsEnabled: true,
+
+          }
+        }
+      });
+
+const webStyleSymbol = new WebStyleSymbol({
+  name: "Telecom",
+  styleName: "EsriIconsStyle"
+});
+
+const popupTemplate = new PopupTemplate({
+  title: "{title}", // dynamic titles
+  content: `
+    <table >
+      <tr>
+        <th>Datastream Description</th>
+        <td>{Datastream_Description}</td>
+      </tr>
+      <tr>
+        <th>Datastream ID</th>
+        <td>{Datastream_ID}</td>
+      </tr>
+      <tr>
+        <th>Date</th>
+        <td>{Date}</td>
+      </tr>
+      <tr>
+        <th>Latitude</th>
+        <td>{Latitude}</td>
+      </tr>
+      <tr>
+        <th>Longitude</th>
+        <td>{Longitude}</td>
+      </tr>
+      <tr>
+        <th>observedArea</th>
+        <td>{observedArea}</td>
+      </tr>
+      <tr>
+        <th>Result</th>
+        <td>{Result}</td>
+      </tr>
+
+    </table>
+  ` 
+});
+
+const featureLayer1 = new FeatureLayer({
+  url: "https://services.arcgis.com/1lplwYilIlo008hQ/arcgis/rest/services/Datastreams_observation_xy_splited/FeatureServer",
+  renderer: new SimpleRenderer({
+    symbol: webStyleSymbol // specified symbol
+  }),
+  popupTemplate: popupTemplate, 
+  outFields: ["*"] // …include all fields 
+});
+
+
+map.add(featureLayer1);
+
+const featureLayer2 = new FeatureLayer({
+  url: "https://services.arcgis.com/1lplwYilIlo008hQ/arcgis/rest/services/Munakata_City_Road/FeatureServer",
+  renderer: new SimpleRenderer({
+    symbol: new SimpleLineSymbol({
+      color: '#7DF9FF', 
+      width: 0.1 
+    })
+  }),
+  outFields: ["*"], 
+});
+
+map.add(featureLayer2);
+
+      // Adding hosted 3D building layer
+      const hostedLayer = new SceneLayer({
+        url: "https://tiles.arcgis.com/tiles/1lplwYilIlo008hQ/arcgis/rest/services/Munakata_City_Building_0h/SceneServer",
+        renderer: new UniqueValueRenderer({
+          field: "usage", // actual usage name
+          defaultSymbol: {
+            type: "mesh-3d",
+            symbolLayers: [
+              {
+                type: "fill",
+                material: {
+                  color: [253, 127, 111, 1] // #fd7f6fff
+                }
+              }
+            ]
+          },
+          uniqueValueInfos: [
+            {
+              value: "文教厚生施設",
+              symbol: {
+                type: "mesh-3d",
+                symbolLayers: [
+                  {
+                    type: "fill",
+                    material: {
+                      color:'#FF6384',
+                    }
+                  }
+                ]
+              }
+            },
+            {
+              value: "商業施設",
+              symbol: {
+                type: "mesh-3d",
+                symbolLayers: [
+                  {
+                    type: "fill",
+                    material: {
+                      color: "#347fb3"
+                    }
+                  }
+                ]
+              }
+            },
+            {
+              value: "共同住宅",
+              symbol: {
+                type: "mesh-3d",
+                symbolLayers: [
+                  {
+                    type: "fill",
+                    material: {
+                      color: "#FFCE56",
+                    }
+                  }
+                ]
+              }
+            },
+            {
+              value: "工場",
+              symbol: {
+                type: "mesh-3d",
+                symbolLayers: [
+                  {
+                    type: "fill",
+                    material: {
+                      color: "#4BC0C0",
+                    }
+                  }
+                ]
+              }
+            },
+            {
+              value: "Other",
+              symbol: {
+                type: "mesh-3d",
+                symbolLayers: [
+                  {
+                    type: "fill",
+                    material: {
+                      color: "#9966FF",
+                    }
+                  }
+                ]
+              }
+            },
+            {
+              value: "住宅",
+              symbol: {
+                type: "mesh-3d",
+                symbolLayers: [
+                  {
+                    type: "fill",
+                    material: {
+                      color: "#b57433",
+                    }
+                  }
+                ]
+              }
+            },
+            {
+              value: "業務施設",
+              symbol: {
+                type: "mesh-3d",
+                symbolLayers: [
+                  {
+                    type: "fill",
+                    material: {
+                      color:"#3ca33c",
+                    }
+                  }
+                ]
+              }
+            },
+            {
+              value: "農林漁業用施設",
+              symbol: {
+                type: "mesh-3d",
+                symbolLayers: [
+                  {
+                    type: "fill",
+                    material: {
+                      color: "#FF99CC",
+                    }
+                  }
+                ]
+              }
+            },
+            {
+              value:"運輸倉庫施設",
+          symbol: {
+            type: "mesh-3d",
+            symbolLayers: [
+              {
+                type: "fill",
+                material: {
+                  color: "#BDBDBD",
+                }
+              }
+            ]
+          }
+        },
+        ]
+      }),
+      elevationInfo: {
+          "mode": "on-the-ground",
+
+  "offset": 20,
+  "featureExpressionInfo": {
+    "expression": "$feature.ELEVATION_Meters"
+  },
+  "unit": "meters"
+      },
+      visible: false // 3D building initially hidden
+      });
+
+  map.add(hostedLayer);
+  
+// usage data with 'usage' and 'count' properties
+const usageData = [
+  { usage: "educational facilities", count: 100 },
+  { usage: "Commercial Facilities", count: 200 },
+];
+
+// Additional usage
+const additionalUsageData = [
+  { usage: "apartment house", count: 150 },
+  { usage: "factory", count: 75 },
+  { usage: "Other", count: 50 },
+  { usage: "Residential", count: 300 },
+  { usage: "business facility", count: 180 },
+  { usage: "Agriculture, Forestry and Fishing Facilities", count: 90 },
+  { usage: "Transportation warehouse facilities", count: 120 }
+];
+
+// Combines all usage_data
+const allUsageData = usageData.concat(additionalUsageData);
+
+// to extract labels and counts
+const labels = allUsageData.map(item => item.usage);
+const counts = allUsageData.map(item => item.count);
+
+// colors for each category
+const colors = [
+  "#FF6384", 
+  "#347fb3", 
+  "#FFCE56", 
+  "#4BC0C0", 
+  "#9966FF", 
+  "#b57433", 
+  "#3ca33c", 
+  "#FF99CC", 
+  "#BDBDBD"  
+];
+
+// Creating pie chart
+const pieChartCanvas = document.getElementById("usage-pie-chart").getContext("2d");
+const usagePieChart = new Chart(pieChartCanvas, {
+  type: "pie",
+  data: {
+    labels: labels,
+    datasets: [{
+      data: counts,
+      backgroundColor: colors
+    }]
+  },
+  options: {
+    title: {
+      display: true,
+      text: "Building Usage"
+    },
+    legend: {
+      labels: {
+        fontColor: 'white' 
+      }
+    }
+  }
+});
+
+  // To add an event listener for toggling 3D plot visibility
+  document.getElementById("toggle3DButton").addEventListener("click", function () {
+    hostedLayer.visible = !hostedLayer.visible;
+  });
+
+  const graphicsLayer = new GraphicsLayer();
+  map.add(graphicsLayer);
+
+function updatePopupContent(thingId, newData) {
+  const graphic = IoTGraphics.find(item => item.thingId === thingId);
+
+  if (graphic) {
+    // updating the popup content
+    graphic.graphic.popupTemplate.content = `New Content: ${newData}`;
+  }
+}
+
+function createSymbol(styleName) {
+    return new WebStyleSymbol({
+        name: styleName,
+        styleName: "EsriIconsStyle"
+    });
+}
+
+function createCallout(point, symbol, height, time) {
+    const iconGraphic = new Graphic({
+        geometry: point,
+        symbol: symbol,
+        attributes: {
+            time: time
+        },
+        popupTemplate: {
+            title: "Time",
+            content: "{time}"
+        }
+    });
+
+    graphicsLayer.add(iconGraphic); // adds graphic to layer
+}
+
+
+function animateMovingFeatures(url, styleName, legendLabel, id, height) {
+    esriRequest(url, { responseType: "json" })
+        .then(response => {
+            const features = response.data.features;
+            const coordinates = features.reduce((acc, curr) => acc.concat(curr.geometry.coordinates), []);
+            const datetimes = features.reduce((acc, curr) => acc.concat(curr.properties.datetimes), []);
+
+            const symbol = createSymbol(styleName); // Create symbol once
+            let currentPoint = 0;
+            let movingFeatureGraphic;
+
+            // To animate moving features
+            const animationInterval = setInterval(() => {
+                if (currentPoint < coordinates.length) {
+                    const [longitude, latitude, featureHeight] = coordinates[currentPoint];
+                    const time = new Date(datetimes[currentPoint]).toLocaleString();
+
+                    const movingFeaturePoint = new Point({
+                        x: longitude,
+                        y: latitude,
+                        z: 0,
+                        spatialReference: {
+                            wkid: 4326
+                        }
+                    });
+
+                    if (!movingFeatureGraphic) {
+                        // Create the moving feature graphic for the first time
+                        movingFeatureGraphic = new Graphic({
+                            geometry: movingFeaturePoint,
+                            symbol: symbol,
+                            attributes: {
+                                time: time
+                            },
+                            popupTemplate: {
+                                title: "Time",
+                                content: "{time}"
+                            }
+                        });
+                        graphicsLayer.add(movingFeatureGraphic);
+                    } else {
+                        // Update the position of the existing moving feature graphic
+                        movingFeatureGraphic.geometry = movingFeaturePoint;
+                        movingFeatureGraphic.attributes.time = time;
+                    }
+
+                    currentPoint++;
+                }
+            }, 1000);
+        })
+        .catch(error => {
+            console.error("Error fetching data:", error);
+        });
+}
+
+// Function to animate moving features for east and west bound trains
+function animateTrainRoutes(eastboundUrl, westboundUrl, styleName, legendLabel, id, height) {
+    Promise.all([esriRequest(eastboundUrl, { responseType: "json" }), esriRequest(westboundUrl, { responseType: "json" })])
+        .then(responses => {
+            const eastboundFeatures = responses[0].data.features;
+            const westboundFeatures = responses[1].data.features;
+
+            //Combine east and westbound features into one array
+            const allFeatures = [...eastboundFeatures, ...westboundFeatures];
+
+            const symbol = createSymbol(styleName); // Create symbol once
+            let currentFeatureIndex = 0;
+            let movingFeatureGraphic;
+
+            // animate features
+            const animationInterval = setInterval(() => {
+                if (currentFeatureIndex < allFeatures.length) {
+                    const feature = allFeatures[currentFeatureIndex];
+                    const [longitude, latitude, featureHeight] = feature.geometry.coordinates;
+                    const time = new Date(feature.properties.datetimes[0]).toLocaleString();
+
+                    const movingFeaturePoint = new Point({
+                        x: longitude,
+                        y: latitude,
+                        z: featureHeight,
+                        spatialReference: {
+                            wkid: 4326
+                        }
+                    });
+
+                    if (!movingFeatureGraphic) {
+                        // Create the moving feature graphic for the first time
+                        movingFeatureGraphic = new Graphic({
+                            geometry: movingFeaturePoint,
+                            symbol: symbol,
+                            attributes: {
+                                time: time
+                            },
+                            popupTemplate: {
+                                title: "Time",
+                                content: "{time}"
+                            }
+                        });
+                        graphicsLayer.add(movingFeatureGraphic);
+                    } else {
+                        // update the position of the existing M_feature graphic
+                        movingFeatureGraphic.geometry = movingFeaturePoint;
+                        movingFeatureGraphic.attributes.time = time;
+                    }
+
+                    currentFeatureIndex++;
+                } else {
+                    // Reset the animation when all features have been displayed
+                    currentFeatureIndex = 0;
+                }
+            }, 1000);
+        })
+        .catch(error => {
+            console.error("Error fetching data:", error);
+        });
+}
+
+animateMovingFeatures("https://ogcapi.hft-stuttgart.de/ogc_api_moving_features/collections/bus_1/items", "Bus", "Bus", "busLegend", 100);
+animateMovingFeatures("https://ogcapi.hft-stuttgart.de/ogc_api_moving_features/collections/train_EastBound_WD/items", "Train", "Eastbound Train", "trainEastLegend", 500);
+animateMovingFeatures("https://ogcapi.hft-stuttgart.de/ogc_api_moving_features/collections/train_WestBound_WD/items", "Train", "Westbound Train", "trainWestLegend", 500);
+
+    document.getElementById("toggleSpaceTime").addEventListener("click", function () {
+      const spaceTimeContainer = document.getElementById("spaceTimeCubeContainer");
+      console.log("Toggle button clicked");
+      console.log("Current display style:", spaceTimeContainer.style.display);
+      spaceTimeContainer.style.display = spaceTimeContainer.style.display === "none" ? "block" : "none";
+      console.log("New display style:", spaceTimeContainer.style.display);
+
+      // If the space-time container is set to block initialize/reload the space-time visualization
+      if (spaceTimeContainer.style.display === "block") {
+        console.log("Initializing space-time visualization...");
+        animateSpaceTimeRoutes('https://ogcapi.hft-stuttgart.de/ogc_api_moving_features/collections/bus_1/items');
+      }
+    });
+
+});
+
+  function animateSpaceTimeRoute(url, containerId, trainColor, trainName) {
+      fetch(url)
+        .then(response => response.json())
+        .then(data => {
+          if (!data || !data.features) {
+            console.error('Invalid data format:', data);
+            return;
+          }
+
+          const features = Array.isArray(data.features) ? data.features : [data.features];
+
+          const frames = features.map((feature, index) => {
+            const coordinates = feature.geometry.coordinates;
+            const timestamps = feature.properties.datetimes;
+
+            if (!Array.isArray(coordinates) || !Array.isArray(timestamps)) {
+              console.error('Invalid feature format:', feature);
+              return;
+            }
+
+            return {
+              data: [
+                {
+                  type: 'scattermapbox',
+                  lat: coordinates.map(coord => coord[1]),
+                  lon: coordinates.map(coord => coord[0]),
+                  mode: 'lines+markers',
+                  marker: { size: 20, color: trainColor },
+                  line: { color: trainColor },
+                  name: `Bus route`,
+                },
+                {
+                  type: 'scatter3d',
+                  x: coordinates.map(coord => coord[0]),
+                  y: coordinates.map(coord => coord[1]),
+                  z: timestamps.map((time, i) => new Date(time).toISOString()), // convert to ISO format
+                  mode: 'lines+markers',
+                  line: { color: trainColor },
+                  text: timestamps.map((time) => new Date(time).toLocaleTimeString()), // labels on the points
+                  name: `Bus Space-Time - ${index + 1}`,
+                },
+              ],
+              name: `Frame ${index + 1}`,
+            };
+          });
+
+          // Set the layout with mapbox style and access token
+          const layout = {
+            mapbox: {
+              style: 'light', 
+              center: { lon: features[0].geometry.coordinates[0][0], lat: features[0].geometry.coordinates[0][1] },
+              zoom: 10,
+              accesstoken: 'pk.eyJ1IjoicmVkaWV0OTk2MyIsImEiOiJjbHJ1cmk5aGUwaDRvMmpuYWM4Z2NqcmZuIn0.c11HYT-5ucd6g6mL03bp3Q', 
+            },
+            margin: { t: 0, b: 0, l: 0, r: 0 },
+
+         };
+
+          // initialize Plotly container
+          Plotly.newPlot(containerId, frames[0].data, layout);
+
+          // adding frames
+          Plotly.addFrames(containerId, frames);
+        })
+        .catch(error => {
+          console.error('Error fetching data:', error);
+        });
+    }
+
+</script>
+<script>
+const thingsLocations = [    { thingId: 1, locationURL: "https://ogcapi.hft-stuttgart.de/sta/udigit4icity/v1.1/Things(1)/Locations", datastreamsURL: "https://ogcapi.hft-stuttgart.de/sta/udigit4icity/v1.1/Things(1)/Datastreams" },    { thingId: 2, locationURL: "https://ogcapi.hft-stuttgart.de/sta/udigit4icity/v1.1/Things(2)/Locations", datastreamsURL: "https://ogcapi.hft-stuttgart.de/sta/udigit4icity/v1.1/Things(2)/Datastreams" },    { thingId: 3, locationURL: "https://ogcapi.hft-stuttgart.de/sta/udigit4icity/v1.1/Things(3)/Locations", datastreamsURL: "https://ogcapi.hft-stuttgart.de/sta/udigit4icity/v1.1/Things(3)/Datastreams" },    { thingId: 4, locationURL: "https://ogcapi.hft-stuttgart.de/sta/udigit4icity/v1.1/Things(4)/Locations", datastreamsURL: "https://ogcapi.hft-stuttgart.de/sta/udigit4icity/v1.1/Things(4)/Datastreams" },    { thingId: 5, locationURL: "https://ogcapi.hft-stuttgart.de/sta/udigit4icity/v1.1/Things(5)/Locations", datastreamsURL      : "https://ogcapi.hft-stuttgart.de/sta/udigit4icity/v1.1/Things(5)/Datastreams" },  ];
+</script>
+</body>
+