public SaveMap BeforeSaveEntities(SaveMap saveMap)
        {
            var unAuthorizedMaps = saveMap.Where(map => map.Key != _tWg &&
                                                 map.Key != _tFacComment &&
                                                 map.Key != _tFacStratResp &&
                                                 map.Key != _tFacSpResp &&
                                                 map.Key != _tStudCommentFlag &&
                                                 map.Key != _tFacCommentFlag)
                                   .ToList();

            //.Select(map => map.Key);

            saveMap.RemoveMaps(unAuthorizedMaps);

            var courseMonitorEntities = saveMap.MonitorCourseMaps()?.ToList();

            //if (courseMonitorEntities != null) ProcessCourseMonitoredMaps(courseMonitorEntities);

            var workGroupMonitorEntities = saveMap.MonitorWgMaps()?.ToList();

            //if (workGroupMonitorEntities != null) ProcessWorkGroupMonitoredMaps(workGroupMonitorEntities);

            //moved processing for monitored entities to monitoredguard
            if (courseMonitorEntities != null || workGroupMonitorEntities != null)
            {
                var monitoredGuard = new MonitoredGuard(ctxManager);

                if (courseMonitorEntities != null)
                {
                    monitoredGuard.ProcessCourseMonitoredMaps(courseMonitorEntities);
                }

                if (workGroupMonitorEntities != null)
                {
                    monitoredGuard.ProcessFacultyWorkGroupMonitoredMaps(workGroupMonitorEntities);
                }
            }

            if (saveMap.ContainsKey(_tWg))
            {
                var workGroupMap = ProcessWorkGroup(saveMap[_tWg]);
                saveMap.MergeMap(workGroupMap);
            }

            if (saveMap.ContainsKey(_tFacComment))
            {
                ProcessComments(saveMap[_tFacComment]);
            }

            saveMap.AuditMap(loggedInUser.PersonId);
            saveMap.SoftDeleteMap(loggedInUser.PersonId);
            return(saveMap);
        }
        public SaveMap BeforeSaveEntities(SaveMap saveMap)
        {
            List <StudentOnTheMove> studentsPendingRemoval = new List <StudentOnTheMove>();

            if (saveMap.ContainsKey(tWg))
            {
                var grps = ProcessWorkGroup(saveMap[tWg]);
                if (grps != null)
                {
                    saveMap.MergeMap(grps);
                }

                var groups = (from info in saveMap[tWg]
                              select info.Entity as WorkGroup).ToList();

                groups.ForEach(group =>
                {
                    group.ModifiedById = loggedInUser.PersonId;
                    group.ModifiedDate = DateTime.Now;
                });
            }

            if (saveMap.ContainsKey(tStudInGroup))
            {
                var groupMembers = saveMap[tStudInGroup];

                //Need to account for adds when a new group is created.

                var studentsOnTheMove = (from info in saveMap[tStudInGroup]
                                         let sig = info.Entity as CrseStudentInGroup
                                                   where info.EntityState == EntityState.Modified
                                                   where info.OriginalValuesMap.ContainsKey("WorkGroupId")
                                                   select info).ToList();

                var unAssignedStudents = (from info in saveMap[tStudInGroup]
                                          let sig = info.Entity as CrseStudentInGroup
                                                    where info.EntityState == EntityState.Deleted
                                                    select info).ToList();


                if (unAssignedStudents.Any())
                {
                    unAssignedStudents.ForEach(uas =>
                    {
                        var studentEntity   = uas.Entity as CrseStudentInGroup;
                        var fromWorkGroupId = Int32.Parse(studentEntity.WorkGroupId.ToString());
                        //uas.EntityState = Breeze.Persistence.EntityState.Deleted;

                        var member = ctxManager.Context.StudentInGroups
                                     .Where(sig => sig.StudentId == studentEntity.StudentId)
                                     .Where(sig => sig.WorkGroupId == fromWorkGroupId)
                                     .Select(sig => new StudentOnTheMove
                        {
                            //Student = sig,
                            StudentId = sig.StudentId,
                            //IsDeleted = sig.IsDeleted,
                            IsMoving        = false,
                            FromWorkGroupId = fromWorkGroupId,
                            //CourseId = studentEntity.CourseId,
                            HasChildren = sig.AuthorOfComments.Any() ||
                                          sig.AssesseeSpResponses.Any() ||
                                          sig.AssessorSpResponses.Any() ||
                                          sig.AssesseeStratResponse.Any() ||
                                          sig.AssessorStratResponse.Any() ||
                                          sig.RecipientOfComments.Any()
                        }).ToList();

                        studentsPendingRemoval.AddRange(member);
                    });
                }

                if (studentsOnTheMove.Any())
                {
                    studentsOnTheMove.ForEach(sm =>
                    {
                        var studentEntity   = sm.Entity as CrseStudentInGroup;
                        var fromWorkGroupId = Int32.Parse(sm.OriginalValuesMap["WorkGroupId"].ToString());

                        var member = ctxManager.Context.StudentInGroups
                                     .Where(sig => sig.StudentId == studentEntity.StudentId)
                                     .Where(sig => sig.WorkGroupId == fromWorkGroupId)
                                     .Select(sig => new StudentOnTheMove
                        {
                            Student         = sig,
                            StudentId       = sig.StudentId,
                            IsDeleted       = sig.IsDeleted,
                            IsMoving        = true,
                            ToWorkGroupId   = studentEntity.WorkGroupId,
                            FromWorkGroupId = fromWorkGroupId,
                            CourseId        = studentEntity.CourseId,
                            HasChildren     = sig.AuthorOfComments.Any() ||
                                              sig.AssesseeSpResponses.Any() ||
                                              sig.AssessorSpResponses.Any() ||
                                              sig.AssesseeStratResponse.Any() ||
                                              sig.AssessorStratResponse.Any() ||
                                              sig.RecipientOfComments.Any() ||
                                              sig.FacultySpResponses.Any() ||
                                              sig.FacultyStrat != null ||
                                              sig.FacultyComment != null
                        }).ToList();

                        studentsPendingRemoval.AddRange(member);
                    });
                }

                var studentsPendingRemovalWithChildren = studentsPendingRemoval
                                                         .Where(spr => spr.HasChildren).ToList();

                var studentsPendingRemovalWithoutChildren = studentsPendingRemoval
                                                            .Where(spr => !spr.HasChildren).ToList();


                if (studentsPendingRemovalWithChildren.Any())
                {
                    studentsPendingRemovalWithChildren.ForEach(sprwc =>
                    {
                        //if (sprwc.IsMoving)
                        //{
                        var authorCommentFlags = ctxManager.Context.StudSpCommentFlags
                                                 .Where(sscf => sscf.AuthorPersonId == sprwc.StudentId)
                                                 .Where(sscf => sscf.WorkGroupId == sprwc.FromWorkGroupId);

                        var recipientCommentFlags = ctxManager.Context.StudSpCommentFlags
                                                    .Where(sscf => sscf.RecipientPersonId == sprwc.StudentId)
                                                    .Where(sscf => sscf.WorkGroupId == sprwc.FromWorkGroupId);

                        var authorOfComments = ctxManager.Context.StudSpComments
                                               .Where(ssc => ssc.AuthorPersonId == sprwc.StudentId)
                                               .Where(ssc => ssc.WorkGroupId == sprwc.FromWorkGroupId);

                        var recipientOfComments = ctxManager.Context.StudSpComments
                                                  .Where(ssc => ssc.RecipientPersonId == sprwc.StudentId)
                                                  .Where(ssc => ssc.WorkGroupId == sprwc.FromWorkGroupId);

                        var assesseeSpResponses = ctxManager.Context.SpResponses
                                                  .Where(sr => sr.AssesseePersonId == sprwc.StudentId)
                                                  .Where(sr => sr.WorkGroupId == sprwc.FromWorkGroupId);

                        var assessorSpResponses = ctxManager.Context.SpResponses
                                                  .Where(sr => sr.AssessorPersonId == sprwc.StudentId)
                                                  .Where(sr => sr.WorkGroupId == sprwc.FromWorkGroupId);

                        var assesseeStratResponses = ctxManager.Context.SpStratResponses
                                                     .Where(ssr => ssr.AssesseePersonId == sprwc.StudentId)
                                                     .Where(ssr => ssr.WorkGroupId == sprwc.FromWorkGroupId);

                        var assessorStratResponses = ctxManager.Context.SpStratResponses
                                                     .Where(ssr => ssr.AssessorPersonId == sprwc.StudentId)
                                                     .Where(ssr => ssr.WorkGroupId == sprwc.FromWorkGroupId);

                        var facSpResponses = ctxManager.Context.FacSpResponses
                                             .Where(fsr => fsr.AssesseePersonId == sprwc.StudentId)
                                             .Where(fsr => fsr.WorkGroupId == sprwc.FromWorkGroupId);

                        var facStratResponse = ctxManager.Context.FacStratResponses
                                               .Where(fsr => fsr.AssesseePersonId == sprwc.StudentId)
                                               .Where(fsr => fsr.WorkGroupId == sprwc.FromWorkGroupId);

                        var facComments = ctxManager.Context.FacSpComments
                                          .Where(fsc => fsc.RecipientPersonId == sprwc.StudentId)
                                          .Where(fsc => fsc.WorkGroupId == sprwc.FromWorkGroupId);

                        var facCommentsFlag = ctxManager.Context.FacSpCommentFlags
                                              .Where(fscf => fscf.RecipientPersonId == sprwc.StudentId)
                                              .Where(fscf => fscf.WorkGroupId == sprwc.FromWorkGroupId);



                        if (authorOfComments.Any())
                        {
                            if (authorCommentFlags.Any())
                            {
                                ctxManager.Context.StudSpCommentFlags.RemoveRange(authorCommentFlags);
                            }

                            ctxManager.Context.StudSpComments.RemoveRange(authorOfComments);
                        }

                        if (recipientOfComments.Any())
                        {
                            if (recipientCommentFlags.Any())
                            {
                                ctxManager.Context.StudSpCommentFlags.RemoveRange(recipientCommentFlags);
                            }
                            ctxManager.Context.StudSpComments.RemoveRange(recipientOfComments);
                        }

                        if (assesseeSpResponses.Any())
                        {
                            ctxManager.Context.SpResponses.RemoveRange(assesseeSpResponses);
                        }

                        if (assessorSpResponses.Any())
                        {
                            ctxManager.Context.SpResponses.RemoveRange(assessorSpResponses);
                        }

                        if (assesseeStratResponses.Any())
                        {
                            ctxManager.Context.SpStratResponses.RemoveRange(assesseeStratResponses);
                        }

                        if (assessorStratResponses.Any())
                        {
                            ctxManager.Context.SpStratResponses.RemoveRange(assessorStratResponses);
                        }

                        if (facSpResponses.Any())
                        {
                            ctxManager.Context.FacSpResponses.RemoveRange(facSpResponses);
                        }

                        if (facStratResponse.Any())
                        {
                            ctxManager.Context.FacStratResponses.RemoveRange(facStratResponse);
                        }

                        if (facComments.Any())
                        {
                            ctxManager.Context.FacSpComments.RemoveRange(facComments);
                        }

                        if (facCommentsFlag.Any())
                        {
                            ctxManager.Context.FacSpCommentFlags.RemoveRange(facCommentsFlag);
                        }


                        //}

                        if (sprwc.IsMoving)
                        {
                            ctxManager.Context.StudentInGroups.Remove(sprwc.Student);
                        }
                    });

                    ctxManager.Context.SaveChanges();
                }

                if (studentsPendingRemovalWithoutChildren.Any())
                {
                    studentsPendingRemovalWithoutChildren.ForEach(sprwoc =>
                    {
                        if (sprwoc.IsMoving)
                        {
                            ctxManager.Context.StudentInGroups.Remove(sprwoc.Student);
                            ctxManager.Context.SaveChanges();
                        }

                        //ctxManager.Context.Entry(sprwoc.Student).State = System.Data.Entity.EntityState.Deleted;
                    });

                    //ctxManager.Context.SaveChanges();
                }

                var studentsToBeAddedBack = studentsPendingRemoval
                                            .Where(spr => spr.IsMoving).ToList();

                ////Students that were previously deleted with children.
                studentsOnTheMove.ForEach(info => saveMap.Remove(tStudInGroup));

                if (studentsToBeAddedBack.Any())
                {
                    List <EntityInfo> toAddInfos;
                    toAddInfos = new List <EntityInfo>();


                    studentsToBeAddedBack.ForEach(stab =>
                    {
                        var toAdd = new CrseStudentInGroup
                        {
                            StudentId       = stab.StudentId,
                            CourseId        = stab.CourseId,
                            WorkGroupId     = stab.ToWorkGroupId,
                            HasAcknowledged = false,
                            IsDeleted       = false,
                            ModifiedById    = loggedInUser.PersonId,
                            ModifiedDate    = DateTime.Now
                        };

                        var toAddEi = ctxManager.CreateEntityInfo(toAdd);
                        toAddInfos.Add(toAddEi);
                    });

                    saveMap.Add(tStudInGroup, toAddInfos);
                }
            }

            return(saveMap);
        }
        public static SaveMap Publish(SaveMap wgSaveMap, IEnumerable <int> svrWgIds, int loggedInPersonId,
                                      EFContextProvider <EcatContext> ctxProvider)
        {
            var infos = wgSaveMap.Single(map => map.Key == tWg).Value;

            var pubWgs = GetPublishingWgData(svrWgIds, ctxProvider);

            if (pubWgs == null)
            {
                var errorMessage = "The database did not return a publishable workgroup.";
                var error        = infos.Select(
                    info => new EFEntityError(info, "Publication Error", errorMessage, "MpSpStatus"));
                throw new EntityErrorsException(error);
            }

            if (pubWgs.Count() < svrWgIds.Count())
            {
                var missingGrps = pubWgs.Where(wg => {
                    if (svrWgIds.Contains(wg.Id))
                    {
                        return(false);
                    }
                    return(true);
                });

                var errorMessage = "Some groups were found to be unpublishable";
                var error        = infos.Select(
                    info => new EFEntityError(info, "Publication Error", errorMessage, "MpSpStatus"));
                throw new EntityErrorsException(error);
            }

            foreach (var wg in pubWgs)
            {
                var stratScoreInterval = 1m / wg.PubWgMembers.Count();
                stratScoreInterval = decimal.Round(stratScoreInterval, 4);
                var stratKeeper   = new List <PubWgMember>();
                var countOfGrp    = wg.PubWgMembers.Count();
                var totalStratPos = 0;
                for (var i = 1; i <= countOfGrp; i++)
                {
                    totalStratPos += i;
                }

                foreach (var me in wg.PubWgMembers)
                {
                    var stratSum = me.PubStratResponses.Sum(strat => strat.StratPosition);
                    stratSum += me.SelfStratPosition;

                    if (me.PeersDidNotAssessMe.Any() || me.PeersIdidNotAssess.Any() || me.PeersDidNotStratMe.Any() ||
                        me.PeersIdidNotStrat.Any() || me.FacStratPosition == 0 || stratSum != totalStratPos)
                    {
                        var errorMessage =
                            $"There was a problem validating necessary information . Problem Flags Are: [Them => Me] NA: !{me.PeersDidNotAssessMe.Count()}, NS: {me.PeersDidNotStratMe.Any()} | [Me => Them] NA: {me.PeersIdidNotAssess.Count()}, NS: {me.PeersIdidNotStrat.Any()} | FacStrat: {me.FacStratPosition}";

                        var error = infos.Select(
                            info => new EFEntityError(info, "Publication Error", errorMessage, "MpSpStatus"));
                        throw new EntityErrorsException(error);
                    }
                    var peerCount   = countOfGrp - 1;
                    var resultScore = ((decimal)me.SpResponseTotalScore / (me.CountSpResponses * 6)) * 100;
                    var spResult    = new SpResult
                    {
                        CourseId             = wg.CourseId,
                        WorkGroupId          = wg.Id,
                        StudentId            = me.StudentId,
                        AssignedInstrumentId = wg.InstrumentId,
                        CompositeScore       = (int)resultScore,
                        BreakOut             = new SpResultBreakOut
                        {
                            NotDisplay = me.BreakOut.NotDisplayed,
                            IneffA     = me.BreakOut.IneffA,
                            IneffU     = me.BreakOut.IneffU,
                            EffA       = me.BreakOut.EffA,
                            EffU       = me.BreakOut.EffU,
                            HighEffA   = me.BreakOut.HighEffA,
                            HighEffU   = me.BreakOut.HighEffU
                        },
                        MpAssessResult = ConvertScoreToOutcome((int)resultScore),
                    };

                    var resultInfo = ctxProvider.CreateEntityInfo(spResult,
                                                                  me.HasSpResult ? EntityState.Modified : EntityState.Added);

                    resultInfo.ForceUpdate = me.HasSpResult;

                    if (!wgSaveMap.ContainsKey(tSpResult))
                    {
                        wgSaveMap[tSpResult] = new List <EntityInfo> {
                            resultInfo
                        };
                    }
                    else
                    {
                        wgSaveMap[tSpResult].Add(resultInfo);
                    }

                    var stratResult = new StratResult
                    {
                        CourseId       = wg.CourseId,
                        StudentId      = me.StudentId,
                        WorkGroupId    = wg.Id,
                        ModifiedById   = loggedInPersonId,
                        ModifiedDate   = DateTime.Now,
                        StratCummScore = decimal.Round(me.StratTable.Select(strat =>
                        {
                            var multipler = 1 - (strat.Position - 1) * stratScoreInterval;
                            return(multipler * strat.Count);
                        }).Sum(), 4)
                    };

                    me.StratResult = stratResult;
                    stratKeeper.Add(me);
                }

                var cummScores = new List <decimal>();
                var oi         = 1;

                foreach (var strat in stratKeeper.OrderByDescending(sk => sk.StratResult.StratCummScore))
                {
                    if (cummScores.Contains(strat.StratResult.StratCummScore) || !cummScores.Any())
                    {
                        strat.StratResult.OriginalStratPosition = oi;
                        cummScores.Add(strat.StratResult.StratCummScore);
                        continue;
                    }
                    ;
                    cummScores.Add(strat.StratResult.StratCummScore);

                    oi += 1;
                    strat.StratResult.OriginalStratPosition = oi;
                }

                var fi          = 0;
                var spInterval  = wg.WgSpTopStrat / wg.StratDivisor;
                var facInterval = wg.WgFacTopStrat / wg.StratDivisor;


                foreach (
                    var gm in
                    stratKeeper.OrderByDescending(sk => sk.StratResult.StratCummScore)
                    .ThenBy(sk => sk.FacStratPosition))
                {
                    var studAwardedPoints = Math.Max(0, wg.WgSpTopStrat - spInterval * fi);
                    var instrAwardPoints  = Math.Max(0, wg.WgFacTopStrat - (facInterval * (gm.FacStratPosition - 1)));

                    //var totalAward = studAwardedPoints + instrAwardPoints;

                    gm.StratResult.StudStratAwardedScore = studAwardedPoints;
                    gm.StratResult.FacStratAwardedScore  = instrAwardPoints;
                    gm.StratResult.FinalStratPosition    = fi + 1;

                    var info = ctxProvider.CreateEntityInfo(gm.StratResult,
                                                            gm.HasStratResult ? EntityState.Modified : EntityState.Added);
                    info.ForceUpdate = gm.HasStratResult;

                    if (!wgSaveMap.ContainsKey(tStratResult))
                    {
                        wgSaveMap[tStratResult] = new List <EntityInfo> {
                            info
                        };
                    }
                    else
                    {
                        wgSaveMap[tStratResult].Add(info);
                    }

                    fi += 1;
                }
            }
            return(wgSaveMap);
        }
        public SaveMap BeforeSaveEntities(SaveMap saveMap)
        {
            var unAuthorizedMaps = saveMap.Where(map => map.Key != tStudComment &&
                                                 map.Key != tSpResponse &&
                                                 map.Key != tStudInGroup &&
                                                 map.Key != tStratResponse &&
                                                 map.Key != tStudCommentFlag)
                                   .ToList();

            saveMap.RemoveMaps(unAuthorizedMaps);

            //Process any monitored entities to see if saves are allowed.
            var courseMonitorEntities    = saveMap.MonitorCourseMaps()?.ToList();
            var workGroupMonitorEntities = saveMap.MonitorWgMaps()?.ToList();

            if (courseMonitorEntities != null || workGroupMonitorEntities != null)
            {
                var monitorGuard = new MonitoredGuard(ctxManager);
                if (courseMonitorEntities != null)
                {
                    monitorGuard.ProcessCourseMonitoredMaps(courseMonitorEntities);
                }
                if (workGroupMonitorEntities != null)
                {
                    monitorGuard.ProcessStudentWorkGroupMonitoredMaps(workGroupMonitorEntities);
                }
            }

            //Process studInGroup to ensure that only the logged student' is being handled.
            if (saveMap.ContainsKey(tStudInGroup))
            {
                var infos = (from info in saveMap[tStudInGroup]
                             let sig = info.Entity as CrseStudentInGroup
                                       where sig != null && sig.StudentId == loggedInUserId
                                       where info.EntityState == EntityState.Modified
                                       where info.OriginalValuesMap.ContainsKey("HasAcknowledged")
                                       select info).ToList();

                if (infos.Any())
                {
                    foreach (var info in infos)
                    {
                        info.OriginalValuesMap = new Dictionary <string, object>()
                        {
                            { "HasAcknowledged", null }
                        };
                    }

                    saveMap[tStudInGroup] = infos;
                }
                else
                {
                    saveMap.Remove(tStudInGroup);
                }
            }

            if (saveMap.ContainsKey(tStudComment))
            {
                var newComments = saveMap[tStudComment]
                                  .Where(info => info.EntityState == EntityState.Added)
                                  .Select(info => info.Entity)
                                  .OfType <StudSpComment>()
                                  .ToList();

                foreach (var comment in newComments)
                {
                    comment.CreatedDate = DateTime.UtcNow;
                }
            }

            saveMap.AuditMap(loggedInUserId);
            saveMap.SoftDeleteMap(loggedInUserId);
            return(saveMap);
        }