From 31e56dbb09a0bea4923be14eea90d73d01e5f3fa Mon Sep 17 00:00:00 2001 From: Jaber Askari <m2947@student.jamk.fi> Date: Thu, 18 Jun 2020 14:12:15 +0300 Subject: [PATCH] LAM point information and filtering --- .../backend/routes/api/vehicles/vehicle.js | 1 - .../frontend/traffic/public/index.html | 2 +- .../frontend/traffic/src/App.css | 112 ++-- .../frontend/traffic/src/App.js | 7 +- .../traffic/src/components/LAMpoints.js | 398 ++++++++++++ .../src/components/MultipleDayGraph.js | 0 .../traffic/src/components/OneDayGraph.js | 598 ++++++++++++++++++ .../traffic/src/components/OneDayGraph_v2.js | 509 +++++++++++++++ .../traffic/src/components/TestRequest.js | 37 +- .../python/cars/lamData.py | 43 +- 10 files changed, 1640 insertions(+), 67 deletions(-) create mode 100644 Tavara- raskaan liikenne/frontend/traffic/src/components/LAMpoints.js create mode 100644 Tavara- raskaan liikenne/frontend/traffic/src/components/MultipleDayGraph.js create mode 100644 Tavara- raskaan liikenne/frontend/traffic/src/components/OneDayGraph.js create mode 100644 Tavara- raskaan liikenne/frontend/traffic/src/components/OneDayGraph_v2.js diff --git a/Tavara- raskaan liikenne/backend/routes/api/vehicles/vehicle.js b/Tavara- raskaan liikenne/backend/routes/api/vehicles/vehicle.js index e5df090..bbae438 100644 --- a/Tavara- raskaan liikenne/backend/routes/api/vehicles/vehicle.js +++ b/Tavara- raskaan liikenne/backend/routes/api/vehicles/vehicle.js @@ -47,7 +47,6 @@ router.get('/',function (req, res) { //res.send(uint8arrayToString(data)); res.write(data,()=>{ - let finnis = res.writableFinished console.log("is finished: " ,finnis) }) diff --git a/Tavara- raskaan liikenne/frontend/traffic/public/index.html b/Tavara- raskaan liikenne/frontend/traffic/public/index.html index 7dece52..56a1c07 100644 --- a/Tavara- raskaan liikenne/frontend/traffic/public/index.html +++ b/Tavara- raskaan liikenne/frontend/traffic/public/index.html @@ -28,7 +28,7 @@ --> <title>React App</title> </head> - <body> + <body style="background-color: rgb(236, 236, 236);"> <noscript>You need to enable JavaScript to run this app.</noscript> <div id="root"></div> <!-- diff --git a/Tavara- raskaan liikenne/frontend/traffic/src/App.css b/Tavara- raskaan liikenne/frontend/traffic/src/App.css index d38a356..be36c05 100644 --- a/Tavara- raskaan liikenne/frontend/traffic/src/App.css +++ b/Tavara- raskaan liikenne/frontend/traffic/src/App.css @@ -1,59 +1,97 @@ -.Cars_graph{ - max-width: 443px; - margin: 30px; +.oneDayGraphComponent{ + display: flex; + + + } + .grid-container { + display: grid; - grid-template-columns: 1.3fr 1.3fr; - grid-template-rows: 0.2fr 1.4fr 1.4fr; - gap: 1px 1px; - grid-template-areas: ". ." ". ." ". ."; + grid-template-columns: 30% 600px ; + grid-auto-rows: 100px; + + column-gap: 5px; + row-gap: 5px; + padding: 50px; + justify-content: center; + margin: auto; + + } +.grid-item-heading { + + grid-column-start: 1; + grid-column-end: 3; + + + padding: 0.7em; + background-color: rgb(255, 255, 255); + border-radius: 10px; + text-align: left; + font-size: 2em; + font-weight: bold; + color: rgb(0, 108, 196) ; +} +.grid-item-form { + grid-column-start: 1; + grid-row-start: 2; + grid-row-end: 10; + + padding: 1.5em; + background-color: rgb(255, 255, 255); + border-radius: 10px; + text-align: left; + font-size: 1.3em; + color: rgba(15, 48, 75, 0.685) ; + +} +.grid-item-graph1 { + grid-column-start: 2; + grid-column-end: 3; + grid-row-start: 2; + grid-row-end: 6; + + display: flex; + background-color: rgb(255, 255, 255); + border-radius: 10px; + text-align: center; + align-content: center; + font-size: 1em; + color: rgba(15, 48, 75, 0.685) ; +} +.grid-item-graph2 { + grid-column-start: 2; + grid-column-end: 3; + grid-row-start: 6; + grid-row-end: 10; + display: flex; + background-color: rgb(255, 255, 255); + border-radius: 10px; + text-align: left; + font-size: 1em; + color: rgba(15, 48, 75, 0.685) ; +} +.grid-item-graph-child{ + margin: auto; +} .App { text-align: center; -} + background-color: rgb(236, 236, 236); -.App-logo { - height: 40vmin; - pointer-events: none; + } -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } -} -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} -.App-link { - color: #61dafb; -} -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/Tavara- raskaan liikenne/frontend/traffic/src/App.js b/Tavara- raskaan liikenne/frontend/traffic/src/App.js index 3a6d314..532253b 100644 --- a/Tavara- raskaan liikenne/frontend/traffic/src/App.js +++ b/Tavara- raskaan liikenne/frontend/traffic/src/App.js @@ -2,15 +2,18 @@ import React from 'react'; import Linechart from './components/Linechart'; import CarsGraph from './components/CarsGraph'; import TestRequest from './components/TestRequest'; +import OneDayGraph from './components/OneDayGraph'; +import LAMpoints from './components/LAMpoints' import './App.css'; import 'bootstrap/dist/css/bootstrap.min.css'; -//<Linechart /> <CarsGraph /> +//<Linechart /> <CarsGraph /> <TestRequest /> <LAMpoints /> function App() { return ( <div className="App"> + <OneDayGraph /> + - <TestRequest /> </div> ); } diff --git a/Tavara- raskaan liikenne/frontend/traffic/src/components/LAMpoints.js b/Tavara- raskaan liikenne/frontend/traffic/src/components/LAMpoints.js new file mode 100644 index 0000000..8fb3f6b --- /dev/null +++ b/Tavara- raskaan liikenne/frontend/traffic/src/components/LAMpoints.js @@ -0,0 +1,398 @@ +import React, { Component } from 'react' +import axios from "axios"; +import Form from "react-bootstrap/Form"; + + +const lamPointList=[] +var pointsData=[]; + +export class LAMpoints extends Component { + + constructor(props) { + super(props); + this.state = { + + ID:[], + address :[], + + years:[], + months:[], + days:[], + info:{}, + selectedYear: 0, + selectedMonth: 0, + selectedDay:0 + + + }; + } + + componentDidMount(){ + const url = "https://tie.digitraffic.fi/api/v3/metadata/tms-stations"; + axios.get(url) + .then(res =>{ + let status = res.status; + console.log({status}); + + if(res.status===200){ + + const features = res.data.features; + const LamPointsTotalNumber = features.length; + console.log(LamPointsTotalNumber); + + features.forEach(element => { + let lamPoint={ + id : element.id, + name : element.properties.name, + status :element.properties.collectionStatus, + coordinatesETRS89 :element.properties.coordinatesETRS89, + address :element.properties.names, + municipality :element.properties.municipality +' '+element.properties.municipalityCode, + province : element.properties.province, + provinceCode : element.properties.provinceCode, + direction1 : element.properties.direction1Municipality, + direction2 : element.properties.direction2Municipality, + startTime : element.properties.startTime, + }; + lamPointList.push(lamPoint); + + + }); + console.log(lamPointList) + + }else{ + + } + + }).catch(err => { + console.log(err); + }) + + + } + + areaIDHandler=(e)=>{ + pointsData=[]; + let address=[]; + let ID=[]; + let areaID = parseInt(e.target.value); + console.log(areaID); + + lamPointList.forEach(element => { + + let provinceCode = parseInt(element.provinceCode); + + if(provinceCode ===areaID){ + pointsData.push(element); + address.push(element.address.en); + ID.push(element.id); + } + + }); + + this.setState({address,ID,years:[],months:[],days:[]},()=>{ + console.log(); + + }) + + } + + lamIDHandler=(e)=>{ + let pointID =parseInt(e.target.value); + console.log({pointID}); + + let info = {}; + //getting the selected lam point information + pointsData.forEach(element => { + if(element.id===pointID){ + info = element; + } + }); + this.setState({info}); + //getting the time lam point start working + let startTime = info.startTime; + let startYear =parseInt((startTime.split('-'))[0]); + + //todays date and year + let now = Date().toString(); + let thisYear = parseInt((now.split(' '))[3]) + + let yearsActive=[] + for(let x=thisYear;x>=startYear;x--){ + yearsActive.push(x); + } + this.setState({info, years : yearsActive,months:[],days:[]},()=>{ + //console.log(this.state) + }); + + this.props.info(info); + } + + yearHandler=(e)=>{ + const monthList=['January','February','March','April','May', 'June','July', + 'August', 'September','October','November','December']; + var selectedYear = parseInt(e.target.value); + //getting the month and year that the selected lam point start working + let startTime = this.state.info.startTime; + let startMonth =parseInt((startTime.split('-'))[1]); + let startYear =parseInt((startTime.split('-'))[0]); + + //todays date and year + let now = Date().toString(); + let n = new Date(now); + let thisMonth = n.getMonth()//(now.split(' '))[1]; + let thisYear = parseInt((now.split(' '))[3]); + //console.log(startMonth,thisMonth,thisYear,typeof(thisYear)) + + //setting the right options for month select based on selected year + let months=[]; + if(selectedYear===startYear){ + + if(startYear===thisYear){ + for(let x=startMonth-1; x<=thisMonth;x++){ + months.push(monthList[x]) + } + }else{ + for(let x=startMonth-1; x<12;x++){ + months.push(monthList[x]) + } + } + + } + else if(selectedYear===thisYear){ + + if(thisYear!==startYear){ + for(let x=0; x<=thisMonth;x++){ + months.push(monthList[x]) + } + }else{ + for(let x=startMonth-1; x<=thisMonth;x++){ + months.push(monthList[x]) + } + } + for(let x=startMonth-1; x<thisMonth;x++){ + months.push(monthList[x]) + } + } + else{ + months=monthList;; + } + this.setState({months, selectedYear,days:[]}); + //console.log(months) + this.props.selectedYear(selectedYear); + + } + + monthHandler=(e)=>{ + var selectedMonth = e.target.value; + var daysOfMonths = [31,28,31,30,31,30,31,31,30,31,30]; + var nameOfMonths = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; + + //getting the month and day that the selected lam point start working + let startTime = this.state.info.startTime; + let startMonth =parseInt((startTime.split('-'))[1]); + let startDay =parseInt((startTime.split('-'))[2])+1; + let startYear =parseInt((startTime.split('-'))[0]); + + //todays date and year + let now = Date().toString(); + let n = new Date(now); + let thisMonth = n.getMonth()//(now.split(' '))[1]; + let thisDay = n.getDate()//(now.split(' '))[1]; + let thisYear = parseInt((now.split(' '))[3]); + //console.log(startMonth,thisMonth,thisDay,typeof(thisYear)) + + //check for leap year + var leap = this.leapyear(this.state.selectedYear); + if(leap) daysOfMonths[1]=29; + + + //getting how many number of day the selected month has + let temp=0; + let indexOfMonth; + nameOfMonths.map((v,i)=>{ + if(selectedMonth===v) { + temp = daysOfMonths[i]; + indexOfMonth =i; + } + }) + + var days =[] + if(this.state.selectedYear===startYear && indexOfMonth===startMonth-1){ + if(startYear===thisYear && indexOfMonth ===thisMonth){ + for(let x = startDay; x<=thisDay-2;x++){ + days.push(x); + } + } + else { + for(let x = startDay; x<=temp;x++){ + days.push(x); + } + } + + }else if(this.state.selectedYear===thisYear && indexOfMonth===thisMonth){ + for(let x = 1; x<=thisDay-2;x++){ + days.push(x); + } + } + else { + for(let x = 1; x<=temp;x++){ + days.push(x); + } + } + + this.setState({days, selectedMonth}) + //console.log(temp) + this.props.selectedMonth(selectedMonth); + + + + + } + dayHandler=(e)=>{ + var selectedDay = e.target.value; + this.setState({selectedDay},()=>{ + //console.log(this.state); + this.props.stateObject(this.state) + }); + this.props.selectedDay(selectedDay); + + + } + + leapyear=(year)=> { + return year % 100 === 0 ? year % 400 === 0 : year % 4 === 0; + } + + + render() { + var ids = this.state.ID; + var address = this.state.address; + return ( + <div> + <Form> + <Form.Label + className="my-1 mr-2" + htmlFor="inlineFormCustomSelectPref" + > + Choose an Area + </Form.Label> + <Form.Control + as="select" + className="my-1 mr-sm-2" + id="areaID" + custom + onChange={this.areaIDHandler} + > + <option value="">Choose...</option> + <option value="01">Uusimaa, Häme</option> + <option value="02">Varsinais-Suomi, Satakunta</option> + <option value="03">Kaakkois-Suomi</option> + <option value="04">Pirkanmaa</option> + <option value="08"> + Pohjois-Savo, Etelä-Savo, Pohjois-Karjala) + </option> + <option value="09">Keski-Suomi</option> + <option value="10">Etelä-Pohjanmaa, Pohjanmaa</option> + <option value="12">Pohjois-Pohjanmaa, Kainuu</option> + <option value="14">Lappi</option> + </Form.Control> + + <Form.Label + className="my-1 mr-2" + htmlFor="inlineFormCustomSelectPref" + > + LAM point ID + </Form.Label> + + <Form.Control + as="select" + className="my-1 mr-sm-2" + id="lamID" + custom + onChange={this.lamIDHandler} + > + <option value="">Choose...</option> + { + React.Children.map(address, (v,i)=> + <option value={ids[i]}>{v}</option> + ) + } + </Form.Control> + + + <Form.Label + className="my-1 mr-2" + htmlFor="inlineFormCustomSelectPref" + > + Year + </Form.Label> + <Form.Control + as="select" + className="my-1 mr-sm-2" + id="year" + custom + onChange={this.yearHandler} + > + <option value="0">Choose...</option> + { + React.Children.map(this.state.years, year=> + <option value={year}>{year}</option> + ) + } + </Form.Control> + + <Form.Label + className="my-1 mr-2" + htmlFor="inlineFormCustomSelectPref" + > + Month + </Form.Label> + <Form.Control + as="select" + className="my-1 mr-sm-2" + id="month" + custom + onChange={this.monthHandler} + > + <option value="0">Choose...</option> + { + React.Children.map(this.state.months, month=> + <option value={month}>{month}</option> + ) + } + </Form.Control> + + <Form.Label + className="my-1 mr-2" + htmlFor="inlineFormCustomSelectPref" + > + Day + </Form.Label> + <Form.Control + as="select" + className="my-1 mr-sm-2" + id="day" + custom + onChange={this.dayHandler} + > + <option value="0">Choose...</option> + { + React.Children.map(this.state.days, day=> + <option value={day}>{day}</option> + ) + } + </Form.Control> + + + </Form> + + + </div> + + ) + } +} + + +export default LAMpoints; \ No newline at end of file diff --git a/Tavara- raskaan liikenne/frontend/traffic/src/components/MultipleDayGraph.js b/Tavara- raskaan liikenne/frontend/traffic/src/components/MultipleDayGraph.js new file mode 100644 index 0000000..e69de29 diff --git a/Tavara- raskaan liikenne/frontend/traffic/src/components/OneDayGraph.js b/Tavara- raskaan liikenne/frontend/traffic/src/components/OneDayGraph.js new file mode 100644 index 0000000..864c2b8 --- /dev/null +++ b/Tavara- raskaan liikenne/frontend/traffic/src/components/OneDayGraph.js @@ -0,0 +1,598 @@ +import React, { Component } from "react"; +import axios from "axios"; +import Chart from "react-apexcharts"; +import Form from "react-bootstrap/Form"; + +import Button from "react-bootstrap/Button"; + +import ButtonGroup from "react-bootstrap/ButtonGroup"; + +var year = ""; +var fromDate; +var startDayNumber; + + +//const dayHour= [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]; +var VehicleNumberDataObjectForOneDay; +var AvgSpeedDataObjectForOneDay; + + +export class CarsGraph extends Component { + constructor(props) { + super(props); + this.state = { + options: {}, + series: [], + + options2: {}, + series2: [], + + year: "", + areaID: "", + lamID: "", + startDayNumber: "", + endDayNumber: "", + vehicleClass: '8',//8 means all classes + trafficDirection : 'both', + + error: "", + message:"", + toggleDisabled:true, + btnDisabled : false, + toggleHide : true, + isloading: false, + }; + this.yearHandler = this.yearHandler.bind(this); + this.lamIDHandler = this.lamIDHandler.bind(this); + this.areaIDHandler = this.areaIDHandler.bind(this); + this.startDayNumberHandler = this.startDayNumberHandler.bind(this); + this.vehicleClassHandler = this.vehicleClassHandler.bind(this); + this.trafficDirectionHandler = this.trafficDirectionHandler.bind(this); + } + + getData() { + var year_ = this.state.year; + var areaID = this.state.areaID; + var lamID = this.state.lamID; + var startDayNumber_ = this.state.startDayNumber; + var endDayNumber_ = this.state.endDayNumber; + + var url = `http://localhost:3030/api/vehicle/?year=${year_}&areaID=${areaID}&lamID=${lamID}&startDayNumber=${startDayNumber_}&endDayNumber=${endDayNumber_}`;//&vehicleClass=${vehicleClass} + axios + .get(url) + .then((res) => { + + console.log(res.status); + //if the user has put only one day + if (res.status === 200) { + + console.log(res.data); + //getting the vehicle number in each our based on vehicle class from response of the request + var vehicle_number = res.data.vehicle_number; + //getting the cars avarage speed based on car category + var avg_speed = res.data.avg_speed_km_h; + + + //filling the missing values of vehicle number to zero + let final_Vehicle_number = this.fillMissingValues(vehicle_number); + //console.log(final_Vehicle_number) + VehicleNumberDataObjectForOneDay = this.filterData(final_Vehicle_number); + //console.log(VehicleNumberDataObjectForOneDay); + + + //filling the missing values of avarage speed to zero + let final_avg_speed = this.fillMissingValues(avg_speed); + AvgSpeedDataObjectForOneDay = this.filterData(final_avg_speed); + + //getting the avarage speed of all cars in each hour and saving them i class '8' + Object.keys(AvgSpeedDataObjectForOneDay).forEach(hour =>{ + let direction1 = []; + let direction2 = []; + let Vclasses = AvgSpeedDataObjectForOneDay[hour]; + Object.keys(Vclasses).forEach(vclass=>{ + + if(vclass==='8'){ + const arrSum = arr => arr.reduce((a,b) => a + b, 0); + AvgSpeedDataObjectForOneDay[hour]['8']['1'] = ((arrSum(direction1))/direction1.length); + AvgSpeedDataObjectForOneDay[hour]['8']['2'] = ((arrSum(direction2))/direction2.length); + + let both = direction1.concat(direction2) + AvgSpeedDataObjectForOneDay[hour]['8']['both'] = Math.round(((arrSum(both))/both.length) * 10) / 10; + }else{ + if(AvgSpeedDataObjectForOneDay[hour][vclass]['1'] !==0){ + + direction1.push(AvgSpeedDataObjectForOneDay[hour][vclass]['1']) + } + if(AvgSpeedDataObjectForOneDay[hour][vclass]['2'] !==0){ + + direction2.push(AvgSpeedDataObjectForOneDay[hour][vclass]['2']) + } + let avg = + (AvgSpeedDataObjectForOneDay[hour][vclass]['1']+ + AvgSpeedDataObjectForOneDay[hour][vclass]['2'])/2; + + AvgSpeedDataObjectForOneDay[hour][vclass]['both'] = Math.round(avg * 10) / 10 + } + + }); + }); + + //using setDataForGraph function to set the filtered and sorted data as graph's data set + this.setDataForGraph(VehicleNumberDataObjectForOneDay,AvgSpeedDataObjectForOneDay); + this.setState({toggleDisabled: false,btnDisabled:false, toggleHide : false, message : ""}); + + + + }else { + console.log("Could not connect to server! code:",res.status) + this.setState({btnDisabled:false}); + } + + }) + .catch((er) => { + this.setState({btnDisabled:false}); + console.log(er); + }); + + } + + setDataForGraph = (Vnumber,Vspeed)=>{ + + var VCLASS = this.state.vehicleClass; + var dates=[]; + var numberData = []; + var speedData = []; + //data for graph + var trafficDirection = this.state.trafficDirection; + + Object.keys(Vnumber).forEach(key=>{ + dates.push(key); + numberData.push(Vnumber[key][VCLASS][trafficDirection]); + }); + Object.keys(Vspeed).forEach(key=>{ + speedData.push(Vspeed[key][VCLASS][trafficDirection]); + }); + + //Setting the fetched data as graph's input data + this.setState({ + //Data for vehcile number graph + options:{ + chart: { + id: "basic-bar" + }, + dataLabels: { + enabled: false + }, + xaxis: { + categories: dates, + title:{ + text : "Hour" + } + }, + yaxis: { + title: { + text: 'Vehicle Number' + } + }, + + + title: { + text: 'Number of vehicles in each hour of day', + align: 'center' + }, + legend: { + position: 'top', + horizontalAlign: 'right', + floating: true, + offsetY: -25, + offsetX: -5 + } + + }, + series:[{ + name: "Vehicle Number", + data: numberData + }], + //data for avarage speed garaph + options2:{ + chart: { + id: "basic-bar" + }, + dataLabels: { + enabled: false + }, + xaxis: { + categories: dates, + title:{ + text : "Time" + } + }, + yaxis: { + title: { + text: 'Avrage speed km/h' + }, + labels: { + formatter: function (value) { + return Math.round(value * 10)/10; + } + } + + }, + colors: ['#cc3b31'], + + title: { + text: 'Avrage Speed in each hour', + align: 'center' + }, + legend: { + position: 'top', + horizontalAlign: 'right', + floating: true, + offsetY: -25, + offsetX: -5 + } + }, + series2:[{ + name: "Avarage Speed km/h", + data: speedData + }], + + }); + } + + filterData= (input)=>{ + var DataObj = {}; + let d = {}; + let c = {}; + + let sum =0; + Object.keys(input).forEach((key)=>{ + let value = input[key]; + let keyToList = key.toString().split('_'); + + let dates = keyToList[0]; + let category = parseFloat(keyToList[1]); + let direction = parseFloat(keyToList[2]); + + c[direction] = Math.round(value * 10) / 10; + + sum = c['1']+c['2']; + c['both'] = sum; + d[category] = {...c}; + + //checking if all the classes 1-7 exists, and then creates class 8 which is total of all classes + if(d['1'] && d['2'] && d['3'] && d['4'] && d['5'] && d['6'] && d['7']){ + d['8'] = {1:0, 2:0, both:0}; + d['8']['1'] = d['1']['1'] + d['2']['1']+d['3']['1']+d['4']['1']+d['5']['1']+d['6']['1']+d['7']['1']; + d['8']['2'] = d['1']['2'] + d['2']['2']+d['3']['2']+d['4']['2']+d['5']['2']+d['6']['2']+d['7']['2']; + d['8']['both'] = d['8']['1'] + d['8']['2']; + + } + DataObj[dates] = {...d}; + //if() + + }); + return DataObj; + } + + +//function for filling the missing values like vehicle category and its number +fillMissingValues=(input)=>{ + let final = {}; + for (let i = 0; i <= 23; i++) { + for (let j = 1; j <= 7; j++) { + for(let x=1; x<=2;x++){ + const key = [`${i}_${j}_${x}`]; + final[key] = input[key]; + if (input[key] === undefined) { + final[key] = 0; + } + } + + } + } + return final; +} + + + + dateTodaynumber = (year, md) => { + var x = new Date(year, 0, 0); + x = x.getTime(); + + var d = md.split("."); + d = new Date(year, parseInt(d[0]) - 1, d[1]); + d = d.getTime(); + var sec = d - x; + var secToDay = sec / 1000 / 60 / 60 / 24; + secToDay = Math.floor(secToDay); + return secToDay; + } + + yearHandler(e) { + year = e.target.value; + this.setState({ year }); + } + areaIDHandler(e) { + var areaID = e.target.value; + this.setState({ areaID }); + } + lamIDHandler(e) { + var lamID = e.target.value; + this.setState({ lamID }); + } + startDayNumberHandler(e) { + fromDate = e.target.value; + startDayNumber = this.dateTodaynumber(year, e.target.value); + this.setState({ startDayNumber }); + } + + vehicleClassHandler(e) { + var vehicleClass = e.target.value; + this.setState({ vehicleClass },()=>{ + //one day data + //using setDataForGraph function to set the filtered and sorted data as graph's data set + this.setDataForGraph(VehicleNumberDataObjectForOneDay,AvgSpeedDataObjectForOneDay); + + }); + } + trafficDirectionHandler(e){ + var btnID = e.target.id; + + let trafficDirection; + if(btnID ==="direction1"){ + console.log(btnID) + trafficDirection=1; + }else if(btnID ==="direction2"){ + console.log(btnID) + trafficDirection=2; + }else if(btnID === "bothDirection"){ + console.log(btnID) + trafficDirection='both'; + } + this.setState({trafficDirection},()=>{ + //one day data + //using setDataForGraph function to set the filtered and sorted data as graph's data set + this.setDataForGraph(VehicleNumberDataObjectForOneDay,AvgSpeedDataObjectForOneDay); + }); + } + + buttonHandler = () => { + //checking for all input if they are fed with the right data + var patt = /^(0[1-9]|1[0-2])\.([0-2][0-9]|3[0-1])$/; + var matchPattern = patt.test(fromDate); + //console.log(matchPattern) + + if (!matchPattern) { + this.setState({ error: "Please insert a valid date mm.dd!" }); + } else { + this.setState({ error: "" }); + } + var inputs = [ + this.state.year, + this.state.areaID, + this.state.lamID, + this.state.vehicleClass, + ]; + if ( + (inputs[0] === "") | + (inputs[1] === "") | + (inputs[2] === "") | + !matchPattern + ) { + if(this.state.error !==""){ + this.setState({error: + "Please make sure that you have shosen right value for Year, Area, LAM point ID fields!", + }); + } + + } else { + this.setState({ + message : "Please wait while the data is beeing processed! Depending on your inputs This might take a while!", + btnDisabled : true + }) + + this.getData(); + console.log("Sending request to server!") + //console.log(this.state) + } + }; + + render() { + + return ( + <div className="oneDayGraphComponent"> + <div className="grid-container"> + <div className="grid-item-heading"> + Data analysis for one day + </div> + + <div className="grid-item-form"> + <div style={{ color: "red" }}>{this.state.error}</div> + <Form> + <Form.Row> + <Form.Label + className="my-1 mr-2" + htmlFor="inlineFormCustomSelectPref" + > + Year + </Form.Label> + <Form.Control + as="select" + className="my-1 mr-sm-2" + id="year" + custom + onChange={this.yearHandler} + > + <option value="0">Choose...</option> + <option value="2020">2020</option> + <option value="2019">2019</option> + <option value="2018">2018</option> + <option value="2017">2017</option> + <option value="2016">2016</option> + <option value="2015">2015</option> + <option value="2014">2014</option> + <option value="2013">2013</option> + <option value="2012">2012</option> + <option value="2011">2011</option> + <option value="2010">2010</option> + <option value="2009">2009</option> + </Form.Control> + + <Form.Label + className="my-1 mr-2" + htmlFor="inlineFormCustomSelectPref" + > + Month and day (mm.dd) + </Form.Label> + + <Form.Control + className="my-1 mr-sm-2" + id="dateFrom" + placeholder="mm.dd" + onChange={this.startDayNumberHandler} + pattern="(0[1-9]|1[0-2])\.([0-2]d|3[0-1])" + title="the right format is: mm.dd " + /> + + <Form.Label + className="my-1 mr-2" + htmlFor="inlineFormCustomSelectPref" + > + Choose an Area + </Form.Label> + <Form.Control + as="select" + className="my-1 mr-sm-2" + id="areaID" + custom + onChange={this.areaIDHandler} + > + <option value="">Choose...</option> + <option value="01">Uusimaa, Häme</option> + <option value="02">Varsinais-Suomi, Satakunta</option> + <option value="03">Kaakkois-Suomi</option> + <option value="04">Pirkanmaa</option> + <option value="08"> + Pohjois-Savo, Etelä-Savo, Pohjois-Karjala) + </option> + <option value="09">Keski-Suomi</option> + <option value="10">Etelä-Pohjanmaa, Pohjanmaa</option> + <option value="12">Pohjois-Pohjanmaa, Kainuu</option> + <option value="14">Lappi</option> + </Form.Control> + + <Form.Label + className="my-1 mr-2" + htmlFor="inlineFormCustomSelectPref" + > + LAM point ID + </Form.Label> + <Form.Control + as="select" + className="my-1 mr-sm-2" + id="lamID" + custom + onChange={this.lamIDHandler} + > + <option value="">Choose...</option> + <option value="101">101</option> + </Form.Control><br/> + + <Button + type="button" + className="my-1 mr-sm-2" + id="drawGraph" + onClick={this.buttonHandler} + disabled={this.state.btnDisabled} + block + > + {this.state.btnDisabled ? 'Loading ...' : 'Draw Graph'} + </Button> + </Form.Row> + </Form> + + <div style={{ color: "blue" }}> + {this.state.message} + </div><br/> + + <Form.Label + className="my-1 mr-2" + htmlFor="inlineFormCustomSelectPref" + > + vehicle Category + </Form.Label> + <Form.Control + as="select" + className="my-1 mr-sm-2" + id="vehicleClass" + custom + onChange={this.vehicleClassHandler} + disabled={this.state.toggleDisabled} + > + <option value="8">All</option> + <option value="1">1 HA-PA (henkilö- tai pakettiauto)</option> + <option value="2">2 KAIP (kuorma-auto ilman perävaunua)</option> + <option value="3">3 Linja-autot</option> + <option value="4">4 KAPP (kuorma-auto ja puoliperävaunu)</option> + <option value="5">5 KATP (kuorma-auto ja täysperävaunu)</option> + <option value="6">6 HA + PK (henkilöauto ja peräkärry)</option> + <option value="7">7 HA + AV (henkilöauto ja asuntovaunu)</option> + </Form.Control> + + + <ButtonGroup size="sm" className="mb-2 " style={{width :"100%"}} hidden={this.state.toggleHide}> + <Button + type="button" + className="my-4" + id="direction1" + onClick={this.trafficDirectionHandler} + >Direction 1</Button> + + <Button + type="button" + className="my-4" + id="direction2" + onClick={this.trafficDirectionHandler} + >Direction 2</Button> + + <Button + style={{minWidth : 120 }} + type="button" + className="my-4" + id="bothDirection" + onClick={this.trafficDirectionHandler} + >Both Direction</Button> + </ButtonGroup> + </div> + + <div className="grid-item-graph1"> + <div className="grid-item-graph-child"> + <Chart + options={this.state.options} + series={this.state.series} + type="bar" + width="500" + /> + </div> + + </div> + + <div className="grid-item-graph2"> + <div className="grid-item-graph-child"> + <Chart + options={this.state.options2} + series={this.state.series2} + type="bar" + width="500" + /> + </div> + </div> + </div> + </div> + ); + } +} + +export default CarsGraph; + diff --git a/Tavara- raskaan liikenne/frontend/traffic/src/components/OneDayGraph_v2.js b/Tavara- raskaan liikenne/frontend/traffic/src/components/OneDayGraph_v2.js new file mode 100644 index 0000000..5f39751 --- /dev/null +++ b/Tavara- raskaan liikenne/frontend/traffic/src/components/OneDayGraph_v2.js @@ -0,0 +1,509 @@ +import React, { Component } from "react"; +import axios from "axios"; +import Chart from "react-apexcharts"; +import Form from "react-bootstrap/Form"; +import Col from "react-bootstrap/Col"; +import Button from "react-bootstrap/Button"; +import Row from "react-bootstrap/Row"; +import ButtonGroup from "react-bootstrap/ButtonGroup"; + +var year = ""; +var fromDate; +var startDayNumber; + + +const dayHour= [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23]; +var VehicleNumberDataObjectForOneDay; +var AvgSpeedDataObjectForOneDay; + + +export class CarsGraph extends Component { + constructor(props) { + super(props); + this.state = { + options: {}, + series: [], + + options2: {}, + series2: [], + + year: "", + areaID: "", + lamID: "", + startDayNumber: "", + endDayNumber: "", + vehicleClass: '8',//8 means all classes + trafficDirection : 'both', + + error: "", + message:"", + toggleDisabled:true, + btnDisabled : false, + toggleHide : true, + isloading: false, + }; + this.yearHandler = this.yearHandler.bind(this); + this.lamIDHandler = this.lamIDHandler.bind(this); + this.areaIDHandler = this.areaIDHandler.bind(this); + this.startDayNumberHandler = this.startDayNumberHandler.bind(this); + this.vehicleClassHandler = this.vehicleClassHandler.bind(this); + this.trafficDirectionHandler = this.trafficDirectionHandler.bind(this); + } + + getData() { + var year_ = this.state.year; + var areaID = this.state.areaID; + var lamID = this.state.lamID; + var startDayNumber_ = this.state.startDayNumber; + var endDayNumber_ = this.state.endDayNumber; + + var url = `http://localhost:3030/api/vehicle/?year=${year_}&areaID=${areaID}&lamID=${lamID}&startDayNumber=${startDayNumber_}&endDayNumber=${endDayNumber_}`;//&vehicleClass=${vehicleClass} + axios + .get(url) + .then((res) => { + + console.log(res.status); + //if the user has put only one day + if (res.status === 200) { + + console.log(res.data); + //getting the vehicle number in each our based on vehicle class from response of the request + var vehicle_number = res.data.vehicle_number; + //getting the cars avarage speed based on car category + var avg_speed = res.data.avg_speed_km_h; + + + //filling the missing values of vehicle number to zero + let final_Vehicle_number = this.fillMissingValues(vehicle_number); + //console.log(final_Vehicle_number) + VehicleNumberDataObjectForOneDay = this.filterData(final_Vehicle_number); + //console.log(VehicleNumberDataObjectForOneDay); + + + //filling the missing values of avarage speed to zero + let final_avg_speed = this.fillMissingValues(avg_speed); + AvgSpeedDataObjectForOneDay = this.filterData(final_avg_speed); + + //getting the avarage speed of all cars in each hour and saving them i class '8' + Object.keys(AvgSpeedDataObjectForOneDay).forEach(hour =>{ + let direction1 = []; + let direction2 = []; + let Vclasses = AvgSpeedDataObjectForOneDay[hour]; + Object.keys(Vclasses).forEach(vclass=>{ + + if(vclass==='8'){ + const arrSum = arr => arr.reduce((a,b) => a + b, 0); + AvgSpeedDataObjectForOneDay[hour]['8']['1'] = ((arrSum(direction1))/direction1.length); + AvgSpeedDataObjectForOneDay[hour]['8']['2'] = ((arrSum(direction2))/direction2.length); + + let both = direction1.concat(direction2) + AvgSpeedDataObjectForOneDay[hour]['8']['both'] = Math.round(((arrSum(both))/both.length) * 10) / 10; + }else{ + if(AvgSpeedDataObjectForOneDay[hour][vclass]['1'] !==0){ + + direction1.push(AvgSpeedDataObjectForOneDay[hour][vclass]['1']) + } + if(AvgSpeedDataObjectForOneDay[hour][vclass]['2'] !==0){ + + direction2.push(AvgSpeedDataObjectForOneDay[hour][vclass]['2']) + } + let avg = + (AvgSpeedDataObjectForOneDay[hour][vclass]['1']+ + AvgSpeedDataObjectForOneDay[hour][vclass]['2'])/2; + + AvgSpeedDataObjectForOneDay[hour][vclass]['both'] = Math.round(avg * 10) / 10 + } + + }); + }); + + //using setDataForGraph function to set the filtered and sorted data as graph's data set + this.setDataForGraph(VehicleNumberDataObjectForOneDay,AvgSpeedDataObjectForOneDay); + this.setState({toggleDisabled: false,btnDisabled:false, toggleHide : false, message : ""}); + + + + }else { + console.log("Could not connect to server! code:",res.status) + this.setState({btnDisabled:false}); + } + + }) + .catch((er) => { + this.setState({btnDisabled:false}); + console.log(er); + }); + + } + + setDataForGraph = (Vnumber,Vspeed)=>{ + + var VCLASS = this.state.vehicleClass; + var dates=[]; + var numberData = []; + var speedData = []; + //data for graph + var trafficDirection = this.state.trafficDirection; + + Object.keys(Vnumber).forEach(key=>{ + dates.push(key); + numberData.push(Vnumber[key][VCLASS][trafficDirection]); + }); + Object.keys(Vspeed).forEach(key=>{ + speedData.push(Vspeed[key][VCLASS][trafficDirection]); + }); + + //Setting the fetched data as graph's input data + this.setState({ + //Data for vehcile number graph + options:{ + chart: { + id: "basic-bar" + }, + dataLabels: { + enabled: false + }, + xaxis: { + categories: dates, + title:{ + text : "Hour" + } + }, + yaxis: { + title: { + text: 'Vehicle Number' + } + }, + + + title: { + text: 'Number of vehicles in each hour of day', + align: 'center' + }, + legend: { + position: 'top', + horizontalAlign: 'right', + floating: true, + offsetY: -25, + offsetX: -5 + } + + }, + series:[{ + name: "Vehicle Number", + data: numberData + }], + //data for avarage speed garaph + options2:{ + chart: { + id: "basic-bar" + }, + dataLabels: { + enabled: false + }, + xaxis: { + categories: dates, + title:{ + text : "Time" + } + }, + yaxis: { + title: { + text: 'Avrage speed km/h' + }, + labels: { + formatter: function (value) { + return Math.round(value * 10)/10; + } + } + + }, + colors: ['#cc3b31'], + + title: { + text: 'Avrage Speed in each hour', + align: 'center' + }, + legend: { + position: 'top', + horizontalAlign: 'right', + floating: true, + offsetY: -25, + offsetX: -5 + } + }, + series2:[{ + name: "Avarage Speed km/h", + data: speedData + }], + + }); + } + + filterData= (input)=>{ + var DataObj = {}; + let d = {}; + let c = {}; + + let sum =0; + Object.keys(input).forEach((key)=>{ + let value = input[key]; + let keyToList = key.toString().split('_'); + + let dates = keyToList[0]; + let category = parseFloat(keyToList[1]); + let direction = parseFloat(keyToList[2]); + + c[direction] = Math.round(value * 10) / 10; + + sum = c['1']+c['2']; + c['both'] = sum; + d[category] = {...c}; + + //checking if all the classes 1-7 exists, and then creates class 8 which is total of all classes + if(d['1'] && d['2'] && d['3'] && d['4'] && d['5'] && d['6'] && d['7']){ + d['8'] = {1:0, 2:0, both:0}; + d['8']['1'] = d['1']['1'] + d['2']['1']+d['3']['1']+d['4']['1']+d['5']['1']+d['6']['1']+d['7']['1']; + d['8']['2'] = d['1']['2'] + d['2']['2']+d['3']['2']+d['4']['2']+d['5']['2']+d['6']['2']+d['7']['2']; + d['8']['both'] = d['8']['1'] + d['8']['2']; + + } + DataObj[dates] = {...d}; + //if() + + }); + return DataObj; + } + + +//function for filling the missing values like vehicle category and its number +fillMissingValues=(input)=>{ + let final = {}; + for (let i = 0; i <= 23; i++) { + for (let j = 1; j <= 7; j++) { + for(let x=1; x<=2;x++){ + const key = [`${i}_${j}_${x}`]; + final[key] = input[key]; + if (input[key] === undefined) { + final[key] = 0; + } + } + + } + } + return final; +} + + + + dateTodaynumber = (year, md) => { + var x = new Date(year, 0, 0); + x = x.getTime(); + + var d = md.split("."); + d = new Date(year, parseInt(d[0]) - 1, d[1]); + d = d.getTime(); + var sec = d - x; + var secToDay = sec / 1000 / 60 / 60 / 24; + secToDay = Math.floor(secToDay); + return secToDay; + } + + yearHandler(e) { + year = e.target.value; + this.setState({ year }); + } + areaIDHandler(e) { + var areaID = e.target.value; + this.setState({ areaID }); + } + lamIDHandler(e) { + var lamID = e.target.value; + this.setState({ lamID }); + } + startDayNumberHandler(e) { + fromDate = e.target.value; + startDayNumber = this.dateTodaynumber(year, e.target.value); + this.setState({ startDayNumber }); + } + + vehicleClassHandler(e) { + var vehicleClass = e.target.value; + this.setState({ vehicleClass },()=>{ + //one day data + //using setDataForGraph function to set the filtered and sorted data as graph's data set + this.setDataForGraph(VehicleNumberDataObjectForOneDay,AvgSpeedDataObjectForOneDay); + + }); + } + trafficDirectionHandler(e){ + var btnID = e.target.id; + + let trafficDirection; + if(btnID ==="direction1"){ + console.log(btnID) + trafficDirection=1; + }else if(btnID ==="direction2"){ + console.log(btnID) + trafficDirection=2; + }else if(btnID === "bothDirection"){ + console.log(btnID) + trafficDirection='both'; + } + this.setState({trafficDirection},()=>{ + //one day data + //using setDataForGraph function to set the filtered and sorted data as graph's data set + this.setDataForGraph(VehicleNumberDataObjectForOneDay,AvgSpeedDataObjectForOneDay); + }); + } + + buttonHandler = () => { + //checking for all input if they are fed with the right data + var patt = /^(0[1-9]|1[0-2])\.([0-2][0-9]|3[0-1])$/; + var matchPattern = patt.test(fromDate); + //console.log(matchPattern) + + if (!matchPattern) { + this.setState({ error: "Please insert a valid date mm.dd!" }); + } else { + this.setState({ error: "" }); + } + var inputs = [ + this.state.year, + this.state.areaID, + this.state.lamID, + this.state.vehicleClass, + ]; + if ( + (inputs[0] === "") | + (inputs[1] === "") | + (inputs[2] === "") | + !matchPattern + ) { + if(this.state.error !==""){ + this.setState({error: + "Please make sure that you have shosen right value for Year, Area, LAM point ID fields!", + }); + } + + } else { + this.setState({ + message : "Please wait while the data is beeing processed! Depending on your inputs This might take a while!", + btnDisabled : true + }) + + this.getData(); + console.log("Sending request to server!") + //console.log(this.state) + } + }; + + render() { + + return ( + <div className="oneDayGraphComponent"> + <div className="grid-container"> + <div class="grid-item-heading"> + Data analysis for one day + </div> + + <div class="grid-item-form"> + <div style={{ color: "red" }}>{this.state.error}</div> + + <Button + type="button" + className="my-1 mr-sm-2" + id="drawGraph" + onClick={this.buttonHandler} + disabled={this.state.btnDisabled} + block + > + {this.state.btnDisabled ? 'Loading ...' : 'Draw Graph'} + </Button> + + + + <div style={{ color: "blue" }}> + {this.state.message} + </div><br/> + + <Form.Label + className="my-1 mr-2" + htmlFor="inlineFormCustomSelectPref" + > + vehicle Category + </Form.Label> + <Form.Control + as="select" + className="my-1 mr-sm-2" + id="vehicleClass" + custom + onChange={this.vehicleClassHandler} + disabled={this.state.toggleDisabled} + > + <option value="8">All</option> + <option value="1">1 HA-PA (henkilö- tai pakettiauto)</option> + <option value="2">2 KAIP (kuorma-auto ilman perävaunua)</option> + <option value="3">3 Linja-autot</option> + <option value="4">4 KAPP (kuorma-auto ja puoliperävaunu)</option> + <option value="5">5 KATP (kuorma-auto ja täysperävaunu)</option> + <option value="6">6 HA + PK (henkilöauto ja peräkärry)</option> + <option value="7">7 HA + AV (henkilöauto ja asuntovaunu)</option> + </Form.Control> + + + <ButtonGroup size="sm" className="mb-2 " style={{width :"100%"}} hidden={this.state.toggleHide}> + <Button + type="button" + className="my-4" + id="direction1" + onClick={this.trafficDirectionHandler} + >Direction 1</Button> + + <Button + type="button" + className="my-4" + id="direction2" + onClick={this.trafficDirectionHandler} + >Direction 2</Button> + + <Button + style={{minWidth : 120 }} + type="button" + className="my-4" + id="bothDirection" + onClick={this.trafficDirectionHandler} + >Both Direction</Button> + </ButtonGroup> + </div> + + <div class="grid-item-graph1"> + <div className="grid-item-graph-child"> + <Chart + options={this.state.options} + series={this.state.series} + type="bar" + width="500" + /> + </div> + + </div> + + <div class="grid-item-graph2"> + <div className="grid-item-graph-child"> + <Chart + options={this.state.options2} + series={this.state.series2} + type="bar" + width="500" + /> + </div> + </div> + </div> + </div> + ); + } +} + +export default CarsGraph; + diff --git a/Tavara- raskaan liikenne/frontend/traffic/src/components/TestRequest.js b/Tavara- raskaan liikenne/frontend/traffic/src/components/TestRequest.js index a1a37c6..55bd4a9 100644 --- a/Tavara- raskaan liikenne/frontend/traffic/src/components/TestRequest.js +++ b/Tavara- raskaan liikenne/frontend/traffic/src/components/TestRequest.js @@ -13,7 +13,7 @@ export class TestRequest extends Component { }; } - async componentDidMount() { + async componentDidM() { console.log("sending req!") var url = `http://localhost:3030/api/vehicle/?year=2019&areaID=01&lamID=101&startDayNumber=5&endDayNumber=36`;//&vehicleClass=${vehicleClass} // Step 1: start the fetch and obtain a reader @@ -37,31 +37,38 @@ export class TestRequest extends Component { chunks.push(value); receivedLength += value.length; - //console.log(`Received ${receivedLength} of ${contentLength}`) - } + console.log(`Received ${receivedLength} of ${contentLength}`) - // Step 4: concatenate chunks into single Uint8Array - let chunksAll = new Uint8Array(receivedLength); // (4.1) - let position = 0; - for(let chunk of chunks) { - chunksAll.set(chunk, position); // (4.2) - position += chunk.length; + let result = new TextDecoder("utf-8").decode(value); + console.log(result) } + // // Step 4: concatenate chunks into single Uint8Array + // let chunksAll = new Uint8Array(receivedLength); // (4.1) + // let position = 0; + // for(let chunk of chunks) { + // chunksAll.set(chunk, position); // (4.2) + // position += chunk.length; + // } + // Step 5: decode into a string - let result = new TextDecoder("utf-8").decode(chunksAll); + //let result = new TextDecoder("utf-8").decode(chunksAll); // We're done! - let commits = JSON.parse(result); + //let commits = JSON.parse(result); - console.log("here is the final result", commits) + //console.log("here is the final result", commits) } render() { return ( - <div> - - TestRequest Component + <div className="grid-container"> + <div className="grid-item-heading">Data for a day</div> + <div className="grid-item-form">inputs and info</div> + <div className="grid-item-graph1"> car number graph</div> + <div className="grid-item-graph2">speed graph</div> + + </div> ) diff --git a/Tavara- raskaan liikenne/python/cars/lamData.py b/Tavara- raskaan liikenne/python/cars/lamData.py index e81af56..6e44462 100644 --- a/Tavara- raskaan liikenne/python/cars/lamData.py +++ b/Tavara- raskaan liikenne/python/cars/lamData.py @@ -24,7 +24,8 @@ if(check == False): end = int(endDayNumber) duration = (end+1) - start - vehicleTotalNumberInOneDay = pd.DataFrame() + #vehicleTotalNumberInOneDay = pd.DataFrame() + date = [] day = start for x in range(duration): @@ -39,6 +40,7 @@ if(check == False): dt=dt.strftime('%d.%m.%Y') date.append(dt) + temp = pd.DataFrame() #temp = csv.groupby(["vehicle_class"])["vehicle_class"].count() temp = csv.groupby(["vehicle_class","direction"]).agg({"vehicle_class":"count", "speed_km/h":"mean"})\ .rename(columns={'vehicle_class':'vehicle_number','speed_km/h':'avg_speed_km_h'}) @@ -54,16 +56,23 @@ if(check == False): #setting the new index to dataframe temp["date_vehicleclass_direction"]= newindex temp.set_index("date_vehicleclass_direction", inplace= True) - vehicleTotalNumberInOneDay= vehicleTotalNumberInOneDay.append(temp) + #vehicleTotalNumberInOneDay= vehicleTotalNumberInOneDay.append(temp) + + output= temp + output['avg_speed_km_h'] = output['avg_speed_km_h'].astype(float).round(1) + outputJson = output.to_json() + print(outputJson) + sys.stdout.flush() + day +=1 - output= vehicleTotalNumberInOneDay - output['avg_speed_km_h'] = output['avg_speed_km_h'].astype(float).round(1) - outputJson = output.to_json() - print(outputJson) - sys.stdout.flush() + # output= vehicleTotalNumberInOneDay + # output['avg_speed_km_h'] = output['avg_speed_km_h'].astype(float).round(1) + # outputJson = output.to_json() + # print(outputJson) + # sys.stdout.flush() #data for only one day else: @@ -78,12 +87,24 @@ else: dt = dt + dtdelta dt=dt.strftime('%d.%m.%Y') - # df = allData.groupby(["hour","vehicle_class","direction"]).agg({"vehicle_class": "count", "speed_km/h":"mean"})\ - # .rename(columns={'vehicle_class':'vehicle_number','speed_km/h':'avg_speed_km_h'}) - - df = allData.groupby(["hour","vehicle_class"]).agg({"vehicle_class": "count", "speed_km/h":"mean"})\ + df = allData.groupby(["hour","vehicle_class","direction"]).agg({"vehicle_class": "count", "speed_km/h":"mean"})\ .rename(columns={'vehicle_class':'vehicle_number','speed_km/h':'avg_speed_km_h'}) + + #df = allData.groupby(["hour","vehicle_class"]).agg({"vehicle_class": "count", "speed_km/h":"mean"})\ + # .rename(columns={'vehicle_class':'vehicle_number','speed_km/h':'avg_speed_km_h'}) df['avg_speed_km_h'] = df['avg_speed_km_h'].astype(float).round(1) + + #changing indexes to create uniqe indexs containing date and vehicle class + indexv = df.index.values.tolist() + newindex = [] + for i in range(len(indexv)): + a= list(indexv[i]) + ind = str(a[0])+"_"+str(a[1])+"_"+str(a[2]) + newindex.append(ind) + + df["date_vehicleclass_direction"]= newindex + df.set_index("date_vehicleclass_direction", inplace= True) + outjson = df.to_json() print(outjson) sys.stdout.flush() \ No newline at end of file -- GitLab