/// <summary> /// Метод, проверяющий валидность формулы /// </summary> /// <param name="formula"></param> /// <returns></returns> public bool Validate(ServerFormula formula) { if (string.IsNullOrWhiteSpace(formula?.FormulaString)) { return(false); } var tokens = TokenDiscriminator.ConstructTokens(formula.FormulaString); if ((tokens?.Count ?? 0) == 0 || tokens.Any(t => t is UnknownToken)) { return(false); } if (tokens.Any(token => token.Value == formula.Name)) //проверка на рекурсивную ссылку { return(false); } var bracketsIsValid = ValidateBrackets(tokens); if (!bracketsIsValid) { return(false); } var tokenSequenceIsValid = ValidateTokenSequence(tokens); if (!tokenSequenceIsValid) { return(false); } return(true); }
/// <summary> /// Асинхронный метод пересылки состояния. Добавляет пользователя в группу рассылки /// </summary> /// <param name="name"></param> /// <returns></returns> public async Task GetState(string name) { //достаем формулу из репозитория, чтобы убедиться, что такая вообще есть ServerFormula formula = null; using (AsyncScopedLifestyle.BeginScope(container)) formula = await container.GetInstance <IRepository <ServerFormula> >().GetByNameAsync(name); if (formula is null) { Clients.Caller.SendError(name, "Формула не найдена или была окончательно удалена", DateTime.UtcNow); } else { //Добавляем в группу коннекшн и отправляем ему текущее состояние await Groups.Add(Context.ConnectionId, name); connectionGroups.AddOrUpdate(Context.ConnectionId, new List <string> { name }, (key, value) => { value.Add(name); return(value); }); Clients.Caller.SendState(formula.Name, formula.Status, DateTime.UtcNow); } }
public async Task <IHttpActionResult> Post([FromBody][Bind(Include = "Name, FormulaString")] ServerFormula formula) { if (!ModelState.IsValid) { return(BadRequest(ModelState)); } var existsformula = await repository.GetByNameAsync(formula.Name); if (existsformula != null) { return(Content(System.Net.HttpStatusCode.Conflict, "Такая формула уже существует")); } var success = await repository.CreateAsync(formula); if (success) { monitor.Created(); return(Created("api/calculator", "Запрос на создание формулы успешно создан")); } else { return(InternalServerError(new Exception("Не удалось сохранить объект"))); } }
public async Task <IHttpActionResult> Update([FromBody][Bind(Include = "Name, FormulaString")] ServerFormula formula) { if (!ModelState.IsValid) { return(BadRequest(ModelState)); } var existsformula = await repository.GetByNameAsync(formula.Name); if (existsformula == null) { return(NotFound()); } existsformula.FormulaString = formula.FormulaString; var success = await repository.UpdateAsync(existsformula); if (success) { monitor.Updated(); return(Content(System.Net.HttpStatusCode.OK, "Запрос на обновление успешно создан")); } else { return(InternalServerError(new Exception("Не удалось обновить объект"))); } }
public void Validate_WithNullStringTest() { //Arrange var formula = new ServerFormula(); //Act var isValid = validator.Validate(formula); //Assert Assert.IsFalse(isValid); }
public void Validate_NotValidSequenceTest() { //Arrange var formula = new ServerFormula() { Name = "a", FormulaString = "12 + - 10 * (5)" }; //Act var isValid = validator.Validate(formula); //Assert Assert.IsFalse(isValid); }
/// <summary> /// Расчет значения формулы /// </summary> /// <param name="formula"></param> /// <returns></returns> public bool Calculate(ServerFormula formula, List <ServerFormula> requirments) { var tokens = TokenDiscriminator.Tokens ?? TokenDiscriminator.ConstructTokens(formula.FormulaString); tokens.CreateRPN(); try { formula.Value = tokens.Calculate(requirments); } catch (DivideByZeroException) { throw; } catch { return(false); } return(true); }
public void ValidateRecursiveReferenceTest() { //Arrange var formula = new ServerFormula() { Name = "a", FormulaString = "(12 + 10) * (a)" }; //Act var isValid = validator.Validate(formula); //Assert Assert.IsFalse(isValid); }
public void Validate_NotValidBracketTest() { //Arrange var formula = new ServerFormula() { Name = "a", FormulaString = "(12 + 10)) * (5)" }; //Act var isValid = validator.Validate(formula); //Assert Assert.IsFalse(isValid); }
public void Validate_WithUnknownTokenTest() { //Arrange var formula = new ServerFormula() { Name = "a", FormulaString = "12 + - 10 * (5) + _a" }; //Act var isValid = validator.Validate(formula); //Assert Assert.IsFalse(isValid); }
public void ValidateSuccessTest() { //Arrange var formula = new ServerFormula() { Name = "a", FormulaString = "(12 + 10) * (c)" }; //Act var isValid = validator.Validate(formula); //Assert Assert.IsTrue(isValid); }
public void CalculateTest() { //Arrange var formula = new ServerFormula() { Name = "a", FormulaString = "2 + 2" }; //Act var success = calculator.Calculate(formula, new List <ServerFormula>()); //Assert Assert.IsTrue(success); }
public void Calculate_WithNotEnoughRequirements() { //Arrange var formula = new ServerFormula() { Name = "a", FormulaString = "2 + b" }; //Act var success = calculator.Calculate(formula, new List <ServerFormula>()); //Assert Assert.IsFalse(success); }
public void Add_ValidationErrorTest() { //Arrange ServerFormula formula = new ServerFormula { FormulaString = null }; controller = new CalculatorController(repository.Object, monitor.Object); //Act var result = controller.Post(formula).Result as ExceptionResult; //Assert Assert.IsNotNull(result); }
public INotifier ChangeStatus(ServerFormula formula, FormulaStatus newStatus) { if (formula is null) { throw new ArgumentNullException(nameof(formula)); } formula.Status = newStatus; // Информация в обновлении info = new UpdateInfo(formula?.Name, newStatus); return(this); }
public void Delete_NotFoundTest() { //Arrange ServerFormula formula = new ServerFormula { FormulaString = null }; controller = new CalculatorController(repository.Object, monitor.Object); //Act var result = controller.Update(formula).Result as NotFoundResult; //Assert Assert.IsNotNull(result); }
public void ChangeStateTest() { //Arrange IFormulaStatusManager statusManager = new FormulaStatusManager(); var formula = new ServerFormula() { Status = FormulaStatus.Success }; var newStatus = FormulaStatus.Deleted; //Act var notifier = statusManager.ChangeStatus(formula, newStatus); //Assert Assert.AreEqual(newStatus, formula.Status); Assert.IsNotNull(notifier); }
public void Add_AlreadyExistsTest() { //Arrange ServerFormula formula = new ServerFormula { Name = "A", FormulaString = "5 + 5" }; repository.Setup(r => r.GetByNameAsync(It.IsAny <string>())).Returns(Task.FromResult(formula)); controller = new CalculatorController(repository.Object, monitor.Object); //Act var result = controller.Post(formula).Result as NegotiatedContentResult <string>; //Assert repository.Verify(); Assert.IsNotNull(result); }
public void Delete_ErrorSaveTest() { //Arrange ServerFormula formula = new ServerFormula { Name = "A", FormulaString = "5 + 5" }; repository.Setup(r => r.GetByNameAsync("A")).Returns(Task.FromResult(formula)); repository.Setup(r => r.CreateAsync(formula)).Returns(Task.FromResult(false)); controller = new CalculatorController(repository.Object, monitor.Object); //Act var result = controller.Delete(formula.Name).Result as ExceptionResult; //Assert repository.Verify(); Assert.IsNotNull(result); }
public void AddTest() { //Arrange ServerFormula formula = new ServerFormula { Name = "A", FormulaString = "5 + 5" }; repository.Setup(r => r.CreateAsync(formula)).Returns(Task.FromResult(true)); monitor.Setup(m => m.Created()); controller = new CalculatorController(repository.Object, monitor.Object); //Act var result = controller.Post(formula).Result as CreatedNegotiatedContentResult <string>; //Assert repository.Verify(); Assert.IsNotNull(result); Assert.IsFalse(string.IsNullOrEmpty(result.Content)); }
/// <summary> /// Вызывается когда все необходимые значения есть и остается только посчитать /// </summary> /// <param name="formula"></param> /// <param name="requireExistsFormula"></param> private void AllRequirementsReady(ServerFormula formula, IEnumerable <ServerFormula> requireExistsFormula) { foreach (var require in requireExistsFormula) //Добавляем ссылки на необходимые значения в базу { if (!formula.Required.Contains(require)) { formula.Required.Add(require); } } try { formulaCalculator.Calculate(formula, requireExistsFormula.ToList()); // и Считаем } catch (DivideByZeroException) { statusManager.ChangeStatus(formula, FormulaStatus.DivideByZeroError); } }
public void GetWithIdTest() { //Arrange const int searchingId = 1; var formula = new ServerFormula() { FormulaId = searchingId }; repository.Setup(r => r.GetByIdAsync(searchingId)).Returns(Task.FromResult(formula)); controller = new CalculatorController(repository.Object, monitor.Object); //Act var result = controller.Get(searchingId).Result as JsonResult <ServerFormula>; var model = result.Content; //Assert repository.Verify(); Assert.IsNotNull(result); Assert.AreSame(formula, model); }
/// <summary> /// Асинхронный метод расчета формул /// </summary> /// <param name="formula"></param> /// <returns></returns> public async Task CalculateAsync(ServerFormula formula, Func <Func <ServerFormula, bool>, Task <IEnumerable <ServerFormula> > > getSource) { bool isCalculated = false; DateTime startCalculateTime = DateTime.UtcNow; var tree = CreateTree(formula); // Если не будут получены все данные для расчета формулы в течение 10 минут, // то формула считается невалидной и не будет расчитана while (!isCalculated && (DateTime.UtcNow - startCalculateTime).TotalMinutes < 10) { isCalculated = await CalculateValue(tree, getSource); await Task.Delay(500); } if (!isCalculated) { formula.Status = FormulaStatus.Error; } }
/// <summary> /// Метод, проверяющий валидность формулы /// </summary> /// <param name="formula"></param> /// <returns></returns> public bool IsValid(ServerFormula formula) { throw new NotImplementedException(); }
/// <summary> /// Построение дерева выражения /// </summary> /// <param name="formula"></param> /// <returns></returns> private object CreateTree(ServerFormula formula) { throw new NotImplementedException(); }