import { Task, TaskCategory, TaskCategoryID } from "../models/task"; import { Project } from "../models/project"; import { TaskCategoriesTableProps } from "../routes/project/task-categories-table"; import { Estimation } from "../hooks/use-project-estimations"; import { getTaskCategoryCost } from "../models/params"; export function getTaskWeightedMean(t: Task): number { return (t.estimations.optimistic + (4*t.estimations.likely) + t.estimations.pessimistic) / 6; } export function getTaskStandardDeviation(t: Task): number { return (t.estimations.pessimistic - t.estimations.optimistic) / 6; } export function getProjectWeightedMean(p : Project): number { return Object.values(p.tasks).reduce((sum: number, t: Task) => { sum += getTaskWeightedMean(t); return sum; }, 0); } export function getTaskCategoryWeightedMean(taskCategoryId: TaskCategoryID, p : Project): number { return Object.values(p.tasks).filter(t => t.category === taskCategoryId).reduce((sum: number, t: Task) => { sum += getTaskWeightedMean(t); return sum; }, 0); } export function getProjectStandardDeviation(p : Project): number { return Math.sqrt(Object.values(p.tasks).reduce((sum: number, t: Task) => { sum += Math.pow(getTaskStandardDeviation(t), 2); return sum; }, 0)); } export interface MeanRepartition { [id: string]: number } export function getTaskCategoriesMeanRepartition(project: Project): MeanRepartition { let projectMean = getProjectWeightedMean(project); const repartition: MeanRepartition = {}; Object.values(project.params.taskCategories).forEach(tc => { repartition[tc.id] = getTaskCategoryWeightedMean(tc.id, project) / projectMean; if (Number.isNaN(repartition[tc.id])) repartition[tc.id] = 0; }); return repartition; } export interface MinMaxCost { max: Cost min: Cost } export interface Cost { totalCost: number totalTime: number details: { [taskCategoryId: string]: { time: number, cost: number } } } export function getMinMaxCosts(project: Project, estimation: Estimation): MinMaxCost { const max: Cost = {totalCost: 0, totalTime: 0, details: {}}; const min: Cost = {totalCost: 0, totalTime: 0, details: {}}; const repartition = getTaskCategoriesMeanRepartition(project); Object.values(project.params.taskCategories).forEach(tc => { const cost = getTaskCategoryCost(tc); const maxTime = Math.round((estimation.e + estimation.sd) * repartition[tc.id]); max.details[tc.id] = { time: maxTime, cost: Math.ceil(maxTime) * cost, }; max.totalTime += max.details[tc.id].time; max.totalCost += max.details[tc.id].cost; const minTime = Math.round((estimation.e - estimation.sd) * repartition[tc.id]); min.details[tc.id] = { time: minTime, cost: Math.ceil(minTime) * cost, }; min.totalTime += min.details[tc.id].time; min.totalCost += min.details[tc.id].cost; }); return { max, min }; }