Package: dumbpm
dumbpmInstallationPrioritize projectsProjects formatExampleEstimate project duration without historical dataInput formatExampleEstimate project duration based on historical dataInput formatExampleA pretty dumb PM.The whole philosophy behinddumbpmis that PMs (project managers, program managers, product managers, people managers, pokemon masters, etc.) all do some tasks that could use some automation, but at the same time this automation should be as dumb as possible. There are so many changing factors that influence such tasks that you better hire a PM (or a team of researchers to do the automation) to do the clever stuff, not a random software on the internet. In addition, if we keep it dumb, people can just read the code and understand what is going on, if they really want to.If you have any suggestions for something (but nothing clever!) that you would likedumbpmto do for you, open an issue and let me know.Installationpip install dumbpmTested on both Linux and Mac OS. Windowsmightwork.NOTEPython 3.9+ required.Prioritize projectsGiving a table of projects defined as below, it outputs a list of projects in order of priority within the optionally specified budget (prioritization as "data problem").The prioritized list is modelled as the exact solution of aKnapsack Problemwith the following value function:norm(value) / (norm(cost) + norm(duration) + norm(risk)). Pretty dumb, indeed.If--budgetisn't specified, the list will simply be sorted by the result of the above value function. Budget is relative to thecostparameter.If you are expressingcostas cost per unit of duration (e.g. developers per week or sprint), you'll have to specify the--cost-per-durationoption, so thattotal cost = cost * durationandbudgetis measured againsttotal cost(durationwill also disappear from the value function not to count it twice).By setting thepickparameter you can also "cheat" and tell the solver to always include a project in the solution. This can be useful if you want to see how the solution would change based on that choice.$dumbpmprioritize--help
usage:dumbpmprioritize[-h][--budget[BUDGET]]filename

positionalarguments:filenameCSVfilewithprojectsdefinition

optionalarguments:-h,--helpshowthishelpmessageandexit--budget[BUDGET]Maxbudgetallowed--cost-per-durationCostistobeassumedperunitofduration.Budget=(cost*duration)Projects formatProject definition happens in a CSV file with the following structure:Project: [required] name of the projectValue: [required] value of the projectCost: [required] cost of the projectDuration: [optional] duration of the project expressed in unit of timesRisk: [optional] risk of failure of the projectPick: [optional, default = FALSE] force the inclusion of the projectAlternatives: [optional, empty field = empty list] comma separated list of projects that are incompatible with this one (e.g. make lunch vs buy lunch)There is a bit of slack on the headers of the columns (e.g.Project,Projects,project, etc. are all alright). Notable mentions:altsandalternativeswork the same;PQcan be used instead ofcostif that's your thing.ProjectValueCostDurationRiskPickAlternativesBuy a better espresso machine5421TRUEBuy ambient parfume for the back1111Find and remove source of bad smell5244TRUEFind better coffee vendors4263Buy smart component for roaster3523Build in-house roasting notification systemIntroduce a periodical suggestion survey for treats3261Buy a more modern sign3311Contact a designer to re-think the front5563Buy beds for powernaps1311Import treats from France2422Build in-house roasting notification system3565Buy smart component for roasterExample$ cat projects.csv
Project,Value,Cost,Duration,Pick,Alternatives
Buy a better espresso machine,5,4,2,TRUE,
Buy ambient parfume for the back,1,1,1,,
Find and remove source of bad smell,5,2,4,TRUE,
Find better coffee vendors,4,2,6,,
Buy smart component for roaster,3,5,2,,Build in-house roasting notification system
Introduce a periodical suggestion survey for treats,3,2,6,,
Buy a more modern sign,3,3,1,,
Contact a designer to re-think the front,5,5,6,,
Buy beds for powernaps,1,3,1,,
Import treats from France,2,4,2,,
Build in-house roasting notification system,3,5,6,,Buy smart component for roaster

$ dumbpm prioritize projects.csv
01 Buy ambient parfume for the back
02 Buy a more modern sign
03 Find and remove source of bad smell
04 Buy a better espresso machine
05 Find better coffee vendors
06 Buy beds for powernaps
07 Buy smart component for roaster
08 Import treats from France
09 Introduce a periodical suggestion survey for treats
10 Contact a designer to re-think the front

