Partials.Loads = function (params) { var tabs = [{ text: "냉방" }, { text: "난방" }]; var selectedTab = ko.observable(0); var dateBoxValue = ko.observable(new Date((new Date).getTime() + (24 * 60 * 60 * 1000))); var initialized = false; var dataSource; var chartDataSource = ko.observable(); function createDaily() { return new DevExpress.data.DataSource({ store: Partials.odata.LoadsHourly, paginate: false, select: ['Year', 'Month', 'Day', 'Hour', 'Prediction', 'Measurement', 'Temperature'], map: function (item) { return item; }, filter: [ ["SiteId", "=", 1], ["BuildingId", "=", 1], ["ServiceTypeId", "=", selectedTab() + 1], ["Year", "=", dateBoxValue().getFullYear()], ["Month", "=", dateBoxValue().getMonth() + 1], ["Day", "=", dateBoxValue().getDate()], ] }); } function load(result) { chartDataSource(result); viewModel.summary.load(result); $("#graphContainer").dxChart("instance").option({ dataSource: chartDataSource, commonSeriesSettings: { argumentField: "Hour", type: "bar", hoverMode: "allArgumentPoints", selectionMode: "allArgumentPoints", }, argumentAxis: { label: { customizeText: function () { return this.value + '시'; } } }, valueAxis: [ { name: 'valueAxis', label: { format: 'fixedPoint millions', customizeText: function () { return this.valueText + ' cal'; } } }, { name: 'tempAxis', position: 'right', label: { customizeText: function () { return this.value + ' ℃'; }, }, maxValueMargin: 0.1, minValueMargin: 0.1, min: -10, max: 30 } ], series: [ { name: "예측", color: "#70cbed", valueField: "Prediction" }, { name: "실측", color: "#b3d199", valueField: "Measurement" }, { name: "온도", type: "spline", color: "#9dD5ad", valueField: "Temperature", axis: 'tempAxis' }, ], legend: { verticalAlignment: "top", horizontalAlignment: "right", position: "inside", border: { visible: true } }, onPointClick: function (e) { e.target.select(); }, tooltip: { enabled: true, location: "edge", format: 'fixedPoint', customizeTooltip: function (point) { return point.seriesName + " : " + point.valueText; } } }); } dateBoxValue.subscribe(function (e) { dataSource = createDaily(); handleViewShown(); }); selectedTab.subscribe(function (e) { switch (selectedTab()) { case 0: dataSource = createDaily(); break; case 1: dataSource = createDaily(); break; } handleViewShown(); }); var handleViewShown = function () { if (initialized == false) { dataSource = createDaily(); initialized = true; } dataSource.load().done(function (result) { load(result); }); }; var dataViewPopup = { width: 700, height: 'auto', showTitle: true, title: ko.computed({ read: function () { return moment(dateBoxValue()).format("YYYY년 MM월 D일"); } }), visible: ko.observable(false), dragEnabled: false, closeOnOutsideClick: false, show: function () { dataViewPopup.visible(true); }, shownAction: function () { var dataGrid = $("#dataGrid").dxDataGrid("instance"); dataGrid.option({ "export": { enabled: true, fileName: "LoadsHourly" }, columns: [ { dataField: 'Hour', caption: '시간', width: '10%', }, { dataField: 'Temperature', caption: '온도', format: 'fixedPoint', precision: 1, }, { dataField: 'Prediction', caption: '예측', format: 'fixedPoint', alignment: 'right' }, { dataField: 'Measurement', caption: '실측', format: 'fixedPoint', alignment: 'right' }] }); } }; var predictPopup = { width: 800, height: 'auto', showTitle: true, weatherDataSource: ko.observable(), zoneDataSource: ko.observable(), buttons: [ { toolbar: 'bottom', location: 'after', widget: 'button', options: { text: '예측', clickAction: function () { //var tomorrow = new Date(); //tomorrow.setDate(tomorrow.getDate() + 1); Partials.api.post('ExecuteLoadsHourly', { SiteId: 1, CreatedDate: dateBoxValue(), serviceTypeId: selectedTab() + 1}).done(function (result) { viewModel.predictPopup.visible(false); viewModel.viewShown(); }); /* if (moment(tomorrow).format('YYYYMMDD') === moment(dateBoxValue()).format('YYYYMMDD')) { Partials.api.post('ExecuteLoadsHourly', { SiteId: 1, CreatedDate: dateBoxValue() }).done(function (result) { viewModel.predictPopup.visible(false); viewModel.viewShown(); }); } else { DevExpress.ui.dialog.alert('익일 부하예측만 가능합니다.', '알림'); } */ } } } ], title: ko.computed({ read: function(){ return moment(dateBoxValue()).format("YYYY년 MM월 D일"); } }), visible: ko.observable(false), dragEnabled: false, closeOnOutsideClick: false, show: function () { predictPopup.visible(true); }, showingAction: function() { predictPopup.weatherDataSource = new DevExpress.data.DataSource({ store: Partials.db.BemsWeatherHourly, paginate: false, map: function (item) { return item; }, filter: [ ["SiteId", "=", 1], ["year(CreatedDate)", "=", dateBoxValue().getFullYear()], ["month(CreatedDate)", "=", dateBoxValue().getMonth() + 1], ["day(CreatedDate)", "=", dateBoxValue().getDate()], ] }); predictPopup.zoneDataSource = new DevExpress.data.DataSource({ store: Partials.db.BemsZoneActivateDaily, expand: ['BemsZoneActivate', 'BemsZoneActivate/BemsZone'], paginate: false, map: function (item) { return item; }, filter: [ ["SiteId", "=", 1], ["BuildingId", "=", 1], ["ServiceTypeId", "=", selectedTab() + 1], ["year(CreatedDate)", "=", dateBoxValue().getFullYear()], ["month(CreatedDate)", "=", dateBoxValue().getMonth() + 1], ["day(CreatedDate)", "=", dateBoxValue().getDate()], ] }); }, shownAction: function () { predictPopup.weatherDataSource.load().done(function (result) { var dataGrid = $("#weatherGrid").dxDataGrid("instance"); dataGrid.option({ dataSource: result, editing: { editMode: 'batch', editEnabled: true, }, rowUpdating: function (rowInfo) { var key = new Partials.BemsWeatherHourlyViewModel(rowInfo.key); Partials.db.BemsWeatherHourly.update(key.toJS(), rowInfo.newData); }, columns: [ { dataField: 'CreatedDate', caption: '시간', width: '10%', alignment: 'right', allowEditing: false, customizeText: function (cellInfo) { return moment(cellInfo.value).format("H"); } }, { dataField: 'Temperature', caption: '온도(℃)', format: 'fixedPoint', precision: 1, }, { dataField: 'Humidity', caption: '습도(%)', format: 'fixedPoint', precision: 0, }, { dataField: 'Wind', caption: '풍속(m/s)', format: 'fixedPoint', precision: 2, }, { dataField: 'Rainfall', caption: '강수량(mm)', format: 'fixedPoint', precision: 2, }, ] }); }); predictPopup.zoneDataSource.load().done(function (result) { var dataGrid = $("#zoneGrid").dxDataGrid("instance"); dataGrid.option({ dataSource: result, editing: { editMode: 'batch', editEnabled: true, }, columnFixing: { enabled: true }, rowUpdating: function (rowInfo) { Partials.db.BemsZoneActivateDaily.update(rowInfo.key, rowInfo.newData); }, columns: [ { dataField: 'BemsZoneActivate.BemsZone.Name', caption: '시설명', fixed: true, width: 150, allowEditing: false }, { dataField: 'BemsZoneActivate.Loads', caption: '부하(cal)', fixed: true, format: 'fixedPoint', width: 110, alignment: 'right', allowEditing: false }, { dataField: 'BemsZoneActivate.RateOfWork', caption: '가동율(%)', fixed: true, format: 'fixedPoint', precision: 2, width: 100, alignment: 'right', allowEditing: false }, { dataField: 'H00', caption: '00시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H01', caption: '01시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H02', caption: '02시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H03', caption: '03시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H04', caption: '04시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H05', caption: '05시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H06', caption: '06시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H07', caption: '07시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H08', caption: '08시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H09', caption: '09시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H10', caption: '10시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H11', caption: '11시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H12', caption: '12시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H13', caption: '13시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H14', caption: '14시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H15', caption: '15시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H16', caption: '16시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H17', caption: '17시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H18', caption: '18시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H19', caption: '19시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H20', caption: '20시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H21', caption: '21시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H22', caption: '22시', width: 50, alignment: 'center', dataType: 'boolean', }, { dataField: 'H23', caption: '23시', width: 50, alignment: 'center', dataType: 'boolean', }, ] }); }); } }; var viewModel = { tabs: tabs, selectedTab: selectedTab, dateBoxValue: dateBoxValue, dataSource: chartDataSource, dataViewPopup: dataViewPopup, predictPopup: predictPopup, viewShown: handleViewShown, dataViewOption: dataViewPopup, summary: { load: function (data) { viewModel.summary.temperature.max(data.reduce(function (p, c) { return p.value > c.Temperature ? p : { title: c.Hour + '시', value: c.Temperature } })); viewModel.summary.temperature.min(data.reduce(function (p, c) { return p.value <= c.Temperature ? p : { title: c.Hour + '시', value: c.Temperature } })); viewModel.summary.pred.max(data.reduce(function (p, c) { return p.value > c.Prediction ? p : { title: c.Hour + '시', value: c.Prediction } })); viewModel.summary.pred.min(data.reduce(function (p, c) { return p.value <= c.Prediction ? p : { title: c.Hour + '시', value: c.Prediction } })); var date = new Date(dateBoxValue()); date.setDate(date.getDate() - 1); previousDataSource = new DevExpress.data.DataSource({ store: Partials.odata.LoadsHourly, paginate: false, select: ['Year', 'Month', 'Day', 'Hour', 'Prediction', 'Measurement', 'Temperature'], map: function (item) { return item; }, filter: [ ["SiteId", "=", 1], ["BuildingId", "=", 1], ["ServiceTypeId", "=", selectedTab() + 1], ["Year", "=", date.getFullYear()], ["Month", "=", date.getMonth() + 1], ["Day", "=", date.getDate()], ] }); previousDataSource.load().done(function (prev) { viewModel.summary.previous.max(prev.reduce(function (p, c) { return p.value > c.Prediction ? p : { title: c.Hour + '시', value: c.Prediction } })); viewModel.summary.previous.min(prev.reduce(function (p, c) { return p.value <= c.Prediction ? p : { title: c.Hour + '시', value: c.Prediction } })); }); }, temperature: { min: ko.observable({ title: '', value: '' }), max: ko.observable({ title: '', value: '' }), }, pred: { min: ko.observable({ title: '', value: '' }), max: ko.observable({ title: '', value: '' }), }, previous: { min: ko.observable({ title: '', value: '' }), max: ko.observable({ title: '', value: '' }), } }, onPrevious: function (e) { var date = new Date(dateBoxValue()); date.setDate(date.getDate() - 1); dateBoxValue(date); }, onNext: function (e) { var date = new Date(dateBoxValue()); date.setDate(date.getDate() + 1) dateBoxValue(date); } }; return viewModel; };