2 * Calculate progress percentage (0 <= integer <= 100) of a certain process
3 * that involves carrying out several tasks, that can either fail or be successful
4 * @param successful Number of tasks completed successfully
5 * @param failed Number of tasks that failed
6 * @param total Total number of tasks
8 export const percentageProgress = (successful: number, failed: number, total: number) => {
10 // assume the process has not started
13 // in case successful + failed > total, do not allow progress > 100
14 return Math.min(Math.floor(((+successful + failed) / total) * 100), 100);
18 * Combine progresses of several processes with predefined allocation percentages
19 * @param processes Processes to be combined. Format: { allocated, successful, failed, total}
20 * @param processes.allocated Allocated percentage for a process. E.g. 0.25
22 * @return Combined progrees
24 export const combineProgress = (
25 processes: { allocated: number; successful: number; failed: number; total: number }[] = []
27 const { combinedTotal, combinedAllocations, progresses } = processes.reduce<{
28 combinedTotal: number;
29 combinedAllocations: number;
32 (acc, { allocated, successful, failed, total }) => {
33 acc.combinedTotal += total;
34 acc.combinedAllocations += allocated;
35 acc.progresses.push(percentageProgress(successful, failed, total));
38 { combinedTotal: 0, combinedAllocations: 0, progresses: [] }
40 if (combinedAllocations !== 1 && !!processes.length) {
41 throw new Error('Allocations must add up to one');
46 const combinedProgress = processes.reduce((acc, { allocated, total }, i) => {
47 // set progress to 100 if there are no tasks to be performed for this process,
48 // but there are tasks in other processes
49 const progress = allocated * (!total && !!combinedTotal ? 100 : progresses[i]);
50 return acc + progress;
53 return Math.round(combinedProgress);