private async Task <VariableSet> GetOperandChildsAsync(Operand parent, VariableSet variableSet)
        {
            KeyValuePair <string, double> result;
            await _context.Entry(parent).Collection(x => x.Childs).Query().LoadAsync();

            var childs = parent.Childs;

            if (childs.Count > 1)
            {
                //caculate child
                for (int i = 1; i < childs.Count; i++)
                {
                    Console.WriteLine("i: " + i);
                    await GetOperandChildsAsync(childs.ElementAt(i), variableSet);
                }
                //caculate parent
                result = await CaculateOperandAsync(parent, variableSet);

                Console.WriteLine(result.Key + " " + result.Value);
                if (variableSet.Where(x => x.VariableName.Equals(result.Key)).FirstOrDefault() == null)
                {
                    variableSet.RegisterVariable(OperandType.Double, result.Key, result.Value);
                }
                return(variableSet);
            }
            else
            {
                result = await CaculateOperandAsync(parent, variableSet);

                Console.WriteLine(result.Key + " " + result.Value);
                if (variableSet.Where(x => x.VariableName.Equals(result.Key)).FirstOrDefault() == null)
                {
                    variableSet.RegisterVariable(OperandType.Double, result.Key, result.Value);
                }
            }
            return(variableSet);
        }
        public ActionResult <Dictionary <int, double> > AddFormula([FromBody] FormulaRequest request)
        {
            try
            {
                var            inputList = request.Operands.Where(x => x.Type == (int)OperandTypeValue.INPUT).ToList();
                List <Operand> list      = request.Operands.Where(x => x.Type != (int)OperandTypeValue.INPUT && x.OperandID == x.ID)
                                           .OrderBy(x => x.Sequence).ToList();
                var tmp = request.GroupValues.ToList();
                foreach (var item in tmp)
                {
                    var t = list.Where(x => x.Type == (int)OperandTypeValue.GROUP_VALUE && x.OperandID == item.OperandID).FirstOrDefault();
                    if (t != null)
                    {
                        list.Remove(t);
                        t.GroupValues.Add(item);
                        list.Add(t);
                    }
                }
                //parse inputed value
                VariableSet vSetBaseFormula = new VariableSet();
                var         ep = new ExpressionParser();
                foreach (var item in inputList)
                {
                    //keyValuesOperand.Add(item.Name, item.Value);
                    vSetBaseFormula.RegisterVariable(OperandType.Double, item.Name, item.Value);
                }

                //-----------------------------
                Dictionary <int, double> listResult = new Dictionary <int, double>();
                Parallel.ForEach(request.testNumber, async(item) =>
                {
                    foreach (var operand in list)
                    {
                        if (operand.Childs != null)
                        {
                            List <Operand> childs = operand.Childs.ToList();
                            if (childs.Count > 0)
                            {
                                Console.WriteLine(operand.Name + "x " + operand.Value);
                                vSetBaseFormula = await GetOperandChildsAsync(operand, vSetBaseFormula);
                            }
                            else
                            {
                                var compiledExpression = ep.Parse(operand.Expression);
                                var resultStack        = compiledExpression.Evaluate(vSetBaseFormula);
                                var tmp = Convert.ToDouble(resultStack.Pop().GetValue());
                                if (vSetBaseFormula.Where(x => x.VariableName.Equals(operand.Name)).FirstOrDefault() == null)
                                {
                                    vSetBaseFormula.RegisterVariable(OperandType.Double, operand.Name, tmp);
                                }
                            }
                        }
                    }
                    var ce = ep.Parse(request.baseFormula.Expression);
                    foreach (var param in vSetBaseFormula)
                    {
                        Console.WriteLine(param.VariableName + " " + param.Value);
                    }
                    var resul    = ce.Evaluate(vSetBaseFormula);
                    double value = Convert.ToDouble(resul.Pop().GetValue());
                    listResult.Add(item, value);
                }
                                 );
                _context.BaseFormulas.Add(request.baseFormula);
                _context.Operands.AddRange(request.Operands);
                var check = _context.SaveChanges() > 0;
                if (check)
                {
                    return(Ok(listResult));
                }
                else
                {
                    return(BadRequest("Cannot save to db"));
                }
            }
            catch (Exception e)
            {
                return(BadRequest(e.Message));
            }
        }
        public async Task <ActionResult <CalculatonResponse> > Caculate([FromBody] List <Operand> operands, int id)
        {
            //get user input
            try
            {
                List <Operand> request     = operands;
                BaseFormula    baseFormula = await _context.BaseFormulas.Where(x => x.ID == id).FirstOrDefaultAsync();

                List <Operand> operandT = await _context.Operands
                                          .Where(x => x.BaseFormulaID == id &&
                                                 x.Type != (int)OperandTypeValue.INPUT &&
                                                 x.OperandID == x.ID).ToListAsync();

                //parse inputed value
                VariableSet vSetBaseFormula = new VariableSet();
                var         ep = new ExpressionParser();
                foreach (var item in request)
                {
                    //keyValuesOperand.Add(item.Name, item.Value);
                    vSetBaseFormula.RegisterVariable(OperandType.Double, item.Name, item.Value);
                }

                //-----------------------------
                if (operandT != null)
                {
                    foreach (var item in operandT)
                    {
                        if (item.Childs != null)
                        {
                            List <Operand> childs = item.Childs.ToList();
                            if (childs.Count > 0)
                            {
                                Console.WriteLine(item.Name + "x " + item.Value);
                                vSetBaseFormula = await GetOperandChildsAsync(item, vSetBaseFormula);
                            }
                            else
                            {
                                var compiledExpression = ep.Parse(item.Expression);
                                var resultStack        = compiledExpression.Evaluate(vSetBaseFormula);
                                var tmp = Convert.ToDouble(resultStack.Pop().GetValue());
                                if (vSetBaseFormula.Where(x => x.VariableName.Equals(item.Name)).FirstOrDefault() == null)
                                {
                                    vSetBaseFormula.RegisterVariable(OperandType.Double, item.Name, tmp);
                                }
                            }
                        }
                    }
                }

                var ce = ep.Parse(baseFormula.Expression);
                foreach (var item in vSetBaseFormula)
                {
                    Console.WriteLine(item.VariableName + " " + item.Value);
                }
                var    resul = ce.Evaluate(vSetBaseFormula);
                double value = Convert.ToDouble(resul.Pop().GetValue());
                operandT.AddRange(request);
                List <Operand>     resultOp           = operandT.Where(x => x.OperandID == x.ID).ToList();
                CalculatonResponse calculatonResponse = new CalculatonResponse();
                calculatonResponse.Operands = resultOp;
                calculatonResponse.Result   = value;
                GoogleSheetData.AddEntries(baseFormula.Name);
                return(Ok(calculatonResponse));
            }
            catch (Exception e)
            {
                var response = new { Message = e.Message };
                //LogException(e);
                return(StatusCode(StatusCodes.Status500InternalServerError, response));
            }
        }