planaco 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- planaco-0.2.1/LICENSE.md +21 -0
- planaco-0.2.1/PKG-INFO +430 -0
- planaco-0.2.1/README.md +391 -0
- planaco-0.2.1/pyproject.toml +137 -0
- planaco-0.2.1/setup.cfg +4 -0
- planaco-0.2.1/src/planaco/__init__.py +158 -0
- planaco-0.2.1/src/planaco/cli.py +336 -0
- planaco-0.2.1/src/planaco/config.py +431 -0
- planaco-0.2.1/src/planaco/distributions.py +657 -0
- planaco-0.2.1/src/planaco/project.py +1085 -0
- planaco-0.2.1/src/planaco/task.py +310 -0
- planaco-0.2.1/src/planaco.egg-info/PKG-INFO +430 -0
- planaco-0.2.1/src/planaco.egg-info/SOURCES.txt +21 -0
- planaco-0.2.1/src/planaco.egg-info/dependency_links.txt +1 -0
- planaco-0.2.1/src/planaco.egg-info/entry_points.txt +2 -0
- planaco-0.2.1/src/planaco.egg-info/requires.txt +13 -0
- planaco-0.2.1/src/planaco.egg-info/top_level.txt +1 -0
- planaco-0.2.1/tests/test_cli.py +337 -0
- planaco-0.2.1/tests/test_config.py +455 -0
- planaco-0.2.1/tests/test_distributions.py +805 -0
- planaco-0.2.1/tests/test_project.py +848 -0
- planaco-0.2.1/tests/test_refactoring.py +550 -0
- planaco-0.2.1/tests/test_task.py +183 -0
planaco-0.2.1/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 Martijn Wieriks
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
planaco-0.2.1/PKG-INFO
ADDED
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: planaco
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Task and project estimation using Monte Carlo simulation
|
|
5
|
+
Author: Martijn Wieriks
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/sepam/planaco
|
|
8
|
+
Project-URL: Repository, https://github.com/sepam/planaco
|
|
9
|
+
Keywords: monte-carlo,simulation,estimation,project-management,task-planning,forecasting
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Topic :: Office/Business :: Scheduling
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
23
|
+
Requires-Python: >=3.8
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE.md
|
|
26
|
+
Requires-Dist: click>=7.0
|
|
27
|
+
Requires-Dist: matplotlib>=3.0
|
|
28
|
+
Requires-Dist: seaborn>=0.11
|
|
29
|
+
Requires-Dist: numpy>=1.18
|
|
30
|
+
Requires-Dist: PyYAML>=5.0
|
|
31
|
+
Requires-Dist: networkx>=2.5
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest>=6.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-cov>=2.10; extra == "dev"
|
|
35
|
+
Requires-Dist: mypy>=0.900; extra == "dev"
|
|
36
|
+
Requires-Dist: black>=23.0; extra == "dev"
|
|
37
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
|
|
40
|
+
<div align="center">
|
|
41
|
+
<picture>
|
|
42
|
+
<source media="(prefers-color-scheme: dark)" srcset="brand/planaco-lockup-dark.svg">
|
|
43
|
+
<img src="brand/planaco-lockup-light.svg" alt="planaco" width="320">
|
|
44
|
+
</picture>
|
|
45
|
+
|
|
46
|
+
**Probabilistic Project Planning with Monte Carlo Simulation**
|
|
47
|
+
|
|
48
|
+
[](https://www.python.org)
|
|
49
|
+
[](LICENSE.md)
|
|
50
|
+

|
|
51
|
+
|
|
52
|
+
<p align="center">
|
|
53
|
+
<a href="#why-planaco">Why Planaco?</a> •
|
|
54
|
+
<a href="#features">Features</a> •
|
|
55
|
+
<a href="#installation">Installation</a> •
|
|
56
|
+
<a href="#quick-start">Quick Start</a> •
|
|
57
|
+
<a href="#monte-carlo-simulation">Monte Carlo</a> •
|
|
58
|
+
<a href="#command-line-interface">CLI</a> •
|
|
59
|
+
<a href="#probability-distributions">Distributions</a> •
|
|
60
|
+
<a href="#contributing">Contributing</a>
|
|
61
|
+
</p>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Why Planaco?
|
|
67
|
+
|
|
68
|
+
Estimating the time it takes to complete a task or project is hard. Traditional approaches use fixed estimates, but this ignores any uncertainty and life often gets in the way.
|
|
69
|
+
|
|
70
|
+
**Planaco helps you make better estimates by modeling tasks as random processes**, accounting for uncertainty and task dependencies through Monte Carlo simulation.
|
|
71
|
+
|
|
72
|
+
> **Status:** Planaco is in **alpha** (v0.2.1). The public API may still change between releases.
|
|
73
|
+
|
|
74
|
+
## Features
|
|
75
|
+
|
|
76
|
+
- **Probabilistic Task Modeling** - Define tasks with min/max/mode duration ranges
|
|
77
|
+
- **6 Distribution Types** - Triangular, PERT, Uniform, Normal, LogNormal, and Beta distributions
|
|
78
|
+
- **Task Dependencies** - Support for parallel and sequential task execution
|
|
79
|
+
- **Monte Carlo Simulation** - Run thousands of simulations to estimate project completion
|
|
80
|
+
- **Statistical Analysis** - Get percentiles, confidence intervals, and key metrics
|
|
81
|
+
- **Visualization** - Generate histogram and cumulative distribution plots
|
|
82
|
+
- **Export Results** - Save results to JSON or CSV for further analysis
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Installation
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
pip install planaco
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Or install from source:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
git clone https://github.com/sepam/planaco.git
|
|
96
|
+
cd planaco
|
|
97
|
+
pip install .
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Quick Start
|
|
103
|
+
|
|
104
|
+
### Define Tasks with Uncertainty
|
|
105
|
+
|
|
106
|
+
Instead of saying "this task takes 5 days", Planaco lets you model uncertainty:
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
from planaco import Task
|
|
110
|
+
|
|
111
|
+
task = Task(
|
|
112
|
+
name='Develop Feature',
|
|
113
|
+
min_duration=3,
|
|
114
|
+
mode_duration=5, # most likely estimate
|
|
115
|
+
max_duration=9,
|
|
116
|
+
estimator='triangular'
|
|
117
|
+
)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
<div align="center">
|
|
121
|
+
<img src="example/task_definition.png" alt="Task Definition" width="600"/>
|
|
122
|
+
</div>
|
|
123
|
+
|
|
124
|
+
### Build Projects with Dependencies
|
|
125
|
+
|
|
126
|
+
Create complex project workflows with parallel and sequential task execution:
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
from planaco import Task, Project
|
|
130
|
+
|
|
131
|
+
# Create a project
|
|
132
|
+
project = Project(name='Web App Development', unit='days')
|
|
133
|
+
|
|
134
|
+
# Define tasks
|
|
135
|
+
design_ui = Task(name='Design UI', min_duration=2, mode_duration=3, max_duration=5, estimator='triangular')
|
|
136
|
+
develop_frontend = Task(name='Develop Frontend', min_duration=5, mode_duration=7, max_duration=10, estimator='triangular')
|
|
137
|
+
develop_backend = Task(name='Develop Backend', min_duration=4, mode_duration=6, max_duration=9, estimator='triangular')
|
|
138
|
+
testing = Task(name='Testing', min_duration=2, mode_duration=3, max_duration=5, estimator='triangular')
|
|
139
|
+
deploy = Task(name='Deploy', min_duration=1, max_duration=2, estimator='uniform')
|
|
140
|
+
|
|
141
|
+
# Add tasks with dependencies
|
|
142
|
+
project.add_task(design_ui)
|
|
143
|
+
project.add_task(develop_frontend, depends_on=[design_ui]) # Sequential: frontend needs UI design
|
|
144
|
+
project.add_task(develop_backend) # Parallel: backend runs independently
|
|
145
|
+
project.add_task(testing, depends_on=[develop_frontend, develop_backend]) # Waits for both tracks
|
|
146
|
+
project.add_task(deploy, depends_on=[testing])
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
<div align="center">
|
|
150
|
+
<img src="example/project_estimation.png" alt="Project Estimation" width="700"/>
|
|
151
|
+
</div>
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Monte Carlo Simulation
|
|
156
|
+
|
|
157
|
+
Planaco uses [Monte Carlo simulation](https://en.wikipedia.org/wiki/Monte_Carlo_method) to estimate project completion time. By running thousands of simulations, it leverages the [Central Limit Theorem](https://en.wikipedia.org/wiki/Central_limit_theorem) to provide probabilistic estimates for the completion of tasks and projects.
|
|
158
|
+
|
|
159
|
+
### Run Simulation & Get Statistics
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
# Get comprehensive statistics of the simulation
|
|
163
|
+
stats = project.statistics(n=10000)
|
|
164
|
+
|
|
165
|
+
print(f"Median completion time: {stats['median']:.1f} days")
|
|
166
|
+
print(f"90% confidence: {stats['percentiles']['p90']:.1f} days")
|
|
167
|
+
print(f"95% confidence: {stats['percentiles']['p95']:.1f} days")
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
`statistics()` returns a dictionary with the full distribution summary:
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
{
|
|
174
|
+
'n_simulations': 10000,
|
|
175
|
+
'unit': 'days',
|
|
176
|
+
'mean': 18.4,
|
|
177
|
+
'median': 18.1,
|
|
178
|
+
'std_dev': 2.7,
|
|
179
|
+
'min': 11.2,
|
|
180
|
+
'max': 29.8,
|
|
181
|
+
'percentiles': {'p50': 18.1, 'p75': 20.1, 'p85': 21.3, 'p90': 22.1, 'p95': 23.4, 'p99': 25.6},
|
|
182
|
+
'confidence_intervals': {'95%': (13.5, 24.2)},
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Visualize Results
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
# Generate histogram
|
|
190
|
+
project.plot(n=10000, hist=True)
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
<div align="center">
|
|
194
|
+
<img src="example/monte_carlo_estimation.png" alt="Monte Carlo Histogram" width="550"/>
|
|
195
|
+
</div>
|
|
196
|
+
|
|
197
|
+
### Cumulative Distribution
|
|
198
|
+
|
|
199
|
+
Read the likelihood of completing your project by a given date:
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
# Generate cumulative distribution
|
|
203
|
+
project.plot(n=10000, hist=False)
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
<div align="center">
|
|
207
|
+
<img src="example/monte_carlo_cumulative.png" alt="Cumulative Distribution" width="550"/>
|
|
208
|
+
</div>
|
|
209
|
+
|
|
210
|
+
The cumulative distribution shows the probability of completing the project within a given timeframe, accounting for both parallel and sequential task execution.
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Advanced Features
|
|
215
|
+
|
|
216
|
+
### Export Results
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
# Export to JSON
|
|
220
|
+
project.export_results(n=10000, format='json', filename='results.json')
|
|
221
|
+
|
|
222
|
+
# Export to CSV
|
|
223
|
+
project.export_results(n=10000, format='csv', filename='results.csv')
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Probability Distributions
|
|
227
|
+
|
|
228
|
+
Planaco supports six probability distributions, each suited for different estimation scenarios:
|
|
229
|
+
|
|
230
|
+
#### Triangular Distribution (Default)
|
|
231
|
+
Best for **three-point estimates** where you can identify optimistic, most likely, and pessimistic values.
|
|
232
|
+
|
|
233
|
+
```python
|
|
234
|
+
task = Task(
|
|
235
|
+
name="Development",
|
|
236
|
+
min_duration=5, # Best case
|
|
237
|
+
mode_duration=8, # Most likely
|
|
238
|
+
max_duration=15, # Worst case
|
|
239
|
+
estimator="triangular"
|
|
240
|
+
)
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**When to use:** Most common choice. Use when you have a clear "most likely" estimate and can define reasonable bounds.
|
|
244
|
+
|
|
245
|
+
#### PERT Distribution
|
|
246
|
+
A smoother alternative to triangular that **weights the mode more heavily** (by default, 4x). Widely used in project management.
|
|
247
|
+
|
|
248
|
+
```python
|
|
249
|
+
task = Task(
|
|
250
|
+
name="Testing",
|
|
251
|
+
min_duration=2,
|
|
252
|
+
mode_duration=4,
|
|
253
|
+
max_duration=10,
|
|
254
|
+
estimator="pert"
|
|
255
|
+
)
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**When to use:** Industry standard for project estimation. Produces more realistic results than triangular by reducing the influence of extreme values.
|
|
259
|
+
|
|
260
|
+
#### Uniform Distribution
|
|
261
|
+
All values between min and max are **equally likely**. No mode required.
|
|
262
|
+
|
|
263
|
+
```python
|
|
264
|
+
task = Task(
|
|
265
|
+
name="Deployment",
|
|
266
|
+
min_duration=1,
|
|
267
|
+
max_duration=3,
|
|
268
|
+
estimator="uniform"
|
|
269
|
+
)
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
**When to use:** When you genuinely don't know the most likely duration, only the range. Good for tasks with high uncertainty.
|
|
273
|
+
|
|
274
|
+
#### Normal (Gaussian) Distribution
|
|
275
|
+
Classic **bell curve** centered on the mean. Best for well-understood, repeatable tasks.
|
|
276
|
+
|
|
277
|
+
```python
|
|
278
|
+
from planaco import Task, NormalDistribution
|
|
279
|
+
|
|
280
|
+
task = Task(
|
|
281
|
+
name="Code Review",
|
|
282
|
+
distribution=NormalDistribution(
|
|
283
|
+
mean=2.0,
|
|
284
|
+
std_dev=0.5,
|
|
285
|
+
min_value=0.5, # Optional lower bound
|
|
286
|
+
max_value=4.0 # Optional upper bound
|
|
287
|
+
)
|
|
288
|
+
)
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
**When to use:** Tasks you've done many times before with predictable variability. The optional bounds prevent unrealistic negative or extreme values.
|
|
292
|
+
|
|
293
|
+
#### LogNormal Distribution
|
|
294
|
+
**Right-skewed** distribution where delays are more likely than early completion. Realistic for many real-world tasks.
|
|
295
|
+
|
|
296
|
+
```python
|
|
297
|
+
from planaco import Task, LogNormalDistribution
|
|
298
|
+
|
|
299
|
+
task = Task(
|
|
300
|
+
name="Integration",
|
|
301
|
+
distribution=LogNormalDistribution(
|
|
302
|
+
mean=5.0,
|
|
303
|
+
std_dev=2.0
|
|
304
|
+
)
|
|
305
|
+
)
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
**When to use:** Tasks with potential for unexpected delays (debugging, third-party dependencies, approvals). Models the common pattern where things take longer than expected more often than they finish early.
|
|
309
|
+
|
|
310
|
+
#### Beta Distribution
|
|
311
|
+
**Most flexible** distribution with customizable shape via alpha and beta parameters.
|
|
312
|
+
|
|
313
|
+
```python
|
|
314
|
+
from planaco import Task, BetaDistribution
|
|
315
|
+
|
|
316
|
+
task = Task(
|
|
317
|
+
name="Research",
|
|
318
|
+
distribution=BetaDistribution(
|
|
319
|
+
alpha=2.0,
|
|
320
|
+
beta=5.0,
|
|
321
|
+
min_value=1.0,
|
|
322
|
+
max_value=10.0
|
|
323
|
+
)
|
|
324
|
+
)
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
**When to use:** When you need fine-grained control over the distribution shape:
|
|
328
|
+
- `alpha < beta`: Right-skewed (more likely to finish early)
|
|
329
|
+
- `alpha > beta`: Left-skewed (more likely to finish late)
|
|
330
|
+
- `alpha = beta`: Symmetric
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
### Choosing the Right Distribution
|
|
335
|
+
|
|
336
|
+
| Scenario | Recommended Distribution |
|
|
337
|
+
|----------|-------------------------|
|
|
338
|
+
| Standard 3-point estimate | PERT or Triangular |
|
|
339
|
+
| Well-understood, repeatable task | Normal |
|
|
340
|
+
| High uncertainty, unknown mode | Uniform |
|
|
341
|
+
| Risk of delays/blockers | LogNormal |
|
|
342
|
+
| Custom uncertainty profile | Beta |
|
|
343
|
+
|
|
344
|
+
**New to Monte Carlo?** Start with **PERT** - it's the industry standard and works well for most project estimation tasks.
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
## Command Line Interface
|
|
349
|
+
|
|
350
|
+
Planaco also ships with a `planaco` CLI that runs simulations from a YAML project file — useful for CI pipelines, shared team configs, and version-controlled estimates.
|
|
351
|
+
|
|
352
|
+
```bash
|
|
353
|
+
planaco init project.yaml # Create a template config
|
|
354
|
+
planaco stats project.yaml -n 10000 # Print formatted statistics
|
|
355
|
+
planaco run project.yaml -o results.json # Export results (json or csv)
|
|
356
|
+
planaco plot project.yaml -o chart.png # Histogram or cumulative plot
|
|
357
|
+
planaco graph project.yaml # Visualize the task dependency graph
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
Example YAML config:
|
|
361
|
+
|
|
362
|
+
```yaml
|
|
363
|
+
project:
|
|
364
|
+
name: Website Redesign
|
|
365
|
+
unit: days
|
|
366
|
+
seed: 42 # optional, for reproducible runs
|
|
367
|
+
|
|
368
|
+
tasks:
|
|
369
|
+
- name: Design
|
|
370
|
+
distribution:
|
|
371
|
+
type: pert
|
|
372
|
+
minimum: 5
|
|
373
|
+
mode: 7
|
|
374
|
+
maximum: 14
|
|
375
|
+
|
|
376
|
+
- name: Development
|
|
377
|
+
depends_on: [Design]
|
|
378
|
+
distribution:
|
|
379
|
+
type: triangular
|
|
380
|
+
minimum: 10
|
|
381
|
+
mode: 15
|
|
382
|
+
maximum: 25
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
Run `planaco --help` or `planaco <command> --help` to see all available options, including `--seed` for reproducible results and `-p/--percentile` markers for plots.
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
389
|
+
## Example
|
|
390
|
+
|
|
391
|
+
A complete, runnable example lives in [`example/example_project.py`](example/example_project.py), with an annotated walkthrough in [`example/example.ipynb`](example/example.ipynb).
|
|
392
|
+
|
|
393
|
+
```bash
|
|
394
|
+
python example/example_project.py
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## Contributing
|
|
400
|
+
|
|
401
|
+
Contributions are welcome! To set up a development environment:
|
|
402
|
+
|
|
403
|
+
```bash
|
|
404
|
+
git clone https://github.com/sepam/planaco.git
|
|
405
|
+
cd planaco
|
|
406
|
+
pip install -e ".[dev]"
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
Run the checks before submitting a PR:
|
|
410
|
+
|
|
411
|
+
```bash
|
|
412
|
+
pytest # run the test suite
|
|
413
|
+
ruff check . # lint
|
|
414
|
+
black . # format
|
|
415
|
+
mypy src # type-check
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
Please open an issue to discuss larger changes before starting work.
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
422
|
+
## License
|
|
423
|
+
|
|
424
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
<div align="center">
|
|
429
|
+
<sub>Built with Monte Carlo simulation for better project planning</sub>
|
|
430
|
+
</div>
|