let _list; let _totList; let ixrNm; let istlLctn; let unit; let strtDt; let endDt; let searchBtn; let closeBtn; let _multiChart; let _pieChart; const _pageName = '교통량 통계'; const dateTime = 'yyyy-MM-dd HH:mm'; const dateHour = 'yyyy-MM-dd HH시'; const time = 'HH:mm'; const hour = 'HH시'; const date = 'yyyy-MM-dd'; const month = 'yyyy-MM'; let strtDtVal = new Date(); let endDtVal = new Date(); strtDtVal.setHours("00"); strtDtVal.setMinutes("00"); strtDtVal.setSeconds("00"); endDtVal.setHours("23"); endDtVal.setMinutes("59"); endDtVal.setSeconds("59"); let searchStart = firstSettingTime; let searchEnd = endSettingTime; const drctMap = new Map(); const categories = ['-', 'A', 'B', 'C', 'D', 'E', 'F', 'FF', 'FFF']; const pieSeries = [ { name :'교통량 통계 조회 (합계)', data : [ { id : 'go_tfvl', name : '직진', color : 'coral', y : 0, }, { id : 'left_tfvl', name : '좌회전', color : 'rgb(124, 181, 236)', y : 0, }, { id : 'rght_tfvl', name : '우회전', color : 'rgb(144, 237, 125)', y : 0, } ] }, ] const multiSeries = [ { name: '직진', type : 'column', data: [], color : 'coral', }, { name: '좌회전', type : 'column', data: [], color : 'rgb(124, 181, 236)', }, { name: '우회전', type : 'column', data: [], color : 'rgb(144, 237, 125)', }, { name: '서비스수준 ( LOS )', type : 'line', yAxis: 1, data: [], color : 'red', } ] const lookupData = [ { code : 0, desc : '-', }, { code : 1, desc : 'A', }, { code : 2, desc : 'B', }, { code : 3, desc : 'C', }, { code : 4, desc : 'D', }, { code : 5, desc : 'E', }, { code : 6, desc : 'F', }, { code : 7, desc : 'FF', }, { code : 8, desc : 'FFF', } ] const unitData = [ { unit : '15m', desc : '15분 통계', }, // { // unit : '30m', // desc : '30분 통계', // }, { unit : 'hh', desc : '시간 통계(1시간)', }, { unit : 'dd', desc : '일 통계(1일)', }, { unit : 'mn', desc : '월 통계(1개월)', }, ]; $(()=>{ //교차로교통량 통계 테이블 let listColumns = [ { dataField : "ixr_nm", caption : '교차로명', alignment : 'center', }, { dataField : "stat_dt", caption : '수집일시', alignment : 'center', sortIndex : 1, sortOrder : 'asc', }, { caption : '교통량(대)', alignment : "center", columns : [ { dataField : "go_tfvl", caption : '직진', alignment : 'center', format : '#,##0', width : 80, }, { dataField : "left_tfvl", caption : '좌회전', alignment : 'center', format : '#,##0', width : 90, }, { dataField : "rght_tfvl", caption : '우회전', alignment : 'center', format : '#,##0', width : 90, }, { dataField : "tot_tfvl", caption : '총교통량', alignment : "center", format : '#,##0', width : 120, }, ], }, { dataField : "dely_hh", caption : '지체시간(초/대)', alignment : "center", width : 140, }, { dataField : "srvc_lvl", caption : 'LOS', alignment : "center", width : 70, lookup : { dataSource : lookupData, displayExpr : 'desc', valueExpr : 'code', } }, ]; _list = initializedGrid($(".list"), '100%', '100%', listColumns, [], 'single', 'virtual', ['ixr_nm', 'stat_dt'], false, true, false, '', false, false, true, _pageName, true, '', null).dxDataGrid('instance'); //교차로교통량 통계 합계 테이블 let totColumns = [ { dataField : "go_tfvl", caption : '직진', alignment : 'center', format : '#,##0', }, { dataField : "left_tfvl", caption : '좌회전', alignment : 'center', format : '#,##0', }, { dataField : "rght_tfvl", caption : '우회전', alignment : 'center', format : '#,##0', }, { dataField : "tot_tfvl", caption : '총교통량', alignment : "center", format : '#,##0', }, ]; _totList = initializedGrid($(".tot-list"), '100%', '100%', totColumns, [], 'none', 'virtual', '', false, false, false, '', false, false, false, '', false, '', null).dxDataGrid('instance'); _totList.option('sorting', {mode : 'none'}); ixrNm = new dxSelect($(".ixr_nm"), 'outlined', 300, 30, 'ixr_nm', 'ixr_id', false, 'ixr_id', '교차로명'); istlLctn = new dxSelect($(".istl_lctn"), 'outlined', 300, 30, 'desc', 'cmra_id', false, 'cmra_id', '설치위치'); unit = new dxSelect($(".unit"), 'outlined', 150, 30, 'desc', 'unit', false, 'unit', '단위'); strtDt = new dxDate($(".strt-dt"), 'yyyy-MM-dd', '조회기간 시작일', 110, 30, 'date', null, '', null); strtTime = new dxDate($(".strt-time"), 'HH:mm', '조회기간 시각', 80, 30, 'time', 5, '', null); endDt = new dxDate($(".end-dt"), 'yyyy-MM-dd', '조회기간 종료일', 110, 30, 'date', null, '', null); endTime = new dxDate($(".end-time"), 'HH:mm', '조회기간 시각', 80, 30, 'time', 5, '', null); unit.setDataSource(unitData); unit.setValue('15m'); unit.onItemClick(unitClick); strtDt.setValue(strtDtVal); strtTime.setValue(strtDtVal); endDt.setValue(endDtVal); endTime.setValue(endDtVal); ixrNm.onItemClick((e)=>ixrNmClick(e.itemData.ixr_id)); searchBtn = new dxBtn($(".search-btn"),'조회', 'refresh', 'outlined', 80, 30, false, true); closeBtn = new dxBtn($(".close-btn"), '닫기', 'close', 'outlined', 80, 30, false, true); closeBtn.onClick(()=>window.close()); searchBtn.onClick(searchBtnClick); _multiChart = Highcharts.chart('multi-chart', { chart: { type: 'column', backgroundColor: { classNmae: 'dx-theme-background-color dx-theme-border-color', }, }, title: { text : '교통량 통계 조회', style : { color: $('.dx-theme-material-typography').css('color'), }, }, xAxis: { categories: [], labels: { style: { color: $('.dx-theme-material-typography').css('color') } }, }, yAxis: [{ ticks : 5, labels: { style: { color: $('.dx-theme-material-typography').css('color') } }, title: { text: '교통량(대)', style: { color: $('.dx-theme-material-typography').css('color') } } }, { // Secondary yAxis min : 1, max : 8, title: { text: '서비스수준(LOS)', style: { color: $('.dx-theme-material-typography').css('color'), } }, labels: { style: { color: $('.dx-theme-material-typography').css('color'), }, }, categories : categories, opposite: true, }], plotOptions: { column: { stacking: 'percent' } }, legend: { align: 'center', verticalAlign: 'bottom', itemStyle:{ color: $('.dx-theme-material-typography').css('color'), }, backgroundColor: { className : 'dx-nav-item dx-theme-border-color', } }, series : multiSeries, tooltip: { formatter: function () { let name = this.series.name; let dt = name.substring(0,name.indexOf('(')); if (this.series.name.indexOf('( LOS )') > -1) { let rank = this.series.yAxis.categories[this.y]; if (this.y >= 0){ return '교통량 통계 조회
' + '일시 : ' + this.x + '
' + '서비스수준(LOS) : ' + rank + ''; } } else { return '교통량 통계 조회 - ' + name +'
' + '일시 : ' + this.x + '
' + '교통량 : ' + this.y + ' 대'; } } }, exporting : { enabled : false, }, credits : { enabled : false }, }); _pieChart = Highcharts.chart('pie-chart', { chart: { type: 'pie', marginLeft: 20, marginTop : 20, plotBackgroundColor: null, plotBorderWidth: null, plotShadow: false, backgroundColor: { classNmae: 'dx-theme-background-color dx-theme-border-color', }, }, title: { text : '교통량 통계 조회 (합계)', y : 35, style : { color: $('.dx-theme-material-typography').css('color'), }, }, plotOptions: { pie: { allowPointSelect: true, cursor: 'pointer', size: '70%', dataLabels: { enabled: true, format: '{point.name}
{point.y:,.0f} 대', distance: -50, filter: { property: 'percentage', operator: '>', value: 4 }, color: $('.dx-theme-material-typography').css('color'), }, showInLegend: true } }, tooltip : { pointFormat: '{series.name}: {point.y}대' }, legend: { layout: 'vertical', align: 'left', verticalAlign: 'top', floating: false, y: 0, borderWidth: 1, itemStyle:{ color: $('.dx-theme-material-typography').css('color'), }, backgroundColor: { className : 'dx-nav-item dx-theme-border-color', }, shadow: true, }, exporting : { enabled : false, }, credits : { enabled : false }, series : pieSeries, }); window.$chartArr = [_multiChart, _pieChart]; fetchBaseData(); }) function fetchBaseData(){ const uri = "/api/scrs/tb_sc_ixr_mngm"; let drctData = []; getData(_codeUrl + '/DRCT', drctData); if (drctData[0] && drctData[0].length > 0) { drctData[0].map((item)=>{ drctMap.set(Number(item.cmmn_cd), item.cmmn_cd_kor_nm); }) } getDataAsync(uri, (jsonData)=>{ dataSorting(jsonData, 'ixr_nm'); ixrNm.setDataSource(jsonData); if (jsonData[0]) { ixrNm.setValue(jsonData[0].ixr_id); ixrNmClick(jsonData[0].ixr_id); } }) } /** * 교차로 명칭 클릭 이벤트 * @param ixrIdVal 교차로 Id */ function ixrNmClick(ixrIdVal){ let istlData = []; getData('/api/scrs/tb_sc_ixr_cmra_mngm/' + encodeURIComponent(ixrIdVal), istlData); if (istlData[0] && istlData[0].length > 0) { istlData[0].map((item)=>{ item.desc = item.istl_lctn + ' [' + drctMap.get(item.drct_dvsn_cd) + ']'; }) istlLctn.setValue(istlData[0][0].cmra_id); } istlLctn.setDataSource(istlData[0]); } /** * 단위 클릭 변경 이벤트 * @param {*} e select 상자 정보 */ function unitClick(e){ if (e.itemData && e.itemData.unit) { let format = null; let display = null; let changeColumn = null; const dateColumn = [strtDt, endDt]; const timeColumn = [strtTime, endTime]; const strtTimeBox = $('.strt-time-box'); const endTimeBox = $('.end-time-box'); switch (e.itemData.unit) { case 'hh': changeColumn = 'time'; format = hour; display = 'flex'; break; case 'dd': changeColumn = 'date'; format = date; display = 'none'; break; case 'mn': changeColumn = 'date'; format = month; display = 'none'; break; default : changeColumn = 'time'; format = time; display = 'flex'; break; } if (changeColumn) { if (changeColumn === 'time') { timeColumn.map((item)=>{ item.setFormat(format); }); dateColumn.map((item)=>{ item.setFormat(date); }); } else { dateColumn.map((item)=>{ item.setFormat(format); }); } strtTimeBox.css('display', display); endTimeBox.css('display', display); } } } /** * 상단 조회 버튼 이벤트 * @returns 유효성 체크용 */ function searchBtnClick(){ if (ixrNm.isNull()) { return alertWarning('교차로명을 선택해주세요', null, ixrNm); } else if (istlLctn.isNull()) { return alertWarning('설치위치를 선택해주세요', null, istlLctn); } const unitVal = unit.getValue(); let timeArr = getSearchValues(unitVal); if (timeArr.length === 0){ return; }; const FROM_DT = timeArr[0]; const TO_DT = timeArr[1]; const idVal = ixrNm.getValue(); const cmraVal = istlLctn.getValue() let statData = { ixrId : idVal, cmraIds : cmraVal, FROM_DT : FROM_DT, TO_DT : TO_DT, }; let losData = { ixrIds : idVal, FROM_DT : FROM_DT, TO_DT : TO_DT, }; const stat = []; getData("/api/scrs/statistics/tfvl/" + unitVal + '/' + idVal, stat, statData); // 교차로 통계 const los = []; getData("/api/scrs/statistics/srvc/" + unitVal, los, losData); // 서비스수준 통계 let formatData = []; if (stat[0] && stat[0].length > 0) { stat[0].map((item)=>{ let clone = {...item}; if (los[0] && los[0].length > 0) { los[0].map((obj)=>{ if (item.ixr_id === obj.ixr_id && item.stat_dt === obj.stat_dt) { clone.srvc_lvl = nullChecker(obj.srvc_lvl) === "" ? 0 : obj.srvc_lvl; clone.dely_hh = nullChecker(obj.dely_hh) === "" ? '-' : obj.dely_hh; } }) } formatData.push(clone); }) } drawTableAndChart(formatData, unitVal); } function drawTableAndChart(jsonData, unitVal){ let xAxis = []; let totGo = 0; let totLeft = 0; let totRght = 0; let totTot = 0; let totDataSource; let yAxis = [ {data: []}, {data: []}, {data: []}, {data: []}, ]; if (jsonData.length > 0) { dataSorting(jsonData, 'clct_dt'); jsonData.map((item)=>{ console.log(item); if (item.stat_dt) item.stat_dt = timeFommater(item.stat_dt, unitVal); item.go_tfvl = 0; item.left_tfvl = 0; item.rght_tfvl = 0; for (let key in item) { if (key.indexOf("pce_") === -1 ) { if ( key.indexOf('go') > -1 && key !== 'go_tfvl' ) { item.go_tfvl += item[key]; } if ( key.indexOf('left') > -1 && key !== 'left_tfvl' ) { item.left_tfvl += item[key]; } if ( key.indexOf('rght') > -1 && key !== 'rght_tfvl') { item.rght_tfvl += item[key]; } } } item.tot_tfvl = item.go_tfvl + item.left_tfvl + item.rght_tfvl; totGo += item.go_tfvl; totLeft += item.left_tfvl; totRght += item.rght_tfvl; totTot += item.tot_tfvl; yAxis[0].data.push(item.go_tfvl); yAxis[1].data.push(item.left_tfvl); yAxis[2].data.push(item.rght_tfvl); yAxis[3].data.push(nullChecker(item.srvc_lvl) === "" ? 0 : item.srvc_lvl); xAxis.push(item.stat_dt); }) totDataSource = [{ go_tfvl : totGo, left_tfvl : totLeft, rght_tfvl : totRght, tot_tfvl : totTot, }]; } else { totDataSource = []; } let pieYAxis = [ {y:totGo}, {y:totLeft}, {y:totTot}, ] _list.option('dataSource', jsonData); _totList.option('dataSource', totDataSource); _multiChart.update({ xAxis : { categories : xAxis, }, series : [ { data : yAxis[0].data }, { data : yAxis[1].data }, { data : yAxis[2].data }, { data : yAxis[3].data }, ] }); _pieChart.update({ series : [ { data : pieYAxis }, ] }); selResultMsg(jsonData); } function getSearchValues(unitVal){ const display = $('.strt-time-box').css('diplay'); let dateColumns = [strtDt, strtTime, endDt, endTime]; if (display === "none") { dateColumns = [strtDt, endDt]; } for (let dateColumn of dateColumns) { if (dateColumn.isValidation()) { alertWarning('형식에 맞게 입력해주세요. [ ' + dateColumn.label + ' ]', null, dateColumn); return []; } else if (dateColumn.isNull()) { alertWarning('조회기간을 입력해주세요. [ ' + dateColumn.label + ' ]', null, dateColumn); return []; } } let FROM_DT; let TO_DT; let format; switch (unitVal) { case '15m': case '30m': FROM_DT = concateVal(strtDt, 8, strtTime, 4) + '00'; TO_DT = concateVal(endDt, 8, endTime, 4) + '59'; break; case 'hh': FROM_DT = concateVal(strtDt, 8, strtTime, 2) + '0000'; TO_DT = concateVal(endDt, 8, endTime, 2) + '5959'; break; case 'dd': FROM_DT = strtDt.getSendDateValue().substring(0, 8) + '000000'; TO_DT = endDt.getSendDateValue().substring(0, 8) + '235959'; break; case 'mn': FROM_DT = strtDt.getSendDateValue().substring(0, 6) + '01000000';; TO_DT = endDt.getSendDateValue().substring(0, 6) + '31235959'; break; } if (FROM_DT > TO_DT) { alertWarning('검색 시작 기간 보다 검색 종료 기간이 큽니다.', null, endDt); return []; } return [FROM_DT, TO_DT]; } function concateVal(dt, dtNum, time, timeNum){ return dt.getSendDateValue().substring(0,dtNum) + time.getSendTimeValue().substring(0, timeNum); } function timeFommater(data, unitVal){ let str = ""; str += data.substring(0, 4); str += "-"; str += data.substring(4, 6); switch (unitVal) { case '15m': str += "-"; str += data.substring(6, 8); str += " "; str += data.substring(8, 10); str += ":"; str += data.substring(10, 12); break; case '30m': str += "-"; str += data.substring(6, 8); str += " "; str += data.substring(8, 10); str += ":"; str += data.substring(10, 12); break; case 'hh': str += "-"; str += data.substring(6, 8); str += " "; str += data.substring(8, 10); str += "시"; break; case 'dd': str += "-"; str += data.substring(6, 8); break; case 'mn': break; } return str; }