模拟通过看板的工作流程

kanban-simulator的Python项目详细描述


运行看板系统模拟的助手。

目前没有gui,但在jupyter/ipython笔记本上运行良好,比如 (需要安装ipython[notebook]pandasnumpymatplotlibopenpyxel):

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")

更改日志

0.3-2016年6月3日
  • 中断:如果touchsplits值是一个函数,则将使用 作为论据的卡片。
  • 卡拆分现在可以是可调用的或数字(类似于 触摸
  • 新的列类型sharedwipcolumn(),它可以将多个列分组,以便 他们有一个共同的总WIP限制。
  • 修正了第一个车道在制品限制可以忽略的问题 列
0.2-2016年5月24日
  • cardhistory现在是ordereddict
  • 一个backlog现在可以通过card-source拥有一个链式的“父”backlog
0.1-2016年5月24日
  • 初始版本

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
ArrayList Java中的搜索字符串   另一个web应用程序的java访问会话   另一个应用程序中的活动和服务之间的java通信   java根据Json字符串类型将Json字符串转换为对象   eclipse如何解决java中的错误异常。lang.NoSuchMethodError:'java。字符串javax。摆动JOptionPane。showInputDialog(java.lang.String)'   线程“main”java中的安卓异常。lang.NoClassDefFoundError:org/codehaus/jackson/JsonParseException   java如何在安卓 emulator上显示Mat图像?使用NDK   Java在本地读取测试源文件,但在服务器上读取失败   java dowhile循环用于计算输入数字中的数字。故障排除代码   JAva初学者在编写获取成本的方法时遇到困难   java是shell游戏。我如何让物体移动,特别是在特定的曲线上,但顺序是随机的?   java如何区分两个同名的JButton   java为什么我在Spring Boot中需要一个接口?   java将文件路径插入数据库将删除\   使用InterfaceType初始化java对象   java如何部署一个分为Angular、Spring Boot和MySQL的项目?   java如何使用Symja解决不等式?