/// <summary> /// Construit une liste d'arbres de ValueObject basé sur un dimension. /// </summary> /// <param name="dicVO">Dictionnaire de ValueObject, avec les infos d'arborescence.</param> /// <param name="nomDimension">Nom de la dimension arborescente</param> /// <param name="topLvl">Niveau max (vers la racine) à parcourir</param> /// <param name="bottomLvl">Niveau min (vers les feuilles) à parcourir</param> /// <returns>Retourne un arbre des ValueObject</returns> public IEnumerable <TreeValueObject> BuildTreeVO(Dictionary <long, Tuple <ValueObject, int, string, bool> > dicVO, string nomDimension, int topLvl, int bottomLvl) { // Construction des arbres List <TreeValueObject> lstTree = new List <TreeValueObject>(); HashSet <long> idOk = new HashSet <long>(); IQueryable <ValueObject> qryVo = dicVO.Values .Select(val => val.Item1) .AsQueryable(); foreach (long idVo in dicVO.Keys) { if (idOk.Contains(idVo)) { continue; } Tuple <ValueObject, int, string, bool> elt = dicVO[idVo]; IEnumerable <Expression <Func <ValueObject, bool> > > filtres = GetFilterForTreeDimension(elt.Item1, nomDimension); List <ValueObject> lstVo = filtres.Aggregate(qryVo, (current, predicate) => current.Where(predicate)).ToList(); List <TreeValueObject> parents = null; for (int currentLvl = topLvl; currentLvl <= bottomLvl; currentLvl++) { IEnumerable <ValueObject> subVo = lstVo.Where(vo => dicVO[vo.Id].Item2 == currentLvl); List <TreeValueObject> nextParents = new List <TreeValueObject>(); foreach (ValueObject voConv in subVo) { string valueNode = dicVO[voConv.Id].Item3; TreeValueObject parent = parents?.Where(tvo => valueNode.StartsWith(tvo.TreeValue))?.FirstOrDefault(); TreeValueObject node = new TreeValueObject() { Node = voConv, TreeValue = valueNode, Parent = parent, Level = dicVO[voConv.Id].Item2 }; parent?.Children.Add(node); idOk.Add(voConv.Id); nextParents.Add(node); } parents = nextParents; if (currentLvl == topLvl) { lstTree.AddRange(nextParents); } } } return(lstTree); }
private async Task <HttpResponseMessageResult> CheckTreeSum(long referenceSequence, int ordreSequence, ConstraintLevelEnum level, SelectorInstance selectorInstance, WorkflowInstance workflowInstance) { HttpResponseMessageResult res = new HttpResponseMessageResult() { IsSuccess = true }; await ConfigVariableDomain.LoadVariables(); string nomDimension = await GetConstraintParameter(referenceSequence, ordreSequence, Constant.PARAMETER_CONSTRAINT_ALIGNMENTNAME); Dictionary <long, Tuple <ValueObject, int, string, bool> > dicVo = await ValueObjectDomain.CreateDictionaryVO(nomDimension, selectorInstance); // Construction des arbres int topLvl = dicVo.Values.Select(t => t.Item2).Min(); int bottomLvl = dicVo.Values.Select(t => t.Item2).Max(); IEnumerable <TreeValueObject> lstTree = ValueObjectDomain.BuildTreeVO(dicVo, nomDimension, topLvl, bottomLvl); // On parcours les arbres et on vérifie les valeurs HashSet <long> idsAlreadyComputed = new HashSet <long>(); //Dictionary<long, Tuple<double, double>> outOfConstraint = new Dictionary<long, Tuple<double, double>>(); Dictionary <long, object> outOfConstraint = new Dictionary <long, object>(); foreach (TreeValueObject tvo in lstTree) { string format = await ValueObjectDomain.GetNumericalFormat(tvo.Node.TypeValue, workflowInstance.DataSetId); for (int currentLvl = bottomLvl; currentLvl > topLvl; currentLvl--) { IEnumerable <TreeValueObject> nodes = TreeValueObject.GetNodesFromLevel(tvo, currentLvl); foreach (TreeValueObject child in nodes) { if ((child.Parent == null) || idsAlreadyComputed.Contains(child.Parent.Node.Id)) { continue; } double sumComputed = child.Parent.Children.Select(subnode => ValueObjectDomain.GetMostCurrentValue(subnode.Node)).Sum(); double sumParent = ValueObjectDomain.GetMostCurrentValue(child.Parent.Node); if (!ValueObjectHelper.AlmostEqual(sumComputed, sumParent, format)) { outOfConstraint.Add(child.Parent.Node.Id, new { expected = sumParent, computed = sumComputed }); } idsAlreadyComputed.Add(child.Parent.Node.Id); } } } if (outOfConstraint.Count > 0) { res.Json = JsonConvert.SerializeObject(outOfConstraint); res.Message = "Some values are not sum of their children."; if ((level == ConstraintLevelEnum.Info) || (level == ConstraintLevelEnum.Warning)) { res.IsSuccess = true; } if (level == ConstraintLevelEnum.Error) { res.IsSuccess = false; } } return(res); }
private async Task <HttpResponseMessageResult> ExecuteAggregatePrimeum(long referenceSequence, int OrderSequence, SelectorInstance selectorInstance, WorkflowInstance wfInstance) { HttpResponseMessageResult res = new HttpResponseMessageResult() { IsSuccess = true }; await ConfigVariableDomain.LoadVariables(); string nomDimension = await GetActionParameter(referenceSequence, OrderSequence, Constant.PARAMETER_ACTION_AGGREGATE_PRIMEUM_ALIGNMENTNAME); long idDimension = await GetIdDimensionTree(nomDimension, Constant.PARAMETER_ACTION_AGGREGATE_PRIMEUM_ALIGNMENTNAME, wfInstance); // niveau utiisateur CriteriaValues cvTree = await UnitOfWork.GetDbContext().CriteriaValues .Include(cv => cv.Criteria) .ThenInclude(c => c.Dimension) .Where(cv => cv.SelectorInstanceModifier != null && cv.SelectorInstanceModifier.Id == selectorInstance.Id && cv.Criteria.Dimension.Id == idDimension) .AsNoTracking() .FirstOrDefaultAsync(); string valueTopUser = cvTree?.Value; int levelTopUser = 0; if (!string.IsNullOrWhiteSpace(valueTopUser)) { levelTopUser = valueTopUser.Split(ConfigVariableDomain.AlignmentChar).Length; } Dictionary <long, Tuple <ValueObject, int, string, bool> > dicVo = await ValueObjectDomain.CreateDictionaryVO(nomDimension, selectorInstance); // Construction des arbres int topLvl = dicVo.Values.Select(t => t.Item2).Min(); int bottomLvl = dicVo.Values.Select(t => t.Item2).Max(); IEnumerable <TreeValueObject> lstTree = ValueObjectDomain.BuildTreeVO(dicVo, nomDimension, topLvl, bottomLvl); // On part du dernier niveau editable pour remonter jusqu'au niveau user. int bottom = dicVo.Values.Where(t => t.Item4).Select(t => t.Item2).Max(); HashSet <long> idsAlreadyComputed = new HashSet <long>(); HashSet <KeyValuePair <long, double> > modifiedValues = new HashSet <KeyValuePair <long, double> >(); foreach (TreeValueObject tvo in lstTree) { for (int currentLvl = bottom; currentLvl > levelTopUser; currentLvl--) { IEnumerable <TreeValueObject> nodes = TreeValueObject.GetNodesFromLevel(tvo, currentLvl); foreach (TreeValueObject child in nodes) { if ((child.Parent == null) || idsAlreadyComputed.Contains(child.Parent.Node.Id) || (child.Parent.Level <= levelTopUser)) { continue; } double sum = child.Parent.Children.Select(subnode => ValueObjectDomain.GetMostCurrentValue(subnode.Node)).Sum(); child.Parent.Node.FutureValue = sum; modifiedValues.Add(new KeyValuePair <long, double>(child.Parent.Node.Id, sum)); idsAlreadyComputed.Add(child.Parent.Node.Id); } } } // On sauve les modifications int nbr = await UnitOfWork.GetDbContext().SaveChangesAsync(); // Mise à jour de la table temporaire res.Append(await GridConfigurationDomain.SaveDataInTemporyTable(selectorInstance, wfInstance, modifiedValues)); return(res); }