loads.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. Partials.Loads = function (params) {
  2. var tabs = [{ text: "냉방" }, { text: "난방" }];
  3. var selectedTab = ko.observable(0);
  4. var dateBoxValue = ko.observable(new Date((new Date).getTime() + (24 * 60 * 60 * 1000)));
  5. var initialized = false;
  6. var dataSource;
  7. var chartDataSource = ko.observable();
  8. function createDaily() {
  9. return new DevExpress.data.DataSource({
  10. store: Partials.odata.LoadsHourly,
  11. paginate: false,
  12. select: ['Year', 'Month', 'Day', 'Hour', 'Prediction', 'Measurement', 'Temperature'],
  13. map: function (item) {
  14. return item;
  15. },
  16. filter: [
  17. ["SiteId", "=", 1],
  18. ["BuildingId", "=", 1],
  19. ["ServiceTypeId", "=", selectedTab() + 1],
  20. ["Year", "=", dateBoxValue().getFullYear()],
  21. ["Month", "=", dateBoxValue().getMonth() + 1],
  22. ["Day", "=", dateBoxValue().getDate()],
  23. ]
  24. });
  25. }
  26. function load(result) {
  27. chartDataSource(result);
  28. viewModel.summary.load(result);
  29. $("#graphContainer").dxChart("instance").option({
  30. dataSource: chartDataSource,
  31. commonSeriesSettings: {
  32. argumentField: "Hour",
  33. type: "bar",
  34. hoverMode: "allArgumentPoints",
  35. selectionMode: "allArgumentPoints",
  36. },
  37. argumentAxis: {
  38. label: {
  39. customizeText: function () {
  40. return this.value + '시';
  41. }
  42. }
  43. },
  44. valueAxis: [
  45. {
  46. name: 'valueAxis',
  47. label: {
  48. format: 'fixedPoint millions',
  49. customizeText: function () {
  50. return this.valueText + ' cal';
  51. }
  52. }
  53. },
  54. {
  55. name: 'tempAxis',
  56. position: 'right',
  57. label: {
  58. customizeText: function () {
  59. return this.value + ' ℃';
  60. },
  61. },
  62. maxValueMargin: 0.1,
  63. minValueMargin: 0.1,
  64. min: -10,
  65. max: 30
  66. }
  67. ],
  68. series: [
  69. { name: "예측", color: "#70cbed", valueField: "Prediction" },
  70. { name: "실측", color: "#b3d199", valueField: "Measurement" },
  71. { name: "온도", type: "spline", color: "#9dD5ad", valueField: "Temperature", axis: 'tempAxis' },
  72. ],
  73. legend: {
  74. verticalAlignment: "top",
  75. horizontalAlignment: "right",
  76. position: "inside",
  77. border: { visible: true }
  78. },
  79. onPointClick: function (e) {
  80. e.target.select();
  81. },
  82. tooltip: {
  83. enabled: true,
  84. location: "edge",
  85. format: 'fixedPoint',
  86. customizeTooltip: function (point) {
  87. return point.seriesName + " : " + point.valueText;
  88. }
  89. }
  90. });
  91. }
  92. dateBoxValue.subscribe(function (e) {
  93. dataSource = createDaily();
  94. handleViewShown();
  95. });
  96. selectedTab.subscribe(function (e) {
  97. switch (selectedTab()) {
  98. case 0:
  99. dataSource = createDaily();
  100. break;
  101. case 1:
  102. dataSource = createDaily();
  103. break;
  104. }
  105. handleViewShown();
  106. });
  107. var handleViewShown = function () {
  108. if (initialized == false) {
  109. dataSource = createDaily();
  110. initialized = true;
  111. }
  112. dataSource.load().done(function (result) {
  113. load(result);
  114. });
  115. };
  116. var dataViewPopup = {
  117. width: 700,
  118. height: 'auto',
  119. showTitle: true,
  120. title: ko.computed({
  121. read: function () {
  122. return moment(dateBoxValue()).format("YYYY년 MM월 D일");
  123. }
  124. }),
  125. visible: ko.observable(false),
  126. dragEnabled: false,
  127. closeOnOutsideClick: false,
  128. show: function () {
  129. dataViewPopup.visible(true);
  130. },
  131. shownAction: function () {
  132. var dataGrid = $("#dataGrid").dxDataGrid("instance");
  133. dataGrid.option({
  134. "export": {
  135. enabled: true,
  136. fileName: "LoadsHourly"
  137. },
  138. columns: [
  139. { dataField: 'Hour', caption: '시간', width: '10%', },
  140. { dataField: 'Temperature', caption: '온도', format: 'fixedPoint', precision: 1, },
  141. { dataField: 'Prediction', caption: '예측', format: 'fixedPoint', alignment: 'right' },
  142. { dataField: 'Measurement', caption: '실측', format: 'fixedPoint', alignment: 'right' }]
  143. });
  144. }
  145. };
  146. var predictPopup = {
  147. width: 800,
  148. height: 'auto',
  149. showTitle: true,
  150. weatherDataSource: ko.observable(),
  151. zoneDataSource: ko.observable(),
  152. buttons: [
  153. {
  154. toolbar: 'bottom', location: 'after', widget: 'button', options: {
  155. text: '예측', clickAction: function () {
  156. //var tomorrow = new Date();
  157. //tomorrow.setDate(tomorrow.getDate() + 1);
  158. Partials.api.post('ExecuteLoadsHourly', { SiteId: 1, CreatedDate: dateBoxValue(), serviceTypeId: selectedTab() + 1}).done(function (result) {
  159. viewModel.predictPopup.visible(false);
  160. viewModel.viewShown();
  161. });
  162. /*
  163. if (moment(tomorrow).format('YYYYMMDD') === moment(dateBoxValue()).format('YYYYMMDD')) {
  164. Partials.api.post('ExecuteLoadsHourly', { SiteId: 1, CreatedDate: dateBoxValue() }).done(function (result) {
  165. viewModel.predictPopup.visible(false);
  166. viewModel.viewShown();
  167. });
  168. } else {
  169. DevExpress.ui.dialog.alert('익일 부하예측만 가능합니다.', '알림');
  170. }
  171. */
  172. }
  173. }
  174. }
  175. ],
  176. title: ko.computed({
  177. read: function(){
  178. return moment(dateBoxValue()).format("YYYY년 MM월 D일");
  179. }
  180. }),
  181. visible: ko.observable(false),
  182. dragEnabled: false,
  183. closeOnOutsideClick: false,
  184. show: function () {
  185. predictPopup.visible(true);
  186. },
  187. showingAction: function() {
  188. predictPopup.weatherDataSource = new DevExpress.data.DataSource({
  189. store: Partials.db.BemsWeatherHourly,
  190. paginate: false,
  191. map: function (item) {
  192. return item;
  193. },
  194. filter: [
  195. ["SiteId", "=", 1],
  196. ["year(CreatedDate)", "=", dateBoxValue().getFullYear()],
  197. ["month(CreatedDate)", "=", dateBoxValue().getMonth() + 1],
  198. ["day(CreatedDate)", "=", dateBoxValue().getDate()],
  199. ]
  200. });
  201. predictPopup.zoneDataSource = new DevExpress.data.DataSource({
  202. store: Partials.db.BemsZoneActivateDaily,
  203. expand: ['BemsZoneActivate', 'BemsZoneActivate/BemsZone'],
  204. paginate: false,
  205. map: function (item) {
  206. return item;
  207. },
  208. filter: [
  209. ["SiteId", "=", 1],
  210. ["BuildingId", "=", 1],
  211. ["ServiceTypeId", "=", selectedTab() + 1],
  212. ["year(CreatedDate)", "=", dateBoxValue().getFullYear()],
  213. ["month(CreatedDate)", "=", dateBoxValue().getMonth() + 1],
  214. ["day(CreatedDate)", "=", dateBoxValue().getDate()],
  215. ]
  216. });
  217. },
  218. shownAction: function () {
  219. predictPopup.weatherDataSource.load().done(function (result) {
  220. var dataGrid = $("#weatherGrid").dxDataGrid("instance");
  221. dataGrid.option({
  222. dataSource: result,
  223. editing: { editMode: 'batch', editEnabled: true, },
  224. rowUpdating: function (rowInfo) {
  225. var key = new Partials.BemsWeatherHourlyViewModel(rowInfo.key);
  226. Partials.db.BemsWeatherHourly.update(key.toJS(), rowInfo.newData);
  227. },
  228. columns: [
  229. {
  230. dataField: 'CreatedDate', caption: '시간', width: '10%', alignment: 'right', allowEditing: false, customizeText: function (cellInfo) {
  231. return moment(cellInfo.value).format("H");
  232. }
  233. },
  234. { dataField: 'Temperature', caption: '온도(℃)', format: 'fixedPoint', precision: 1, },
  235. { dataField: 'Humidity', caption: '습도(%)', format: 'fixedPoint', precision: 0, },
  236. { dataField: 'Wind', caption: '풍속(m/s)', format: 'fixedPoint', precision: 2, },
  237. { dataField: 'Rainfall', caption: '강수량(mm)', format: 'fixedPoint', precision: 2, },
  238. ]
  239. });
  240. });
  241. predictPopup.zoneDataSource.load().done(function (result) {
  242. var dataGrid = $("#zoneGrid").dxDataGrid("instance");
  243. dataGrid.option({
  244. dataSource: result,
  245. editing: { editMode: 'batch', editEnabled: true, },
  246. columnFixing: {
  247. enabled: true
  248. },
  249. rowUpdating: function (rowInfo) {
  250. Partials.db.BemsZoneActivateDaily.update(rowInfo.key, rowInfo.newData);
  251. },
  252. columns: [
  253. { dataField: 'BemsZoneActivate.BemsZone.Name', caption: '시설명', fixed: true, width: 150, allowEditing: false },
  254. { dataField: 'BemsZoneActivate.Loads', caption: '부하(cal)', fixed: true, format: 'fixedPoint', width: 110, alignment: 'right', allowEditing: false },
  255. { dataField: 'BemsZoneActivate.RateOfWork', caption: '가동율(%)', fixed: true, format: 'fixedPoint', precision: 2, width: 100, alignment: 'right', allowEditing: false },
  256. { dataField: 'H00', caption: '00시', width: 50, alignment: 'center', dataType: 'boolean', },
  257. { dataField: 'H01', caption: '01시', width: 50, alignment: 'center', dataType: 'boolean', },
  258. { dataField: 'H02', caption: '02시', width: 50, alignment: 'center', dataType: 'boolean', },
  259. { dataField: 'H03', caption: '03시', width: 50, alignment: 'center', dataType: 'boolean', },
  260. { dataField: 'H04', caption: '04시', width: 50, alignment: 'center', dataType: 'boolean', },
  261. { dataField: 'H05', caption: '05시', width: 50, alignment: 'center', dataType: 'boolean', },
  262. { dataField: 'H06', caption: '06시', width: 50, alignment: 'center', dataType: 'boolean', },
  263. { dataField: 'H07', caption: '07시', width: 50, alignment: 'center', dataType: 'boolean', },
  264. { dataField: 'H08', caption: '08시', width: 50, alignment: 'center', dataType: 'boolean', },
  265. { dataField: 'H09', caption: '09시', width: 50, alignment: 'center', dataType: 'boolean', },
  266. { dataField: 'H10', caption: '10시', width: 50, alignment: 'center', dataType: 'boolean', },
  267. { dataField: 'H11', caption: '11시', width: 50, alignment: 'center', dataType: 'boolean', },
  268. { dataField: 'H12', caption: '12시', width: 50, alignment: 'center', dataType: 'boolean', },
  269. { dataField: 'H13', caption: '13시', width: 50, alignment: 'center', dataType: 'boolean', },
  270. { dataField: 'H14', caption: '14시', width: 50, alignment: 'center', dataType: 'boolean', },
  271. { dataField: 'H15', caption: '15시', width: 50, alignment: 'center', dataType: 'boolean', },
  272. { dataField: 'H16', caption: '16시', width: 50, alignment: 'center', dataType: 'boolean', },
  273. { dataField: 'H17', caption: '17시', width: 50, alignment: 'center', dataType: 'boolean', },
  274. { dataField: 'H18', caption: '18시', width: 50, alignment: 'center', dataType: 'boolean', },
  275. { dataField: 'H19', caption: '19시', width: 50, alignment: 'center', dataType: 'boolean', },
  276. { dataField: 'H20', caption: '20시', width: 50, alignment: 'center', dataType: 'boolean', },
  277. { dataField: 'H21', caption: '21시', width: 50, alignment: 'center', dataType: 'boolean', },
  278. { dataField: 'H22', caption: '22시', width: 50, alignment: 'center', dataType: 'boolean', },
  279. { dataField: 'H23', caption: '23시', width: 50, alignment: 'center', dataType: 'boolean', },
  280. ]
  281. });
  282. });
  283. }
  284. };
  285. var viewModel = {
  286. tabs: tabs,
  287. selectedTab: selectedTab,
  288. dateBoxValue: dateBoxValue,
  289. dataSource: chartDataSource,
  290. dataViewPopup: dataViewPopup,
  291. predictPopup: predictPopup,
  292. viewShown: handleViewShown,
  293. dataViewOption: dataViewPopup,
  294. summary: {
  295. load: function (data) {
  296. viewModel.summary.temperature.max(data.reduce(function (p, c) { return p.value > c.Temperature ? p : { title: c.Hour + '시', value: c.Temperature } }));
  297. viewModel.summary.temperature.min(data.reduce(function (p, c) { return p.value <= c.Temperature ? p : { title: c.Hour + '시', value: c.Temperature } }));
  298. viewModel.summary.pred.max(data.reduce(function (p, c) { return p.value > c.Prediction ? p : { title: c.Hour + '시', value: c.Prediction } }));
  299. viewModel.summary.pred.min(data.reduce(function (p, c) { return p.value <= c.Prediction ? p : { title: c.Hour + '시', value: c.Prediction } }));
  300. var date = new Date(dateBoxValue());
  301. date.setDate(date.getDate() - 1);
  302. previousDataSource = new DevExpress.data.DataSource({
  303. store: Partials.odata.LoadsHourly,
  304. paginate: false,
  305. select: ['Year', 'Month', 'Day', 'Hour', 'Prediction', 'Measurement', 'Temperature'],
  306. map: function (item) {
  307. return item;
  308. },
  309. filter: [
  310. ["SiteId", "=", 1],
  311. ["BuildingId", "=", 1],
  312. ["ServiceTypeId", "=", selectedTab() + 1],
  313. ["Year", "=", date.getFullYear()],
  314. ["Month", "=", date.getMonth() + 1],
  315. ["Day", "=", date.getDate()],
  316. ]
  317. });
  318. previousDataSource.load().done(function (prev) {
  319. viewModel.summary.previous.max(prev.reduce(function (p, c) { return p.value > c.Prediction ? p : { title: c.Hour + '시', value: c.Prediction } }));
  320. viewModel.summary.previous.min(prev.reduce(function (p, c) { return p.value <= c.Prediction ? p : { title: c.Hour + '시', value: c.Prediction } }));
  321. });
  322. },
  323. temperature: {
  324. min: ko.observable({ title: '', value: '' }),
  325. max: ko.observable({ title: '', value: '' }),
  326. },
  327. pred: {
  328. min: ko.observable({ title: '', value: '' }),
  329. max: ko.observable({ title: '', value: '' }),
  330. },
  331. previous: {
  332. min: ko.observable({ title: '', value: '' }),
  333. max: ko.observable({ title: '', value: '' }),
  334. }
  335. },
  336. onPrevious: function (e) {
  337. var date = new Date(dateBoxValue());
  338. date.setDate(date.getDate() - 1);
  339. dateBoxValue(date);
  340. },
  341. onNext: function (e) {
  342. var date = new Date(dateBoxValue());
  343. date.setDate(date.getDate() + 1)
  344. dateBoxValue(date);
  345. }
  346. };
  347. return viewModel;
  348. };