예제 #1
0
        public async Task <IActionResult> Post(IFormFile file)
        {
            if (file.Length == 0)
            {
                return(BadRequest("No file selected!"));
            }

            var content = "";

            using (StreamReader sr = new StreamReader(file.OpenReadStream()))
            {
                content = await sr.ReadToEndAsync();
            }

            IEnumerable <Input> inputCollection = content.DeserializeCsv(", ", "\r\n");

            IEnumerable <IGrouping <int, ProjectGroup> > projects =
                from input in inputCollection
                group new ProjectGroup {
                EmployeeId = input.EmployeeId, DateFrom = input.DateFrom, DateTo = input.DateTo
            }
            by input.ProjectId into projGroup
            where projGroup.Count() > 1     //take only projects where we have more than one person working.
            select projGroup;

            /*Here we build a map between the key (employee1_employee2) and another dictionary mapping projects to days working together.
             */
            Dictionary <string, Dictionary <int, int> > dict = new Dictionary <string, Dictionary <int, int> >();

            //Go through each project group.
            foreach (var group in projects)
            {
                for (var i = 0; i < group.Count(); i++)
                {
                    int projectId;
                    int empA;
                    int empB;

                    //Check if each user`s TimeSpan is intersecting his colleagues TimeSpan.
                    for (var j = i + 1; j < group.Count(); j++)
                    {
                        bool isIntersecting = Calculate.IsIntersecting(
                            group.ElementAt(i).DateFrom,
                            group.ElementAt(i).DateTo,
                            group.ElementAt(j).DateFrom,
                            group.ElementAt(j).DateTo
                            );

                        if (isIntersecting)
                        {
                            //If we have intersection, calculate the days and reevalute the max days period.
                            int days = Calculate.IntersectionDays(
                                group.ElementAt(i).DateFrom,
                                group.ElementAt(i).DateTo,
                                group.ElementAt(j).DateFrom,
                                group.ElementAt(j).DateTo
                                );

                            empA      = group.ElementAt(i).EmployeeId;
                            empB      = group.ElementAt(j).EmployeeId;
                            projectId = group.Key;

                            string key = $"{empA}_{empB}";

                            //Filling the dictionary.
                            if (!dict.ContainsKey(key))
                            {
                                Dictionary <int, int> projectDict = new Dictionary <int, int>();
                                projectDict.Add(projectId, days);
                                dict.Add(key, projectDict);
                            }
                            else
                            {
                                //Check if we already have the project on the dictionary.
                                if (!dict[key].Keys.Contains(projectId))
                                {
                                    dict[key].Add(projectId, days);
                                }
                                else
                                {
                                    //Summing all days working together on that specific project.
                                    dict[key][projectId] += days;
                                }
                            }
                        }
                    }
                }
            }

            string bestDuoKey = "";
            int    maxDays    = 0;

            foreach (KeyValuePair <string, Dictionary <int, int> > kv in dict)
            {
                //summing all the days spent per project to get the total days each pair`s been working together.
                int totalDaysOnProjects = kv.Value.Aggregate(0, (acc, next) => {
                    acc += next.Value;
                    return(acc);
                });

                //getting the max of all and assigning the winning pair.
                if (totalDaysOnProjects > maxDays)
                {
                    maxDays    = totalDaysOnProjects;
                    bestDuoKey = kv.Key;
                }
            }

            //Splitting the key to get employee 1 and 2.
            string[] employees = bestDuoKey.Split("_");

            List <ResultView> projectsResult = new List <ResultView>();

            //Go through all projects of the employee pair and prepare the result.
            foreach (KeyValuePair <int, int> projectDays in dict[bestDuoKey])
            {
                ResultView rv = new ResultView
                {
                    EmployeeIdA   = int.Parse(employees[0]),
                    EmployeeIdB   = int.Parse(employees[1]),
                    ProjectId     = projectDays.Key,
                    DaysOnProject = projectDays.Value
                };

                //Logging to console as well.
                Console.WriteLine(rv.ToString() + "\r\n-----------------");

                projectsResult.Add(rv);
            }

            return(new JsonResult(projectsResult));
        }