using System; using System.Collections; using System.Collections.Generic; using System.Data.Entity; using System.Data.Entity.Infrastructure; using System.Linq; using System.Net; using System.Web; using System.Web.Http; using System.Web.Http.Description; using DevExpress.Office.Utils; using iBemsDataService.Model; using iBemsDataService.Util; using System.Data.Entity.Validation; using System.Text; using System.Text.RegularExpressions; using iBemsDataService.Controllers.Bems.Formula; using System.Diagnostics; using iBemsDataService.Controllers.Bems.Common; using System.Transactions; namespace iBemsDataService.Controllers { public class BemsFormulaController : ApiController { private iBemsEntities db; private PointHistoryValueManager pointHistoryValueManager; private static Regex regexParameter = new Regex(@"\b[A-Z]\b", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase); private static Regex regexFunction = new Regex(@"\$([\w]+).+\$", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase); private static FormulaTableManager tableManager = new FormulaTableManager(); //private BemsMonitoringPointHistoryController pointHistoryController; public BemsFormulaController() { db = new iBemsEntities(); pointHistoryValueManager = new PointHistoryValueManager(db); } public BemsFormulaController(iBemsEntities bemsDb) { db = bemsDb; } [ActionName("Calculation")] public List GetBemsFormula() { Uri uri = Request.RequestUri; var uriQuery = HttpUtility.ParseQueryString(uri.Query); string uriSiteId = uriQuery.Get("SiteId"); string uriFacilityTypeId = uriQuery.Get("FacilityTypeId"); string uriFormulaId = uriQuery.Get("FormulaId"); string uriTimeIntervalType = uriQuery.Get("TimeIntervalType"); string uriStartDate = uriQuery.Get("StartDate"); string uriEndDate = uriQuery.Get("EndDate"); string uriFacilityCode = uriQuery.Get("FacilityCode"); int siteId = -1, facilityTypeId = -1, formulaId = -1, timeIntervalType = -1, facilityCode = -1; DateTime startDate, endDate; if (int.TryParse(uriSiteId, out siteId) == false || int.TryParse(uriFacilityTypeId, out facilityTypeId) == false || int.TryParse(uriFormulaId, out formulaId) == false || int.TryParse(uriTimeIntervalType, out timeIntervalType) == false || int.TryParse(uriFacilityCode, out facilityCode) == false || DateTime.TryParse(uriStartDate, out startDate) == false || DateTime.TryParse(uriEndDate, out endDate) == false) { throw new Exception(string.Format("Not Found FFFF Parameters: {0},{1},{2},{3},{4},{5},{6}", uriSiteId, uriFacilityTypeId, facilityCode, uriFormulaId, uriTimeIntervalType, uriStartDate, uriEndDate)); } return GetBemsFormulaReal(siteId, facilityTypeId, facilityCode, formulaId, startDate, endDate, timeIntervalType); } public List GetBemsFormulaReal(int siteId, int facilityTypeId, int facilityCode, int formulaId, DateTime startDate, DateTime endDate, int timeIntervalType) { List list = new List(); BemsFormula formula = GetFormula(siteId, facilityTypeId, facilityCode, formulaId); if (formula == null) return list; TimeInterval timeInterval = (TimeInterval)timeIntervalType; ArrayList parameters = new ArrayList(); MathCalculator calculator = new MathCalculator(); if (false == calculator.Compile(formula.Formula)) { throw new Exception("Failed to compile formula: " + formula.Formula); } var match = regexParameter.Match(formula.Formula); if (match.Success) { var queryParameters = db.BemsFormulaParameter.Where(x => x.SiteId == siteId && x.FacilityTypeId == facilityTypeId && //x.FacilityCode == facilityCode && //(facilityTypeId >= 24 || x.FacilityCode == facilityCode) && // hcLee 2015 04 21 (facilityTypeId >= 100 || x.FacilityCode == facilityCode) && // hcLee 2015 04 28 x.FormulaId == formulaId); 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) { 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); //2015 04 22 hcLee var pointvalues = pointHistoryValueManager.GetPointValues(siteId, p.ParameterFacilityCode, p.ParameterPropertyId, timeInterval, startDate, endDate); if (pointvalues == null) continue; int index = 0; CalculationValue pp = null; CalculationValue v = null; for (var i = 0; i < values.Length; i++) { v = values[i]; if (pp == null) { if (pointvalues.Length <= index) break; pp = pointvalues[index]; } if (pp.DateTime == v.DateTime) { v.Value += pp.Value; pp = null; index++; if (pointvalues.Length <= index) break; } } 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) => { //Trace.WriteLine( typeof( x ) ); var index = Array.BinarySearch(tableValues, new FormulaTableManager.TableComparerValue { XValue = (double)x }); if (index < 0) { index = ~index; if (index == 0) { //return (decimal)tableValues[0].YValue; return Math.Round((decimal)tableValues[0].YValue, 2); } else if (index == tableValues.Length) { //return (decimal)tableValues[tableValues.Length - 1].YValue; return Math.Round((decimal)tableValues[tableValues.Length - 1].YValue, 2); } } //return (decimal)tableValues[index].YValue; return Math.Round((decimal)tableValues[index].YValue, 2); }; } } } //Trace.WriteLine( calculator.Calculate() ); 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) { list.Add(new CalculationResult { DateTime = parameterBox.DateTime, Value = Math.Round((double)value, 2) //Value = (double)value }); } if (parameterBox.NextStage() == false) { break; } } } else { /* 2015 06 12 hcLee 막음, 데이터가 하나도 없는 경우 현재시간으로 이상한 값이 한개 오는 현상 var value = calculator.Calculate(); if( value != null ) { list.Add( new CalculationResult { DateTime = dateTime , Value = (double)value } ); } */ } return list; } [ResponseType(typeof(void))] [ActionName("ControlPoint")] public IHttpActionResult PostControlPoint() { Uri uri = Request.RequestUri; var uriQuery = HttpUtility.ParseQueryString(uri.Query); string uriSiteId = uriQuery.Get("SiteId"); string uriFacilityTypeId = uriQuery.Get("FacilityTypeId"); string uriFacilityCode = uriQuery.Get("FacilityCode"); string uriFormulaId = uriQuery.Get("FormulaId"); string uriControlValue = uriQuery.Get("ControlValue"); int siteId = -1, facilityTypeId = -1, formulaId = -1, facilityCode = -1; double controlValue = 0; if (int.TryParse(uriSiteId, out siteId) == false || int.TryParse(uriFacilityTypeId, out facilityTypeId) == false || int.TryParse(uriFormulaId, out formulaId) == false || int.TryParse(uriFacilityCode, out facilityCode) == false || double.TryParse(uriControlValue, out controlValue) == false) { throw new Exception(string.Format("Not Found FFFF Parameters: {0},{1},{2},{3},{4} ", uriSiteId, uriFacilityTypeId, facilityCode, uriFormulaId, uriControlValue)); } BemsFormula formula = GetFormula(siteId, facilityTypeId, facilityCode, formulaId); if (formula == null) return StatusCode(HttpStatusCode.NoContent); ArrayList parameters = new ArrayList(); MathCalculator calculator = new MathCalculator(); if (false == calculator.Compile(formula.Formula)) { throw new Exception("Failed to compile formula: " + formula.Formula); } var match = regexParameter.Match(formula.Formula); if (match.Success) { var queryParameters = db.BemsFormulaParameter.Where(x => x.SiteId == siteId && x.FacilityTypeId == facilityTypeId && //x.FacilityCode == facilityCode && //(facilityTypeId >= 24 || x.FacilityCode == facilityCode) && // hcLee 2015 04 21 (facilityTypeId >= 100 || x.FacilityCode == facilityCode) && // hcLee 2015 04 28 x.FormulaId == formulaId); if (queryParameters.Any() == false) { throw new Exception(string.Format("Not Found 2222 Parameters: {0},{1},{2},{3},{4}", siteId, facilityTypeId, facilityCode, formulaId, uriControlValue)); } List parametersForArray = new List(); using (var transaction = new TransactionScope()) { foreach (var p in queryParameters) { char parameter = p.ParameterId[0]; var pValue = new MathParameterValue { Variable = (MathCalculator.Parameter)(parameter - 'A'), Value = 0, }; DateTime currentTime = DateTime.Now; try { { var control = new BemsControlPointHistory { SiteId = siteId, //FacilityTypeId = facilityTypeId, // 2015 08 05 두소장과 통화중 일단 결정함. FacilityTypeId = facilityTypeId, // 2015 08 05 두소장과 통화중 일단 결정함. FacilityCode = p.ParameterFacilityCode, PropertyId = p.ParameterPropertyId, // ???? hcLee CreateDateTime = currentTime, ControlValue = controlValue, WriteServiceName = null, ActionDateTime = null }; db.BemsControlPointHistory.Add(control); db.SaveChanges(); } } catch (Exception e) { Trace.WriteLine(e.Message); //throw e; throw; } } transaction.Complete(); } //calculator.SetParameter(parametersForArray.ToArray()); } return StatusCode(HttpStatusCode.NoContent); } 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 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; } } 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; } } } /* [ActionName("ServiceType")] public List GetBemsFormulaService() { Uri uri = Request.RequestUri; var uriQuery = HttpUtility.ParseQueryString(uri.Query); string uriSiteId = uriQuery.Get("SiteId"); string uriFacilityTypeId = uriQuery.Get("FacilityTypeId"); string uriFormulaId = uriQuery.Get("FormulaId"); string uriTimeIntervalType = uriQuery.Get("TimeIntervalType"); string uriStartDate = uriQuery.Get("StartDate"); string uriEndDate = uriQuery.Get("EndDate"); string uriFacilityCode = uriQuery.Get("FacilityCode"); string uriServiceTypeId = uriQuery.Get("ServiceTypeId"); int siteId = -1, facilityTypeId = -1, formulaId = -1, timeIntervalType = -1, facilityCode = -1; int serviceTypeId = -1; DateTime startDate, endDate; if (int.TryParse(uriSiteId, out siteId) == false || int.TryParse(uriFacilityTypeId, out facilityTypeId) == false || int.TryParse(uriFormulaId, out formulaId) == false || int.TryParse(uriTimeIntervalType, out timeIntervalType) == false || int.TryParse(uriFacilityCode, out facilityCode) == false || DateTime.TryParse(uriStartDate, out startDate) == false || DateTime.TryParse(uriEndDate, out endDate) == false || int.TryParse(uriServiceTypeId, out serviceTypeId) == false) { throw new Exception(string.Format("Not Found Parameters: {0},{1},{2},{3},{4},{5},{6}, {7}", uriSiteId, uriFacilityTypeId, facilityCode, uriFormulaId, uriTimeIntervalType, uriStartDate, uriEndDate, uriServiceTypeId)); } TimeInterval timeInterval = (TimeInterval)timeIntervalType; BemsFormula formula = GetFormula(siteId, facilityTypeId, facilityCode, formulaId); ArrayList parameters = new ArrayList(); MathCalculator calculator = new MathCalculator(); if (false == calculator.Compile(formula.Formula)) { throw new Exception("Failed to compile formula: " + formula.Formula); } var match = regexParameter.Match(formula.Formula); if (match.Success) { var queryParameters = db.BemsFormulaParameter.Where(x => x.SiteId == siteId && x.FacilityTypeId == facilityTypeId && x.FacilityCode == facilityCode && x.FormulaId == formulaId); if (queryParameters.Any() == false) { throw new Exception(string.Format("Not Found Parameters: {0},{1},{2},{3}", siteId, facilityTypeId, facilityCode, formulaId)); } List parametersForArray = new List(); foreach (var p in queryParameters) { char parameter = p.ParameterId[0]; var pValue = new MathParameterValue { Variable = (MathCalculator.Parameter)(parameter - 'A'), Value = 0, }; parametersForArray.Add(pValue); var values = pointHistoryValueManager.GetPointValues(siteId, p.ParameterFacilityCode, p.ParameterPropertyId, timeInterval, startDate, endDate); 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) => { //Trace.WriteLine( typeof( x ) ); var index = Array.BinarySearch(tableValues, new FormulaTableManager.TableComparerValue { XValue = (double)x }); if (index < 0) { index = ~index; if (index == 0) { return (decimal)tableValues[0].YValue; } else if (index == tableValues.Length) { return (decimal)tableValues[tableValues.Length - 1].YValue; } } return (decimal)tableValues[index].YValue; }; } } } //Trace.WriteLine( calculator.Calculate() ); List list = new List(); 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) { list.Add(new CalculationResult { DateTime = parameterBox.DateTime, Value = (double)value }); } if (parameterBox.NextStage() == false) { break; } } } else { var value = calculator.Calculate(); if (value != null) { list.Add(new CalculationResult { DateTime = dateTime, Value = (double)value }); } } return list; } */ [ResponseType(typeof(void))] public IHttpActionResult PostBemsFormula(FormulaData formula) { if (!ModelState.IsValid) { return BadRequest(ModelState); } var queryFormula = db.BemsFormula.Where(x => x.SiteId == formula.SiteId && x.FacilityTypeId == formula.FacilityTypeId && x.FacilityCode == formula.FacilityCode && x.FormulaId == formula.FormulaId); BemsFormula f = null; bool isNewFormula = false; if (queryFormula.Any()) { f = queryFormula.First(); } else { f = new BemsFormula(); isNewFormula = true; } f.SiteId = formula.SiteId; f.FacilityTypeId = formula.FacilityTypeId; f.FacilityCode = formula.FacilityCode; f.FormulaId = formula.FormulaId; f.Formula = formula.Formula; if (isNewFormula) { db.BemsFormula.Add(f); } var parameterQuery = db.BemsFormulaParameter.Where(x => x.SiteId == formula.SiteId && x.FacilityTypeId == formula.FacilityTypeId && x.FacilityCode == formula.FacilityCode && x.FormulaId == formula.FormulaId); var qm = new QueryManager(db); try { qm.DeleteAndInsert(db.BemsFormulaParameter, formula.Paramters, parameterQuery); if (formula.Paramters.Count == 0) { db.BemsFormula.Remove(queryFormula.FirstOrDefault()); } } catch (DbEntityValidationException ex) { StringBuilder sb = new StringBuilder(); foreach (var failure in ex.EntityValidationErrors) { sb.AppendFormat("{0} failed validation\n", failure.Entry.Entity.GetType()); foreach (var error in failure.ValidationErrors) { sb.AppendFormat("- {0} : {1}", error.PropertyName, error.ErrorMessage); sb.AppendLine(); } } return BadRequest(sb.ToString()); // throw ex; } catch (Exception) { throw; } db.SaveChanges(); return StatusCode(HttpStatusCode.NoContent); } protected override void Dispose(bool disposing) { if (disposing) { db.Dispose(); } base.Dispose(disposing); } //private BemsFormula GetFormula( int siteId , int facilityTypeId , public BemsFormula GetFormula(int siteId, int facilityTypeId, int facilityCode, int formulaId) { /* var queryFormula = db.BemsFormula.Where( x => x.SiteId == siteId && x.FacilityTypeId == facilityTypeId && //x.FacilityCode == facilityCode) && //(facilityTypeId >= 24 || x.FacilityCode == facilityCode) && // hcLee 2015 04 16 (facilityTypeId >= 100 || x.FacilityCode == facilityCode) && // hcLee 2015 04 28 x.FormulaId == formulaId );*/ var queryFormula = from f in db.BemsFormula where f.SiteId == siteId && f.FacilityTypeId == facilityTypeId && (facilityTypeId >= 100 || f.FacilityCode == facilityCode) && f.FormulaId == formulaId select f; if (queryFormula == null || queryFormula.Any() == false) { //throw new Exception(string.Format("Not Found FFFF Formula: {0},{1},{2},{3}", siteId, facilityTypeId, facilityCode, formulaId)); //throw new Exception(string.Format("설비 {0}의 {1}번 성능분석 수식이 필요합니다!", facilityCode, formulaId)); //throw new Exception(string.Format("성능분석 수식이 필요합니다!", facilityCode, formulaId)); //return null; //throw new Exception("성능분석 수식이 필요합니다!"); //throw new Exception("Make Fornula please"); return null; } //if (queryFormula == null || queryFormula.Any() == false) return null; return queryFormula.Single(); } } public class CalculationParameter { public MathParameterValue ParameterValue { get; set; } //public string FacilityCode { get; set; } //public int PropertyId { get; set; } public CalculationValue[] Values { get; set; } public DateTime SetValueFromIndex(int index) { var value = this.Values[index]; this.ParameterValue.Value = (decimal)value.Value; return value.DateTime; } }; public class FormulaData { public int SiteId { get; set; } public int FacilityTypeId { get; set; } public int FacilityCode { get; set; } public int FormulaId { get; set; } public string Formula { get; set; } public List Paramters { get; set; } }; public class FormulaParameterData { public int SiteId { get; set; } public int FacilityTypeId { get; set; } public int FacilityCode { get; set; } public int FormulaId { get; set; } public string ParameterId { get; set; } public int ParameterFacilityCode { get; set; } public int ParameterPropertyId { get; set; } }; }