Merge branch 'main' of https://gitlab.fdmci.hva.nl/propedeuse-hbo-ict/onderwijs/2023-2024/out-a-se-ti/blok-3/qaajeeqiinii59
This commit is contained in:
@@ -49,9 +49,9 @@ def loginDB():
|
||||
)
|
||||
return mydb
|
||||
|
||||
def getData(node, dataType, MAC, dateStart, dateEnd):
|
||||
def getData(node, dataTypes, MAC, dateStart, dateEnd):
|
||||
mydb = loginDB()
|
||||
query = get_query(node, dataType, MAC, False, False, dateStart, dateEnd)
|
||||
query = get_query(node, dataTypes, MAC, False, False, dateStart, dateEnd)
|
||||
cursor = mydb.cursor(dictionary=True) # Enable dictionary output
|
||||
cursor.execute(query)
|
||||
result = cursor.fetchall() # Fetch the results
|
||||
@@ -62,7 +62,7 @@ def getData(node, dataType, MAC, dateStart, dateEnd):
|
||||
|
||||
def getNodeInfo(macAdress):
|
||||
mydb = loginDB()
|
||||
query = get_query(False, False, macAdress, False, False)
|
||||
query = get_query(False, False, macAdress, False, False, False, False)
|
||||
cursor = mydb.cursor(dictionary=True) # Enable dictionary output
|
||||
cursor.execute(query)
|
||||
result = cursor.fetchall() # Fetch the results
|
||||
|
@@ -1,5 +1,9 @@
|
||||
def get_query(node, dataType, MAC, questionID, replies, dateStart, dateEnd):
|
||||
if dateStart and dateEnd and node:
|
||||
if dateStart and dateEnd and node and dataType:
|
||||
query = f'''SELECT *
|
||||
FROM Measurement
|
||||
WHERE TimeStamp BETWEEN '{dateStart}' AND '{dateEnd}' AND NodeID = {node} AND Type IN ('{dataType}');'''
|
||||
elif dateStart and dateEnd and node:
|
||||
query = f'''SELECT *
|
||||
FROM Measurement
|
||||
WHERE TimeStamp BETWEEN '{dateStart}' AND '{dateEnd}' AND NodeID = {node};'''
|
||||
@@ -21,10 +25,7 @@ def get_query(node, dataType, MAC, questionID, replies, dateStart, dateEnd):
|
||||
query = f"SELECT * FROM Question"
|
||||
elif replies:
|
||||
query = f"SELECT * FROM Reply"
|
||||
elif dateStart and dateEnd and node:
|
||||
query = f'''SELECT *
|
||||
FROM Measurement
|
||||
WHERE TimeStamp BETWEEN '{dateStart}' AND '{dateEnd}';'''
|
||||
|
||||
else:
|
||||
query = "SELECT * FROM `Measurement`"
|
||||
return query
|
||||
|
@@ -42,8 +42,7 @@ class Graph {
|
||||
}
|
||||
|
||||
updateData(type, value, timestamp) {
|
||||
this.timeArray.push(timestamp);
|
||||
|
||||
// this.timeArray.push(timestamp);
|
||||
switch (type) {
|
||||
case "Temp":
|
||||
this.tempArray.push(value);
|
||||
@@ -67,7 +66,7 @@ class Graph {
|
||||
x: [this.timeArray],
|
||||
y: [this.tempArray, this.humiArray, this.eco2Array, this.tvocArray],
|
||||
};
|
||||
|
||||
console.log(update);
|
||||
Plotly.update(this.id, update);
|
||||
}
|
||||
}
|
||||
@@ -140,10 +139,19 @@ class DataProcessor {
|
||||
}
|
||||
|
||||
updateGraph() {
|
||||
this.graph.timeArray = [];
|
||||
this.graph.tempArray = [];
|
||||
this.graph.humiArray = [];
|
||||
this.graph.eco2Array = [];
|
||||
this.graph.tvocArray = [];
|
||||
|
||||
for (let i = 0; i < this.data.length; i++) {
|
||||
if (i % 4 == 0){
|
||||
this.graph.timeArray.push(this.data[i].TimeStamp);
|
||||
}
|
||||
this.graph.updateData(this.data[i].Type, this.data[i].Value, this.data[i].TimeStamp);
|
||||
console.log(this.data[i].Type, this.data[i].Value, this.data[i].TimeStamp);
|
||||
this.graph.updateGraph();
|
||||
}
|
||||
}
|
||||
this.graph.updateGraph();
|
||||
}
|
||||
}
|
||||
|
@@ -24,10 +24,10 @@ container.setAttribute("class", "container");
|
||||
const dataTypesContainer = document.createElement("div");
|
||||
dataTypesContainer.setAttribute("class", "data-types");
|
||||
|
||||
const temperatureCheckbox = createCheckBox("temperature", "Temperature");
|
||||
const humidityCheckbox = createCheckBox("humidity", "Humidity");
|
||||
const eco2Checkbox = createCheckBox("eco2", "eCO2");
|
||||
const tvocCheckbox = createCheckBox("tvoc", "TVOC");
|
||||
const temperatureCheckbox = createCheckBox("Temp", "Temperature");
|
||||
const humidityCheckbox = createCheckBox("Humi", "Humidity");
|
||||
const eco2Checkbox = createCheckBox("eCO2", "eCO2");
|
||||
const tvocCheckbox = createCheckBox("TVOC", "TVOC");
|
||||
|
||||
dataTypesContainer.appendChild(temperatureCheckbox.checkbox);
|
||||
dataTypesContainer.appendChild(temperatureCheckbox.checkboxLabel);
|
||||
@@ -55,24 +55,30 @@ filterButton.addEventListener("click", () => {
|
||||
temperatureCheckbox,
|
||||
humidityCheckbox,
|
||||
eco2Checkbox,
|
||||
tvocCheckbox,
|
||||
tvocCheckbox
|
||||
];
|
||||
|
||||
checkboxes.forEach((checkbox) => {
|
||||
if (checkbox.checkbox.checked) {
|
||||
selectedFields.push(checkbox.checkbox.id);
|
||||
selectedFields.push(String(checkbox.checkbox.id));
|
||||
}
|
||||
});
|
||||
|
||||
let selectedFieldsString = selectedFields.map(String);
|
||||
|
||||
let formattedString = '(' + selectedFieldsString.map(item => `'${item}'`).join(', ') + ')';
|
||||
|
||||
const filteredData = [
|
||||
startDate,
|
||||
endDate,
|
||||
selectedNodes,
|
||||
selectedFields
|
||||
formattedString
|
||||
];
|
||||
|
||||
console.log(filteredData);
|
||||
console.log(startDate, endDate, selectedNodes);
|
||||
|
||||
generateLink(startDate, endDate, selectedNodes);
|
||||
generateLink(startDate, endDate, selectedNodes, formattedString);
|
||||
fetchData();
|
||||
});
|
||||
|
||||
@@ -98,7 +104,7 @@ nodeFilter.setAttribute("class", "node-filter");
|
||||
|
||||
const nodeInput = document.createElement("input");
|
||||
nodeInput.setAttribute("type", "text");
|
||||
nodeInput.setAttribute("placeholder", "Enter node (A, B, etc.)");
|
||||
nodeInput.setAttribute("placeholder", "Enter Node Name (* for all)");
|
||||
nodeInput.setAttribute("id", "node-input");
|
||||
nodeInput.setAttribute("class", "input-field");
|
||||
|
||||
@@ -110,12 +116,12 @@ container.appendChild(filterButton);
|
||||
document.body.appendChild(container);
|
||||
|
||||
// Function to get the link for the get request
|
||||
function generateLink(dateStart, dateEnd, node) {
|
||||
function generateLink(dateStart, dateEnd, node, dataTypes) {
|
||||
const baseUrl = 'http://145.92.8.114/getMeasurements';
|
||||
const formattedDateStart = new Date(dateStart).toISOString().replace('T', '%20');
|
||||
const formattedDateEnd = new Date(dateEnd).toISOString().replace('T', '%20');
|
||||
|
||||
link = `${baseUrl}?dateStart=${formattedDateStart}&dateEnd=${formattedDateEnd}&node=${node}`;
|
||||
link = `${baseUrl}?dateStart=${formattedDateStart}&dateEnd=${formattedDateEnd}&node=${node}&dataType=${dataTypes}`;
|
||||
|
||||
console.log(link);
|
||||
}
|
||||
|
27
web/newWebsite/questions-chart-class.js
Normal file
27
web/newWebsite/questions-chart-class.js
Normal file
@@ -0,0 +1,27 @@
|
||||
class ChartConfigClass{
|
||||
constructor(data, text){
|
||||
this.data = data
|
||||
this.text = text
|
||||
}
|
||||
|
||||
get chartConfig() {
|
||||
return{
|
||||
type: 'pie',
|
||||
data: this.data,
|
||||
options: {
|
||||
responsive: true,
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: this.text
|
||||
},
|
||||
animation: {
|
||||
animateScale: true,
|
||||
animateRotate: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -30,24 +30,30 @@
|
||||
|
||||
<body>
|
||||
<div class="chart-container">
|
||||
<div class="chart">
|
||||
<h2>Question 1: How clean are the toilets?</h2>
|
||||
<canvas id="chart1"></canvas>
|
||||
|
||||
</div>
|
||||
<div class="chart">
|
||||
<h2>Question 2: How clean is the study area?</h2>
|
||||
<canvas id="chart2"></canvas>
|
||||
|
||||
</div>
|
||||
<div class="chart">
|
||||
<h2>Question 3: What do you think of the temperature in the study area?</h2>
|
||||
<canvas id="chart3"></canvas>
|
||||
|
||||
</div>
|
||||
<div class="chart">
|
||||
<h2>Question 4: How crowded would you say the study area is?</h2>
|
||||
<canvas id="chart4"></canvas>
|
||||
|
||||
</div>
|
||||
<div class="chart">
|
||||
<h2>Question 5: Is there enough help available on the 5th floor?</h2>
|
||||
<canvas id="chart5"></canvas>
|
||||
|
||||
</div>
|
||||
<!-- Add more questions and canvas elements as needed -->
|
||||
</div>
|
||||
<script src="questions-main-class.js"></script>
|
||||
<script src="questions-chart-class.js"></script>
|
||||
<script src="questions-creation-class.js"></script>
|
||||
<script src="questions-main.js"></script>
|
||||
</body>
|
||||
</html>
|
@@ -1,3 +1,4 @@
|
||||
//For now create dummy data to show on the website.
|
||||
let dummydata1 = [40, 30, 20];
|
||||
let questionOptionsDummy1 = ['disgusting','clean', 'fine'];
|
||||
|
||||
@@ -13,119 +14,41 @@ let questionOptionsDummy4 = ['really crowded','not at all', 'its fine', ];
|
||||
let dummydata5 = [30, 20, 20];
|
||||
let questionOptionsDummy5 = ['no','yes', 'decently'];
|
||||
|
||||
const question1Data = new QuestionCreationClass(dummydata1,questionOptionsDummy1)
|
||||
const question2Data = new QuestionCreationClass(dummydata2,questionOptionsDummy2)
|
||||
const question3Data = new QuestionCreationClass(dummydata3, questionOptionsDummy3);
|
||||
const question4Data = new QuestionCreationClass(dummydata4, questionOptionsDummy4);
|
||||
const question5Data = new QuestionCreationClass(dummydata5, questionOptionsDummy5);
|
||||
//make arrays to store data.
|
||||
let chartConfigArray = [];
|
||||
let textArray = [];
|
||||
|
||||
const chartConfig1 = {
|
||||
type: 'pie',
|
||||
data: question1Data.questionData,
|
||||
options: {
|
||||
responsive: true,
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Question 1 Responses'
|
||||
},
|
||||
animation: {
|
||||
animateScale: true,
|
||||
animateRotate: true
|
||||
}
|
||||
}
|
||||
};
|
||||
let questionArray = [];
|
||||
let questionOptionsDummy = [];
|
||||
let dummydata = [];
|
||||
|
||||
const chartConfig2 = {
|
||||
type: 'pie',
|
||||
data: question2Data.questionData,
|
||||
options: {
|
||||
responsive: true,
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Question 2 Responses'
|
||||
},
|
||||
animation: {
|
||||
animateScale: true,
|
||||
animateRotate: true
|
||||
}
|
||||
}
|
||||
};
|
||||
//Go along the array's to fetch data, and push this in a class.
|
||||
for (let i = 0; i < 5; i++) {
|
||||
dummydata.push(dummydata1, dummydata2, dummydata3, dummydata4, dummydata5);
|
||||
questionOptionsDummy.push(questionOptionsDummy1, questionOptionsDummy2, questionOptionsDummy3, questionOptionsDummy4, questionOptionsDummy5);
|
||||
|
||||
const chartConfig3 = {
|
||||
type: 'pie',
|
||||
data: question3Data.questionData,
|
||||
options: {
|
||||
responsive: true,
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Question 3 Responses'
|
||||
},
|
||||
animation: {
|
||||
animateScale: true,
|
||||
animateRotate: true
|
||||
}
|
||||
}
|
||||
};
|
||||
questionArray.push(new QuestionCreationClass(dummydata[i], questionOptionsDummy[i]));
|
||||
}
|
||||
|
||||
const chartConfig4 = {
|
||||
type: 'pie',
|
||||
data: question4Data.questionData,
|
||||
options: {
|
||||
responsive: true,
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Question 4 Responses'
|
||||
},
|
||||
animation: {
|
||||
animateScale: true,
|
||||
animateRotate: true
|
||||
}
|
||||
}
|
||||
};
|
||||
//Go allong another array to also give the class that creates the charts the data collected by the previous array.
|
||||
for (let i = 0; i < 5; i++){
|
||||
textArray.push('Question 1 Responses', 'Question 2 Responses', 'Question 3 Responses', 'Question 4 Responses', 'Question 5 Responses');
|
||||
|
||||
const chartConfig5 = {
|
||||
type: 'pie',
|
||||
data: question5Data.questionData,
|
||||
options: {
|
||||
responsive: true,
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Question 5 Responses'
|
||||
},
|
||||
animation: {
|
||||
animateScale: true,
|
||||
animateRotate: true
|
||||
}
|
||||
}
|
||||
};
|
||||
chartConfigArray.push(new ChartConfigClass(questionArray[i].questionData, textArray[i]));
|
||||
}
|
||||
|
||||
// Create the charts
|
||||
const ctx1 = document.getElementById('chart1').getContext('2d');
|
||||
const myChart1 = new Chart(ctx1, chartConfig1);
|
||||
const myChart1 = new Chart(ctx1, chartConfigArray[0].chartConfig);
|
||||
|
||||
const ctx2 = document.getElementById('chart2').getContext('2d');
|
||||
const myChart2 = new Chart(ctx2, chartConfig2);
|
||||
const myChart2 = new Chart(ctx2, chartConfigArray[1].chartConfig);
|
||||
|
||||
const ctx3 = document.getElementById('chart3').getContext('2d');
|
||||
const myChart3 = new Chart(ctx3, chartConfig3);
|
||||
const myChart3 = new Chart(ctx3, chartConfigArray[2].chartConfig);
|
||||
|
||||
const ctx4 = document.getElementById('chart4').getContext('2d');
|
||||
const myChart4 = new Chart(ctx4, chartConfig4);
|
||||
const myChart4 = new Chart(ctx4, chartConfigArray[3].chartConfig);
|
||||
|
||||
const ctx5 = document.getElementById('chart5').getContext('2d');
|
||||
const myChart5 = new Chart(ctx5, chartConfig5);
|
||||
const myChart5 = new Chart(ctx5, chartConfigArray[4].chartConfig);
|
||||
|
@@ -50,7 +50,7 @@ body {
|
||||
border-radius: 10px;
|
||||
margin: 20px;
|
||||
padding: 20px;
|
||||
width: 100%;
|
||||
width: 90;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@@ -98,8 +98,7 @@ body {
|
||||
}
|
||||
|
||||
.filter-button {
|
||||
flex: 1;
|
||||
width: 20%;
|
||||
width: 10%;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
padding: 10px;
|
||||
@@ -108,4 +107,10 @@ body {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.js-plotly-plot {
|
||||
align-self: center;
|
||||
width: 95%;
|
||||
height: 100%;
|
||||
margin: 10px;
|
||||
}
|
||||
/* Additional styling as needed */
|
||||
|
@@ -4,6 +4,7 @@
|
||||
}
|
||||
|
||||
body {
|
||||
flex-direction: row;
|
||||
padding-top: 5vw;
|
||||
display: flex;
|
||||
background-color: #dbd7d7;
|
||||
@@ -42,16 +43,27 @@
|
||||
}
|
||||
|
||||
#data-container {
|
||||
width: 80%;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: #f5f5f5;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
width: 80%;
|
||||
margin: 20px auto;
|
||||
justify-content: center;
|
||||
align-self: start;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.chart {
|
||||
width: 30%;
|
||||
margin: 20px;
|
||||
padding: 20px;
|
||||
background-color: #dbd7d7;
|
||||
border: 3px solid #000;
|
||||
border-radius: 30px;
|
||||
}
|
||||
canvas {
|
||||
margin-bottom: 20px;
|
||||
|
@@ -0,0 +1,202 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
font-family: "Roboto", sans-serif;
|
||||
|
||||
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 0;
|
||||
margin-top: 8vh;
|
||||
background-color: #f0f0f0;
|
||||
flex-direction: column;
|
||||
background-color: #afafaf;
|
||||
align-items: center;
|
||||
|
||||
}
|
||||
|
||||
.gaugeGroup {
|
||||
width: 98vw;
|
||||
height: auto;
|
||||
display: flex;
|
||||
flex-direction: column; /* Keep as column */
|
||||
justify-content: flex-start;
|
||||
background-color: #333;
|
||||
color: #fff;
|
||||
padding: 10px;
|
||||
border-radius: 50px;
|
||||
border: 2px solid #333;
|
||||
clear: both;
|
||||
margin-bottom: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.groupTitle {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.Node {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.Sensorvalues {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
flex-wrap: wrap;
|
||||
width: 15%;
|
||||
height: 110%;
|
||||
background-color: #ddd;
|
||||
color: #333;
|
||||
padding: 10px;
|
||||
margin: 10px;
|
||||
border-radius: 10px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
padding-top: 3vh; /* Increase bottom padding */
|
||||
|
||||
}
|
||||
|
||||
.gaugeContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 80%; /* Increase the height from 70% to 80% */
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
height: 5vh;
|
||||
margin-bottom: 1vh;
|
||||
|
||||
}
|
||||
|
||||
.gaugeImage {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-height: 120%;
|
||||
object-fit: contain;
|
||||
position: absolute; /* Make the image position absolute */
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1; /* Make the image display below the needle */
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.gaugeValue, .gaugeText {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 24px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.gaugeText {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 1.4vw;
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
top: -1.4vw; /* Adjust this value to move the text further down */
|
||||
|
||||
}
|
||||
|
||||
.arrowimg {
|
||||
width: 3vh;
|
||||
height: auto;
|
||||
max-height: 100%;
|
||||
object-fit: contain;
|
||||
position: absolute;
|
||||
top: 0.5vw;
|
||||
right: 1.2vw;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.valueContainer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#valueText {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.needle {
|
||||
position: absolute;
|
||||
bottom: -10%; /* Lower the needle to the bottom */
|
||||
left: 50%;
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
background-color: black;
|
||||
transform-origin: bottom;
|
||||
z-index: 3; /* Make the needle display above the image */
|
||||
transition: transform 0.1s ease-out;
|
||||
|
||||
}
|
||||
|
||||
.contentContainer {
|
||||
display: flex;
|
||||
flex-direction: row; /* Layout children side by side */
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
background-color: #333;
|
||||
height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 20px;
|
||||
position: fixed; /* Fix the navbar at the top of the page */
|
||||
top: 0; /* Position it at the very top */
|
||||
width: 100%; /* Make it span the full width of the page */
|
||||
z-index: 1000; /* Make sure it's above all other elements */
|
||||
}
|
||||
|
||||
.navbar-nav {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center; /* Center the links horizontally */
|
||||
height: 100%;
|
||||
width: 100%; /* Make it span the full width of the navbar */
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.plotly-container {
|
||||
width: 100%;
|
||||
float: bottom;
|
||||
padding: 1vw;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.js-plotly-plot {
|
||||
width: 90%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
|
||||
}
|
Reference in New Issue
Block a user