using Microsoft.Extensions.Logging; using FMSAdmin.Data; using System.Linq; using FMSAdmin.Helpers; using FMSAdmin.Entities; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using FMSAdmin.Models.Formula; using FMSAdmin.Helpers.Formula; using System.Collections; using System.Text.RegularExpressions; using FMSAdmin.Models; namespace FMSAdmin.Services { public class EnergyUsageService { private readonly ILogger _logger; private readonly FMSContext _context; public EnergyUsageService( ILogger logger, FMSContext context ) { _logger = logger; _context = context; } public IList GetEnergyDailyList(int siteId, EnergyInterval interval, EnergyType type, DateTime startDate, DateTime endDate) { var dic = GetEnergyDailyDic(siteId, interval, type, startDate, endDate); return dic.Values.ToList(); } public IDictionary GetEnergyDailyDic(int siteId, EnergyInterval interval, EnergyType type, DateTime startDate, DateTime endDate) { FormulaTableManager tableManager = new FormulaTableManager(_context); var formulaId = 1; int facilityTypeId = 100; int facilityCode = 1; if (type == EnergyType.전기) { facilityTypeId = 100; facilityCode = 1; } else if (type == EnergyType.가스) { facilityTypeId = 101; facilityCode = 2; } else if (type == EnergyType.수도) { facilityTypeId = 102; facilityCode = 3; } else if (type == EnergyType.등유) { facilityTypeId = 104; facilityCode = 4; } else if (type == EnergyType.LPG) { facilityTypeId = 105; facilityCode = 5; } else if (type == EnergyType.중온수) { facilityTypeId = 106; facilityCode = 6; } var timeInterval = interval == EnergyInterval.일 ? TimeInterval.Day : interval == EnergyInterval.월 ? TimeInterval.Month : TimeInterval.Day; IDictionary list = new Dictionary(); var queryFormula = from f in _context.BemsFormula where f.SiteId == siteId && f.FacilityTypeId == facilityTypeId && (facilityTypeId >= 100 || f.FacilityCode == facilityCode) && f.FormulaId == formulaId select f; var formula = queryFormula.FirstOrDefault(); if (formula == null) { throw new Exception("수식정보가 없습니다."); } ArrayList parameters = new ArrayList(); MathCalculator calculator = new MathCalculator(); if (false == calculator.Compile(formula.Formula)) { throw new Exception("Failed to compile formula: " + formula.Formula); } var regexParameter = new Regex(@"\b[A-Z]\b", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase); var match = regexParameter.Match(formula.Formula); if (match.Success) { var queryParameters = from x in _context.BemsFormulaParameter where x.SiteId == siteId && x.FacilityTypeId == facilityTypeId && (facilityTypeId >= 100 || x.FacilityCode == facilityCode) && x.FormulaId == formulaId select x; if (queryParameters == null || queryParameters.Any() == false) { throw new Exception(string.Format("Not Found Formula Parameters: {0},{1},{2},{3}", siteId, facilityTypeId, facilityCode, formulaId)); } List parametersForArray = new List(); foreach (var p in queryParameters.ToList()) { char parameter = p.ParameterId[0]; var pValue = new MathParameterValue { Variable = (MathCalculator.Parameter)(parameter - 'A'), Value = 0, }; parametersForArray.Add(pValue); var values = _CreateCalculationValues(startDate, endDate, timeInterval); var pointvalues = timeInterval == TimeInterval.Day ? GetMonitoringPointHistoryDaily(siteId, p.ParameterFacilityCode, p.ParameterPropertyId, startDate, endDate) : timeInterval == TimeInterval.Month ? GetMonitoringPointHistoryMonthly(siteId, p.ParameterFacilityCode, p.ParameterPropertyId, startDate, endDate) : null; if (pointvalues == null) continue; CalculationValue pp = null; CalculationValue v = null; for (var i = 0; i < values.Length; i++) { v = values[i]; for (var j = 0; j < pointvalues.Length; j++) { pp = pointvalues[j]; if (pp.DateTime == v.DateTime) { v.Value += pp.Value; } } } parameters.Add(new CalculationParameter { ParameterValue = pValue, Values = values }); } calculator.SetParameter(parametersForArray.ToArray()); } { var functions = calculator.GetFunctions(); if (functions.Any()) { foreach (var f in functions) { var tableValues = tableManager.GetTableValues(f.Function.FunctionName); if (tableValues == null) { throw new Exception("Not Found Function."); } f.Function.FunctionDelegate = (x) => { var index = Array.BinarySearch(tableValues, new FormulaTableManager.TableComparerValue { XValue = (double)x }); if (index < 0) { index = ~index; if (index == 0) { return Math.Round((decimal)tableValues[0].YValue, 2); } else if (index == tableValues.Length) { return Math.Round((decimal)tableValues[tableValues.Length - 1].YValue, 2); } } return Math.Round((decimal)tableValues[index].YValue, 2); }; } } } DateTime dateTime = DateTime.Now; if (parameters.Count > 0) { var ps = parameters.Cast().ToArray(); ParameterBox parameterBox = new ParameterBox(ps); while (parameterBox.Sync()) { var value = calculator.Calculate(); if (value != null) { var date = parameterBox.DateTime.ToString("yyyy-MM-dd"); list.Add(date, new CalculationResult { DateTime = parameterBox.DateTime, ShortDateTime = date, Value = value < 0 ? 0 : Math.Round((double)value, 2) }); } if (parameterBox.NextStage() == false) { break; } } } return list; } public CalculationValue[] GetMonitoringPointHistoryDaily(int siteId, int facilityCode, int propertyId, DateTime startDate, DateTime endDate) { var query = _context.BemsMonitoringPointHistoryDaily.Where(x => x.SiteId == siteId && x.FacilityCode == facilityCode && x.PropertyId == propertyId && startDate <= x.CreatedDateTime && x.CreatedDateTime <= endDate); if (query.Any() == false) { return null; } return query.Select(x => new CalculationValue { DateTime = x.CreatedDateTime, Value = x.DailyValue }).ToArray(); } public CalculationValue[] GetMonitoringPointHistoryMonthly(int siteId, int facilityCode, int propertyId, DateTime startDate, DateTime endDate) { var groupQuery = from data in _context.BemsMonitoringPointHistoryDaily where data.SiteId == siteId && data.FacilityCode == facilityCode && data.PropertyId == propertyId && startDate <= data.CreatedDateTime && data.CreatedDateTime <= endDate group data by new { Year = data.CreatedDateTime.Year, Month = data.CreatedDateTime.Month } into g // select g; select new { Year = g.Key.Year, Month = g.Key.Month, SumDailyValue = g.Sum(x => x.DailyValue), AverageDailyValue = g.Average(x => x.DailyValue) }; if (groupQuery == null || groupQuery.Any() == false) { return null; } //CalculationValue[] values = { };// = new CalculationValue[groupQuery.ToList().Count()]; CalculationValue[] values = new CalculationValue[groupQuery.ToList().Count()]; var i = 0; foreach (var g in groupQuery.ToList()) { double dValue = 0; if (_CheckPointValueType(siteId, facilityCode, propertyId) == 0) dValue = g.SumDailyValue; else if (_CheckPointValueType(siteId, facilityCode, propertyId) == 1) dValue = g.AverageDailyValue; else if (_CheckPointValueType(siteId, facilityCode, propertyId) == 2) { dValue = g.SumDailyValue; dValue = (dValue > 0) ? 1 : 0; } values[i] = new CalculationValue { DateTime = new DateTime(g.Year, g.Month, 1), //Value = g.Sum(x => x.CurrentValue) Value = dValue }; i++; } return values; } private int _CheckPointValueType(int siteId, int facilityCode, int propertyId) { // return 0 -> 누적, 1 -> 평균, 2 -> On,Off var Query = from data in _context.BemsMonitoringPoint where data.SiteId == siteId && data.FacilityCode == facilityCode && data.PropertyId == propertyId select data; if (Query.FirstOrDefault().ValueType == 2) return 2; if (Query.FirstOrDefault().ValueType == 0 && Query.FirstOrDefault().FuelTypeId > 0) return 0; if (Query.FirstOrDefault().ValueType == 0 && Query.FirstOrDefault().FuelTypeId == 0) return 1; return 0; } private CalculationValue[] _CreateCalculationValues(DateTime startDate, DateTime endDate, TimeInterval timeIntervalType) { DateTime datetime = startDate; int count = _GetCountInTimeRange(startDate, endDate, timeIntervalType); CalculationValue[] values = new CalculationValue[count]; for (var i = 0; i < values.Length; i++) { values[i] = new CalculationValue { DateTime = datetime, Value = 0 }; _NextTimeFromTimeInterval(ref datetime, timeIntervalType); } return values; } private int _GetCountInTimeRange(DateTime startDate, DateTime endDate, TimeInterval timeIntervalType) { TimeSpan ts = endDate - startDate; switch (timeIntervalType) { case TimeInterval.QuarterMin: return (int)ts.TotalMinutes / 15 + 1; case TimeInterval.Hour: return (int)ts.TotalHours + 1; case TimeInterval.Day: return (int)ts.TotalDays + 1; case TimeInterval.Month: { int count = 0; DateTime date = startDate; //while (date.Year <= endDate.Year && date.Month <= endDate.Month) while (date <= endDate) { count++; date = date.AddMonths(1); } return count; } default: // TimeInterval.Year: { int count = 0; DateTime date = startDate; while (date.Year <= endDate.Year) { count++; date = date.AddYears(1); } return count; } } } private void _NextTimeFromTimeInterval(ref DateTime datetime, TimeInterval timeIntervalType) { switch (timeIntervalType) { case TimeInterval.QuarterMin: datetime = datetime.AddMinutes(15); break; case TimeInterval.Hour: datetime = datetime.AddHours(1); break; case TimeInterval.Day: datetime = datetime.AddDays(1); break; case TimeInterval.Month: datetime = datetime.AddMonths(1); break; default: // TimeInterval.Year: datetime = datetime.AddYears(1); break; } } public IQueryable GetFuelType() { var data = _context.BemsFuelType.Where(x => x.FuelTypeId != 0); return data; } } }