FormulaControllers.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. using System;
  2. using System.Linq;
  3. using System.Threading.Tasks;
  4. using FMSAdmin.Data;
  5. using FMSAdmin.Models;
  6. using FMSAdmin.Entities;
  7. using FMSApp.Services;
  8. using Microsoft.AspNetCore.Mvc;
  9. using Microsoft.Extensions.Logging;
  10. using Microsoft.AspNetCore.Authorization;
  11. using FMSAdmin.Helpers;
  12. using System.Data;
  13. using System.IO;
  14. using OfficeOpenXml;
  15. using System.Text.RegularExpressions;
  16. using System.Collections;
  17. using System.Collections.Generic;
  18. using FMSAdmin.Models.Formula;
  19. using FMSAdmin.Helpers.Formula;
  20. namespace FMSApp.Controllers {
  21. [Authorize]
  22. [ApiController]
  23. [ApiVersion("1")]
  24. [Route("api/app/[controller]")]
  25. public class FormulaController : Controller {
  26. private static Regex regexParameter = new Regex(@"\b[A-Z]\b", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase);
  27. private static Regex regexFunction = new Regex(@"\$([\w]+).+\$", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase);
  28. private static FormulaTableManager tableManager;
  29. private readonly ILogger<FormulaController> _logger;
  30. private readonly FormulaService _service;
  31. private readonly FMSContext _context;
  32. public FormulaController(
  33. ILogger<FormulaController> logger,
  34. FormulaService service,
  35. FMSContext context
  36. ) {
  37. _logger = logger;
  38. _service = service;
  39. _context = context;
  40. tableManager = new FormulaTableManager(context);
  41. }
  42. /// <summary>
  43. // 성능분석-챠트에 사용되는듯
  44. ///</summary>
  45. [HttpGet("[action]")]
  46. public IActionResult Calculation([FromQuery] int siteId, [FromQuery] int facilityTypeId, [FromQuery] int formulaId, [FromQuery] int facilityCode, [FromQuery] int timeIntervalType, [FromQuery] string sDate, [FromQuery] string eDate) {
  47. DateTime startDate = DateTime.Parse(sDate);
  48. DateTime endDate = DateTime.Parse(eDate);
  49. List<CalculationResult> list = new List<CalculationResult>();
  50. BemsFormula formula = GetFormula(Util.ToInt(siteId), Util.ToInt(facilityTypeId), Util.ToInt(facilityCode), Util.ToInt(formulaId));
  51. if (formula == null) return Ok(new { });
  52. TimeInterval timeInterval = (TimeInterval)timeIntervalType;
  53. ArrayList parameters = new ArrayList();
  54. MathCalculator calculator = new MathCalculator();
  55. if (false == calculator.Compile(formula.Formula)) {
  56. throw new Exception("Failed to compile formula: " + formula.Formula);
  57. }
  58. var match = regexParameter.Match(formula.Formula);
  59. if (match.Success) {
  60. var queryParameters = _context.BemsFormulaParameter.Where(x =>
  61. x.SiteId == siteId &&
  62. x.FacilityTypeId == facilityTypeId &&
  63. (facilityTypeId >= 100 || x.FacilityCode == facilityCode) &&
  64. x.FormulaId == formulaId);
  65. if (queryParameters == null || queryParameters.Any() == false) {
  66. throw new Exception(string.Format("Not Found Formula Parameters: {0},{1},{2},{3}", siteId, facilityTypeId, facilityCode, formulaId));
  67. }
  68. List<MathParameterValue> parametersForArray = new List<MathParameterValue>();
  69. var test = queryParameters.ToList();
  70. foreach (var p in queryParameters.ToList()) {
  71. char parameter = p.ParameterId[0];
  72. var pValue = new MathParameterValue {
  73. Variable = (MathCalculator.Parameter)(parameter - 'A'),
  74. Value = 0,
  75. };
  76. parametersForArray.Add(pValue);
  77. var values = CreateCalculationValues(startDate, endDate, timeInterval);
  78. var pointvalues = _service.GetPointValues(siteId, p.ParameterFacilityCode,
  79. p.ParameterPropertyId, timeInterval, startDate, endDate);
  80. if (pointvalues == null)
  81. continue;
  82. CalculationValue pp = null;
  83. CalculationValue v = null;
  84. for (var i = 0; i < values.Length; i++) {
  85. v = values[i];
  86. for (var j = 0; j < pointvalues.Length; j++) {
  87. pp = pointvalues[j];
  88. if (pp.DateTime == v.DateTime) {
  89. v.Value += pp.Value;
  90. }
  91. }
  92. }
  93. parameters.Add(new CalculationParameter {
  94. ParameterValue = pValue,
  95. Values = values
  96. });
  97. }
  98. calculator.SetParameter(parametersForArray.ToArray());
  99. }
  100. {
  101. var functions = calculator.GetFunctions();
  102. if (functions.Any()) {
  103. foreach (var f in functions) {
  104. var tableValues = tableManager.GetTableValues(f.Function.FunctionName);
  105. if (tableValues == null) {
  106. throw new Exception("Not Found Function.");
  107. }
  108. f.Function.FunctionDelegate = (x) => {
  109. var index = Array.BinarySearch(tableValues, new FormulaTableManager.TableComparerValue { XValue = (double)x });
  110. if (index < 0) {
  111. index = ~index;
  112. if (index == 0) {
  113. return Math.Round((decimal)tableValues[0].YValue, 2);
  114. } else if (index == tableValues.Length) {
  115. return Math.Round((decimal)tableValues[tableValues.Length - 1].YValue, 2);
  116. }
  117. }
  118. return Math.Round((decimal)tableValues[index].YValue, 2);
  119. };
  120. }
  121. }
  122. }
  123. DateTime dateTime = DateTime.Now;
  124. if (parameters.Count > 0) {
  125. var ps = parameters.Cast<CalculationParameter>().ToArray();
  126. ParameterBox parameterBox = new ParameterBox(ps);
  127. while (parameterBox.Sync()) {
  128. var value = calculator.Calculate();
  129. if (value != null) {
  130. list.Add(new CalculationResult {
  131. DateTime = parameterBox.DateTime,
  132. ShortDateTime = timeInterval == TimeInterval.Day ? parameterBox.DateTime.ToString("yyyy.MM.dd") : parameterBox.DateTime.ToString("yyyy.MM"),
  133. Value = Math.Round((double)value, 2)
  134. //Value = (double)value
  135. });
  136. }
  137. if (parameterBox.NextStage() == false) {
  138. break;
  139. }
  140. }
  141. } else {
  142. IList emptyArr = new List<CalculationResult>();
  143. return Ok(new {
  144. total = 0,
  145. page = 1,
  146. limit = 0,
  147. list = emptyArr,
  148. maxValue = 0
  149. });
  150. }
  151. //list.Select(x=>x.Value).Max();
  152. return Ok(new {
  153. total = list.Count(),
  154. page = 1,
  155. limit = 0,
  156. list = list,
  157. maxValue = list.Select(x => x.Value).Max()
  158. });
  159. }
  160. public BemsFormula GetFormula(int siteId, int facilityTypeId, int facilityCode, int formulaId) {
  161. var queryFormula = from f in _context.BemsFormula
  162. where f.SiteId == siteId && f.FacilityTypeId == facilityTypeId &&
  163. (facilityTypeId >= 100 || f.FacilityCode == facilityCode) && f.FormulaId == formulaId
  164. select f;
  165. if (queryFormula == null || queryFormula.Any() == false) {
  166. return null;
  167. }
  168. return queryFormula.Single();
  169. }
  170. private CalculationValue[] CreateCalculationValues(DateTime startDate, DateTime endDate, TimeInterval timeIntervalType) {
  171. DateTime datetime = startDate;
  172. int count = GetCountInTimeRange(startDate, endDate, timeIntervalType);
  173. CalculationValue[] values = new CalculationValue[count];
  174. for (var i = 0; i < values.Length; i++) {
  175. values[i] = new CalculationValue {
  176. DateTime = datetime,
  177. Value = 0
  178. };
  179. NextTimeFromTimeInterval(ref datetime, timeIntervalType);
  180. }
  181. return values;
  182. }
  183. private int GetCountInTimeRange(DateTime startDate, DateTime endDate, TimeInterval timeIntervalType) {
  184. TimeSpan ts = endDate - startDate;
  185. switch (timeIntervalType) {
  186. case TimeInterval.QuarterMin:
  187. return (int)ts.TotalMinutes / 15 + 1;
  188. case TimeInterval.Hour:
  189. return (int)ts.TotalHours + 1;
  190. case TimeInterval.Day:
  191. return (int)ts.TotalDays + 1;
  192. case TimeInterval.Month: {
  193. int count = 0;
  194. DateTime date = startDate;
  195. //while (date.Year <= endDate.Year && date.Month <= endDate.Month)
  196. while (date <= endDate) {
  197. count++;
  198. date = date.AddMonths(1);
  199. }
  200. return count;
  201. }
  202. default: // TimeInterval.Year:
  203. {
  204. int count = 0;
  205. DateTime date = startDate;
  206. while (date.Year <= endDate.Year) {
  207. count++;
  208. date = date.AddYears(1);
  209. }
  210. return count;
  211. }
  212. }
  213. }
  214. private void NextTimeFromTimeInterval(ref DateTime datetime, TimeInterval timeIntervalType) {
  215. switch (timeIntervalType) {
  216. case TimeInterval.QuarterMin:
  217. datetime = datetime.AddMinutes(15);
  218. break;
  219. case TimeInterval.Hour:
  220. datetime = datetime.AddHours(1);
  221. break;
  222. case TimeInterval.Day:
  223. datetime = datetime.AddDays(1);
  224. break;
  225. case TimeInterval.Month:
  226. datetime = datetime.AddMonths(1);
  227. break;
  228. default: // TimeInterval.Year:
  229. datetime = datetime.AddYears(1);
  230. break;
  231. }
  232. }
  233. }
  234. }