This is a pre-production deployment of Warehouse, however changes made here WILL affect the production instance of PyPI.
Latest Version Dependencies status unknown Test status unknown Test coverage unknown
Project Description

Helpers for running simulations of Kanban systems.

Currently no GUI, but works well in a Jupyter/iPython Notebook, like (requires installation of ipython[notebook], pandas, numpy, matplotlib and openpyxel):

import random
import kanban_simulator.board as kb

# For rendering HTML output in an iPython notebook:
from IPython.display import display, HTML
%matplotlib inline

# For data analysis and plan view:
import pandas as pd
import numpy as np

def to_plan(board, start_date, finished_day, freq='W-MON'):
    """Use Pandas to print a week-by-week plan-like view showing
    what state each card was in each week.
    """

    grid = pd.DataFrame(
        index=[c.name for c in board.donelog.cards],
        columns=pd.date_range(start_date, freq='D', periods=finished_day)
    )

    for card in board.donelog.cards:
        for col, data in card.history.items():
            for day in data['dates']:
                grid.ix[card.name, day-1] = col.name

    return grid.resample(freq, label='left', axis=1).first().fillna("")

# Build a backlog with some epics.
# Stipulate that when the epic enters the "Build" sublane-column, it will
# split into a number of stories.

backlog = kb.Backlog(cards=[
        kb.Epic("Epic one", splits={'Build': random.randint(5, 10)}),
        kb.Epic("Epic two", splits={'Build': random.randint(10, 20)}),
        kb.Epic("Epic three", splits={'Build': 30}),
        kb.Epic("Epic four", splits={'Build': 50}),
        kb.Epic("Epic five", splits={'Build': 50}),
        kb.Epic("Epic six", splits={'Build': 50}),
        kb.Epic("Epic seven", splits={'Build': 50}),
    ])

# Create a lane and clone it so that we have two lanes with the same columns
# It has a lane-wide WIP limit (optional), and a series of columns
# operating on epics. The "Build" column has a sub-lane (or rather,
# might have one or more depending on the number of epics in this column,
# subject to WIP limits), which operates on stories. The epic itself splits
# into stories and becomes a backlog for these stories, as per the number of
# stories above.

lane_template = kb.Lane(
    name="<lane name>",
    wip_limit=3,
    columns=[
        kb.Column(
            name="Discovery",
            touch=lambda: random.randint(5, 10),
            wip_limit=1,
            card_type=kb.Epic
        ),
        kb.QueueColumn(
            name="Ready for Build",
            wip_limit=1,
            card_type=kb.Epic
        ),
        kb.SublaneColumn(
            name="Build",
            lane_template=kb.Lane(
                name="Build",
                columns=[
                    kb.Column(
                        name="Analysis",
                        touch=lambda: random.randint(1, 3),
                        wip_limit=3,
                        card_type=kb.Story
                    ),
                    kb.Column(
                        name="Development",
                        touch=lambda: random.randint(1, 4),
                        wip_limit=3,
                        card_type=kb.Story
                    ),
                    kb.Column(
                        name="Test",
                        touch=lambda: random.randint(1, 2),
                        wip_limit=3,
                        card_type=kb.Story
                    ),
                ],
            ),
            wip_limit=1,
            card_type=kb.Epic
        ),
        kb.Column(
            name="Final testing",
            touch=lambda: random.randint(1, 5),
            wip_limit=1,
            card_type=kb.Epic
        ),
    ]
)

lanes = [
    lane_template.clone(name="Team 1"),
    lane_template.clone(name="Team 2"),
]

# Create the board
board = kb.Board(
    name="Test simulation",
    lanes=lanes,
    backlog=backlog
)

# Show the Kanban board day by day. The board is a state machine,
# so when we iterate through it, the state changes. We use `clone()` to
# get a new copy so we can use the same `board` later.

for day, board_state in board.clone():
    print "Day", day
    board_html = board_state.to_html()

    # iPython notebook specific magic to print HTML
    display(HTML(board_html))

# If we only want the end state, we can just do:
days, board_state = board.clone().run_simulation()
print "It took", days, "days"

# The cards are in the `board_state.donelog.cards` list. They have
# attributes like `age` (total number of days), `dates` (dates the card
# was active), `touch` (number of days actually working on a card, as
# opposed to waiting), and `history` (a breakdown of `age`, `dates` and
# `touch`) by column name.

# We can also run a Monte Carlo simulation:
mc_results = board.run_monte_carlo_simulation(trials=100)

# We can do some data analysis on the finish dates of each
finishes = pd.Series([r[0] for r in mc_results])

print "Monte Carlo, after", len(mc_results), "loops. Quantiles:"
print finishes.quantile([0.5, 0.85, 0.95])

# Histogram of finishes
finishes.plot.hist()

# Board at the 85th percentile, output as a grid plan
day85, board85 = mc_results[int(len(mc_results) * 0.85)]

plan = to_plan(board85, '2016-06-01', day85)
display(HTML(plan.to_html()))

# Save to Excel (requires openpyxl)
plan.to_excel("simulation.xlsx", "Simulation")

Changelog

0.3 - 03 June 2016
  • BREAKING: If touch or a splits value is a function, it will be called with the card as an argument.
  • Card splits can now be either a callable or a number (analogous to touch)
  • New column type, SharedWIPColumn(), which can group multiple columns so that they have a shared overall WIP limit.
  • Fixed problem whereby lane WIP limits could be ignored in the first column
0.2 - 24 May 2016
  • Card history is now an OrderedDict
  • A backlog can now have a chained “parent” backlog via card_source
0.1 - 24 May 2016
  • Initial release
Release History

Release History

0.3

This version

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.2

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

0.1

History Node

TODO: Figure out how to actually get changelog content.

Changelog content for this version goes here.

Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit.

Show More

Download Files

Download Files

TODO: Brief introduction on what you do with files - including link to relevant help section.

File Name & Checksum SHA256 Checksum Help Version File Type Upload Date
kanban-simulator-0.3.tar.gz (8.7 kB) Copy SHA256 Checksum SHA256 Source Jun 2, 2016

Supported By

WebFaction WebFaction Technical Writing Elastic Elastic Search Pingdom Pingdom Monitoring Dyn Dyn DNS HPE HPE Development Sentry Sentry Error Logging CloudAMQP CloudAMQP RabbitMQ Heroku Heroku PaaS Kabu Creative Kabu Creative UX & Design Fastly Fastly CDN DigiCert DigiCert EV Certificate Rackspace Rackspace Cloud Servers DreamHost DreamHost Log Hosting