private double ComputeRatio(BuildEntity buildEntity, ReportingContext context)
        {
            var currentProject = context.Projects.FirstOrDefault(i => i.Name == buildEntity.Definition);
            if (currentProject == null)
            {
                currentProject = new ProjectEntity { Name = buildEntity.Definition };
                context.Projects.Add(currentProject);
            }
            if (!buildEntity.CoverageCollection.Any())
                return 0;

            var currentProjectBlock = buildEntity.CoverageCollection.Sum(i => i.BlocksCovered + i.BlocksNotCovered);
            currentProject.Blocks = currentProjectBlock;

            if (!context.Projects.Any())
                return 1;

            var maxBlock = context.Projects.Max(i => i.Blocks);
            var maxProject = context.Projects.FirstOrDefault(i => i.Blocks == maxBlock);
            if (maxProject == null || maxBlock == 0)
                return 1; // Ratio = 1 : no project to be compared.

            if (maxProject.Id == currentProject.Id)
                return 1; // current projet is the bigest project.

            return (double)currentProjectBlock / maxBlock;
        }
        private double ComputeBuildCoverage(BuildEntity build)
        {
            if (build.CoverageCollection == null)
                return 0;

            var covered = build.CoverageCollection.Sum(i => i.BlocksCovered);
            var notCovered = build.CoverageCollection.Sum(i => i.BlocksNotCovered);

            return ((Double)covered * 100) / (notCovered + covered);
        }
        public async Task<IHttpActionResult> Post([FromBody] HttpHookBuild build)
        {
            var knowDefinitionsBuilds = ConfigurationManager.AppSettings["ExpectedBuilds"].Split('|').Where(i => !string.IsNullOrEmpty(i)).ToArray();
            if (knowDefinitionsBuilds.Any() && !knowDefinitionsBuilds.Contains(build.resource.definition.name))
                return Ok();

            try
            {
                using (var context = new ReportingContext())
                {
                    var request = build.resource.requests.FirstOrDefault();

                    var buildEntity = new BuildEntity
                    {
                        BuildName = build.resource.buildNumber,
                        Definition = build.resource.definition.name,
                        Date = build.resource.finishTime,
                        Status = build.resource.status,
                        Reason = build.resource.reason,
                        Link = build.message.html,
                        User = request != null ? request.requestedFor.uniqueName : "Unknown user",
                        CoverageCollection = new Collection<CoverageEntity>()
                    };

                    if (buildEntity.User == "Project Collection Service Accounts")
                        buildEntity.User = "******";

                    if (buildEntity.User == ConfigurationManager.AppSettings["VsoUsername"])
                        return Ok();

                    if (string.IsNullOrEmpty(ConfigurationManager.AppSettings["VSO.OrganisationName"]) || string.IsNullOrEmpty(ConfigurationManager.AppSettings["VSO.ProjectName"]))
                        throw new ApplicationException("Please configuration VSO.OrganisationName and VSO.ProjectName first.");

                    var api = new ApiWrapper(ConfigurationManager.AppSettings["VSO.OrganisationName"], ConfigurationManager.AppSettings["VSO.ProjectName"]);
                    var coverage = await api.GetBuildCoverageAsync(build);
                    if (coverage != null)
                    {
                        foreach (var moduleCoverage in coverage)
                        {
                            buildEntity.CoverageCollection.Add(new CoverageEntity
                            {
                                Name = moduleCoverage.Name,
                                ComputedAverage = moduleCoverage.ComputedAverage,
                                BlocksCovered = moduleCoverage.BlocksCovered,
                                BlocksNotCovered = moduleCoverage.BlocksNotCovered,
                                Build = buildEntity
                            });
                        }
                    }

                    double currentRatio = ComputeRatio(buildEntity, context);
                    var challenge = ComputeCoverageChanges(buildEntity, context, currentRatio);
                    if (challenge != null)
                        context.Challenges.Add(challenge);

                    context.Builds.Add(buildEntity);
                    context.SaveChanges();
                }

                return Ok();
            }
            catch (Exception e)
            {
                return BadRequest(e.Message);
            }
        }
        private ChallengeEntity ComputeCoverageChanges(BuildEntity buildEntity, ReportingContext context, double currentRatio)
        {
            if (buildEntity.Status != "succeeded")
                return null;

            var previousBuild = context.Builds
                .OrderByDescending(i => i.Date)
                .FirstOrDefault(i => i.Definition == buildEntity.Definition && i.Status == "succeeded" && i.CoverageCollection.Any());

            if (previousBuild == null)
                return null;

            var challenge = new ChallengeEntity
            {
                User = buildEntity.User,
                Build = buildEntity,
                ModuleCoverages = new List<ModuleChallengeCoverage>()
            };

            var allModules = previousBuild.CoverageCollection.Select(i => i.Name).Union(buildEntity.CoverageCollection.Select(i => i.Name));
            foreach (var moduleName in allModules)
            {
                var currentModuleName = moduleName;

                var previousModule = previousBuild.CoverageCollection.FirstOrDefault(i => i.Name == currentModuleName);
                var currentModule = buildEntity.CoverageCollection.FirstOrDefault(i => i.Name == currentModuleName);

                if (currentModule != null && previousModule != null && (previousModule.BlocksCovered == currentModule.BlocksCovered && previousModule.BlocksNotCovered == currentModule.BlocksNotCovered))
                    continue; // Ignore if no change in the module.
                if (currentModule == null)
                    continue;

                var previousModuleCoverage = ComputeBuildCoverage(previousModule);
                var currentModuleCoverage = ComputeBuildCoverage(currentModule);

                var deltaCoverage = currentModuleCoverage - previousModuleCoverage;
                var allBlocks = currentModule.BlocksCovered + currentModule.BlocksNotCovered;

                challenge.ModuleCoverages.Add(new ModuleChallengeCoverage { Module = currentModuleName, DeltaCoverage = deltaCoverage, Blocks = allBlocks });
            }

            var previousProjectCoverage = ComputeBuildCoverage(previousBuild);
            var currentProjectCoverage = ComputeBuildCoverage(buildEntity);
            challenge.Points = (currentProjectCoverage - previousProjectCoverage) * 100 * currentRatio;
            if (double.IsNaN(challenge.Points))
                challenge.Points = 0;

            return challenge;
        }