$ dumbpm prioritize projects.csv --budget 10
01 Buy ambient parfume for the back
02 Buy a more modern sign
03 Find and remove source of bad smell
04 Buy a better espresso machineEstimate project duration without historical dataGiving a list of tasks or milestones the project can be broken into and (best case, expected, worst case) estimates for the duration of such tasks, it outputs an estimate of the project duration in the form of a probability distribution (median, variance, percentiles). You can use these numbers to formulate guesstimates like "I am 75% confident that we will complete the project in 38 weeks". Instead of using a unit of time (e.g. days, weeks), you can instead specify story points for each tasks and so estimate the project size in story point instead of its duration.The estimation is based on aMonte Carlo simulationof the following equation:project_duration = sum(duration, over=tasks). Tasks duration for each iteration are derived from amodified-PERT distributioninterpolating the (best case, expected, worst case) estimates for the task. Pretty dumb, indeed.The command is calledguesstimateto highlight that the result of this method should be considered with lower confidence than the one produced by theestimatecommand, which is based on historical data. You can switch toestimateafter you conclude a few sprints, while relying onguesstimatefor the initial estimates during the planning period.If it is taking too long to perform the estimation on your computer, set--simulationsto something lower than10000.$dumbpmguesstimate--help
usage:dumbpmguesstimate[-h][--simulations[SIMULATIONS]]filename

positionalarguments:filenameCSVfilewithtasksestimates

optionalarguments:-h,--helpshowthishelpmessageandexit--simulations[SIMULATIONS]NumberofsimulationstorunInput formatEstimates for tasks or milestones have to be defined in a CSV file with the following structure:Task: [required] name of the task (Milestoneworks as header, too)Best: [required] best case estimate for the task durationExpected: [required] most likely estimate for the task durationWorst: [required] worst case estimate for the task durationTaskBestExpectedWorstTask A51020Task B61240Task C11324Task D101315Task E5712Task F122534Example$ cat tasks.csv
Task,Best,Expected,Worst
Task A,5,10,20
Task B,6,12,40
Task C,1,13,24
Task D,10,13,15
Task E,5,7,12
Task F,12,25,34

$ dumbpm guesstimate tasks.csv
            Duration
count   10000.000000
mean        7.761430
std         0.993793
min         5.000000
50%         8.000000
5%         8.000000
90%         9.000000
99%        10.000000
max        12.000000Estimate project duration based on historical dataGiving a list of past sprint velocities and (optionally) a list of scope changes for the project in story points defined as below, it outputs an estimate of the project duration in the form of a probability distribution (median, variance, percentiles). You can use these numbers to formulate guesstimates like "I am 75% confident that we will complete the project in 38 weeks".Please note that the estimate is measured in sprints, so you'll have to multiply that for the duration of your sprint and project that on your working calendar to account for holidays and anything else which could affect your schedule.The estimation is based on aMonte Carlo simulationof the following inequation:scope + sum(scope_change, over=sprints) <= sum(velocity, over=sprints). Pretty dumb, indeed.By default, velocity and scope change for each iteration are picked at random following auniform probability distributionfrom the provided historical data. If--normalis specified, the input will be modelled asnormal distributionfrom which velocity and scope changes will be derived.If it is taking too long to perform the estimation on your computer, set--simulationsto something lower than10000.$dumbpmestimate--help
usage:dumbpmestimate[-h][--normal][--simulations[SIMULATIONS]]filenamescope

positionalarguments:filenameCSVfilewithvelocityandscopechangedatapointsscopeRemainingscopeinstorypointsfortheproject

optionalarguments:-h,--helpshowthishelpmessageandexit--normalUseanormaldistributionfortheinputdata--simulations[SIMULATIONS]NumberofsimulationstorunInput formatHistorical data has to be defined in a CSV file with the following structure:Velocity: [required] velocity for each past sprintChange: [optional] project scope change for each past sprint (zero and negative values are allowed)VelocityChange1751911001202117-315-212512014218-4Example$ cat sprints.csv
Velocity,Change
17,5
19,1
10,0
12,0
21,1
7,-3
15,-2
12,5
12,0
14,2
18,-4

$ dumbpm estimate sprints.csv 100
            Duration
count   10000.000000
mean        7.761430
std         0.993793
min         5.000000
50%         8.000000
75%         8.000000
90%         9.000000
99%        10.000000
max        12.000000

$ dumbpm prioritize projects.csv 100 --normal
           Duration
count   10000.00000
mean        7.75637
std         0.99810
min         4.00000
50%         8.00000
75%         8.00000
90%         9.00000
99%        10.00000
max        13.00000