EnergyUsageService.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. using Microsoft.Extensions.Logging;
  2. using FMSAdmin.Data;
  3. using System.Linq;
  4. using FMSAdmin.Helpers;
  5. using FMSAdmin.Entities;
  6. using Microsoft.EntityFrameworkCore;
  7. using System;
  8. using System.Collections.Generic;
  9. using FMSAdmin.Models.Formula;
  10. using FMSAdmin.Helpers.Formula;
  11. using System.Collections;
  12. using System.Text.RegularExpressions;
  13. using FMSAdmin.Models;
  14. namespace FMSAdmin.Services {
  15. public class EnergyUsageService {
  16. private readonly ILogger<EnergyUsageService> _logger;
  17. private readonly FMSContext _context;
  18. public EnergyUsageService(
  19. ILogger<EnergyUsageService> logger,
  20. FMSContext context
  21. ) {
  22. _logger = logger;
  23. _context = context;
  24. }
  25. public IList<CalculationResult> GetEnergyDailyList(int siteId, EnergyInterval interval, EnergyType type, DateTime startDate, DateTime endDate) {
  26. var dic = GetEnergyDailyDic(siteId, interval, type, startDate, endDate);
  27. return dic.Values.ToList();
  28. }
  29. public IDictionary<string, CalculationResult> GetEnergyDailyDic(int siteId, EnergyInterval interval, EnergyType type, DateTime startDate, DateTime endDate) {
  30. FormulaTableManager tableManager = new FormulaTableManager(_context);
  31. var formulaId = 1;
  32. int facilityTypeId = 100;
  33. int facilityCode = 1;
  34. if (type == EnergyType.전기) {
  35. facilityTypeId = 100;
  36. facilityCode = 1;
  37. } else if (type == EnergyType.가스) {
  38. facilityTypeId = 101;
  39. facilityCode = 2;
  40. } else if (type == EnergyType.수도) {
  41. facilityTypeId = 102;
  42. facilityCode = 3;
  43. } else if (type == EnergyType.등유) {
  44. facilityTypeId = 104;
  45. facilityCode = 4;
  46. } else if (type == EnergyType.LPG) {
  47. facilityTypeId = 105;
  48. facilityCode = 5;
  49. } else if (type == EnergyType.중온수) {
  50. facilityTypeId = 106;
  51. facilityCode = 6;
  52. }
  53. var timeInterval = interval == EnergyInterval.일 ?
  54. TimeInterval.Day
  55. : interval == EnergyInterval.월 ?
  56. TimeInterval.Month
  57. : TimeInterval.Day;
  58. IDictionary<string, CalculationResult> list = new Dictionary<string, CalculationResult>();
  59. var queryFormula = from f in _context.BemsFormula
  60. where f.SiteId == siteId && f.FacilityTypeId == facilityTypeId &&
  61. (facilityTypeId >= 100 || f.FacilityCode == facilityCode) && f.FormulaId == formulaId
  62. select f;
  63. var formula = queryFormula.FirstOrDefault();
  64. if (formula == null) {
  65. throw new Exception("수식정보가 없습니다.");
  66. }
  67. ArrayList parameters = new ArrayList();
  68. MathCalculator calculator = new MathCalculator();
  69. if (false == calculator.Compile(formula.Formula)) {
  70. throw new Exception("Failed to compile formula: " + formula.Formula);
  71. }
  72. var regexParameter = new Regex(@"\b[A-Z]\b", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase);
  73. var match = regexParameter.Match(formula.Formula);
  74. if (match.Success) {
  75. var queryParameters = from x in _context.BemsFormulaParameter
  76. where x.SiteId == siteId && x.FacilityTypeId == facilityTypeId &&
  77. (facilityTypeId >= 100 || x.FacilityCode == facilityCode) && x.FormulaId == formulaId
  78. select x;
  79. if (queryParameters == null || queryParameters.Any() == false) {
  80. throw new Exception(string.Format("Not Found Formula Parameters: {0},{1},{2},{3}", siteId, facilityTypeId, facilityCode, formulaId));
  81. }
  82. List<MathParameterValue> parametersForArray = new List<MathParameterValue>();
  83. foreach (var p in queryParameters.ToList()) {
  84. char parameter = p.ParameterId[0];
  85. var pValue = new MathParameterValue {
  86. Variable = (MathCalculator.Parameter)(parameter - 'A'),
  87. Value = 0,
  88. };
  89. parametersForArray.Add(pValue);
  90. var values = _CreateCalculationValues(startDate, endDate, timeInterval);
  91. var pointvalues = timeInterval == TimeInterval.Day ?
  92. GetMonitoringPointHistoryDaily(siteId, p.ParameterFacilityCode,
  93. p.ParameterPropertyId, startDate, endDate)
  94. : timeInterval == TimeInterval.Month ?
  95. GetMonitoringPointHistoryMonthly(siteId, p.ParameterFacilityCode,
  96. p.ParameterPropertyId, startDate, endDate)
  97. : null;
  98. if (pointvalues == null)
  99. continue;
  100. CalculationValue pp = null;
  101. CalculationValue v = null;
  102. for (var i = 0; i < values.Length; i++) {
  103. v = values[i];
  104. for (var j = 0; j < pointvalues.Length; j++) {
  105. pp = pointvalues[j];
  106. if (pp.DateTime == v.DateTime) {
  107. v.Value += pp.Value;
  108. }
  109. }
  110. }
  111. parameters.Add(new CalculationParameter {
  112. ParameterValue = pValue,
  113. Values = values
  114. });
  115. }
  116. calculator.SetParameter(parametersForArray.ToArray());
  117. }
  118. {
  119. var functions = calculator.GetFunctions();
  120. if (functions.Any()) {
  121. foreach (var f in functions) {
  122. var tableValues = tableManager.GetTableValues(f.Function.FunctionName);
  123. if (tableValues == null) {
  124. throw new Exception("Not Found Function.");
  125. }
  126. f.Function.FunctionDelegate = (x) => {
  127. var index = Array.BinarySearch(tableValues, new FormulaTableManager.TableComparerValue { XValue = (double)x });
  128. if (index < 0) {
  129. index = ~index;
  130. if (index == 0) {
  131. return Math.Round((decimal)tableValues[0].YValue, 2);
  132. } else if (index == tableValues.Length) {
  133. return Math.Round((decimal)tableValues[tableValues.Length - 1].YValue, 2);
  134. }
  135. }
  136. return Math.Round((decimal)tableValues[index].YValue, 2);
  137. };
  138. }
  139. }
  140. }
  141. DateTime dateTime = DateTime.Now;
  142. if (parameters.Count > 0) {
  143. var ps = parameters.Cast<CalculationParameter>().ToArray();
  144. ParameterBox parameterBox = new ParameterBox(ps);
  145. while (parameterBox.Sync()) {
  146. var value = calculator.Calculate();
  147. if (value != null) {
  148. var date = parameterBox.DateTime.ToString("yyyy-MM-dd");
  149. list.Add(date, new CalculationResult {
  150. DateTime = parameterBox.DateTime,
  151. ShortDateTime = date,
  152. Value = value < 0 ? 0 : Math.Round((double)value, 2)
  153. });
  154. }
  155. if (parameterBox.NextStage() == false) {
  156. break;
  157. }
  158. }
  159. }
  160. return list;
  161. }
  162. public CalculationValue[] GetMonitoringPointHistoryDaily(int siteId, int facilityCode, int propertyId, DateTime startDate, DateTime endDate) {
  163. var query = _context.BemsMonitoringPointHistoryDaily.Where(x =>
  164. x.SiteId == siteId &&
  165. x.FacilityCode == facilityCode &&
  166. x.PropertyId == propertyId &&
  167. startDate <= x.CreatedDateTime && x.CreatedDateTime <= endDate);
  168. if (query.Any() == false) {
  169. return null;
  170. }
  171. return query.Select(x => new CalculationValue {
  172. DateTime = x.CreatedDateTime,
  173. Value = x.DailyValue
  174. }).ToArray();
  175. }
  176. public CalculationValue[] GetMonitoringPointHistoryMonthly(int siteId, int facilityCode, int propertyId, DateTime startDate, DateTime endDate) {
  177. var groupQuery = from data in _context.BemsMonitoringPointHistoryDaily
  178. where data.SiteId == siteId &&
  179. data.FacilityCode == facilityCode &&
  180. data.PropertyId == propertyId &&
  181. startDate <= data.CreatedDateTime && data.CreatedDateTime <= endDate
  182. group data by new { Year = data.CreatedDateTime.Year, Month = data.CreatedDateTime.Month } into g
  183. // select g;
  184. select new {
  185. Year = g.Key.Year,
  186. Month = g.Key.Month,
  187. SumDailyValue = g.Sum(x => x.DailyValue),
  188. AverageDailyValue = g.Average(x => x.DailyValue)
  189. };
  190. if (groupQuery == null || groupQuery.Any() == false) {
  191. return null;
  192. }
  193. //CalculationValue[] values = { };// = new CalculationValue[groupQuery.ToList().Count()];
  194. CalculationValue[] values = new CalculationValue[groupQuery.ToList().Count()];
  195. var i = 0;
  196. foreach (var g in groupQuery.ToList()) {
  197. double dValue = 0;
  198. if (_CheckPointValueType(siteId, facilityCode, propertyId) == 0) dValue = g.SumDailyValue;
  199. else if (_CheckPointValueType(siteId, facilityCode, propertyId) == 1) dValue = g.AverageDailyValue;
  200. else if (_CheckPointValueType(siteId, facilityCode, propertyId) == 2) {
  201. dValue = g.SumDailyValue;
  202. dValue = (dValue > 0) ? 1 : 0;
  203. }
  204. values[i] = new CalculationValue {
  205. DateTime = new DateTime(g.Year, g.Month, 1),
  206. //Value = g.Sum(x => x.CurrentValue)
  207. Value = dValue
  208. };
  209. i++;
  210. }
  211. return values;
  212. }
  213. private int _CheckPointValueType(int siteId, int facilityCode, int propertyId) {
  214. // return 0 -> 누적, 1 -> 평균, 2 -> On,Off
  215. var Query = from data in _context.BemsMonitoringPoint
  216. where data.SiteId == siteId &&
  217. data.FacilityCode == facilityCode &&
  218. data.PropertyId == propertyId
  219. select data;
  220. if (Query.FirstOrDefault().ValueType == 2) return 2;
  221. if (Query.FirstOrDefault().ValueType == 0 && Query.FirstOrDefault().FuelTypeId > 0) return 0;
  222. if (Query.FirstOrDefault().ValueType == 0 && Query.FirstOrDefault().FuelTypeId == 0) return 1;
  223. return 0;
  224. }
  225. private CalculationValue[] _CreateCalculationValues(DateTime startDate, DateTime endDate, TimeInterval timeIntervalType) {
  226. DateTime datetime = startDate;
  227. int count = _GetCountInTimeRange(startDate, endDate, timeIntervalType);
  228. CalculationValue[] values = new CalculationValue[count];
  229. for (var i = 0; i < values.Length; i++) {
  230. values[i] = new CalculationValue {
  231. DateTime = datetime,
  232. Value = 0
  233. };
  234. _NextTimeFromTimeInterval(ref datetime, timeIntervalType);
  235. }
  236. return values;
  237. }
  238. private int _GetCountInTimeRange(DateTime startDate, DateTime endDate, TimeInterval timeIntervalType) {
  239. TimeSpan ts = endDate - startDate;
  240. switch (timeIntervalType) {
  241. case TimeInterval.QuarterMin:
  242. return (int)ts.TotalMinutes / 15 + 1;
  243. case TimeInterval.Hour:
  244. return (int)ts.TotalHours + 1;
  245. case TimeInterval.Day:
  246. return (int)ts.TotalDays + 1;
  247. case TimeInterval.Month: {
  248. int count = 0;
  249. DateTime date = startDate;
  250. //while (date.Year <= endDate.Year && date.Month <= endDate.Month)
  251. while (date <= endDate) {
  252. count++;
  253. date = date.AddMonths(1);
  254. }
  255. return count;
  256. }
  257. default: // TimeInterval.Year:
  258. {
  259. int count = 0;
  260. DateTime date = startDate;
  261. while (date.Year <= endDate.Year) {
  262. count++;
  263. date = date.AddYears(1);
  264. }
  265. return count;
  266. }
  267. }
  268. }
  269. private void _NextTimeFromTimeInterval(ref DateTime datetime, TimeInterval timeIntervalType) {
  270. switch (timeIntervalType) {
  271. case TimeInterval.QuarterMin:
  272. datetime = datetime.AddMinutes(15);
  273. break;
  274. case TimeInterval.Hour:
  275. datetime = datetime.AddHours(1);
  276. break;
  277. case TimeInterval.Day:
  278. datetime = datetime.AddDays(1);
  279. break;
  280. case TimeInterval.Month:
  281. datetime = datetime.AddMonths(1);
  282. break;
  283. default: // TimeInterval.Year:
  284. datetime = datetime.AddYears(1);
  285. break;
  286. }
  287. }
  288. public IQueryable<BemsFuelType> GetFuelType() {
  289. var data = _context.BemsFuelType.Where(x => x.FuelTypeId != 0);
  290. return data;
  291. }
  292. }
  293. }