Operations — time study with confidence intervals
A direct time study that reports how precise it is, which is the part normally missing. Typed FlowScript for supply chains. Keywords: supply chain, logistics, network, supplier.
Make it your own.
// A direct time study that reports how precise it is, which is the part
// normally missing.
//
// Five elements of a pick-and-pack operation in an ambient distribution
// centre, timed at the bin face. Observed time becomes basic time through
// the rating, and basic time becomes standard time through the allowances;
// both conversions are derivations, so changing the rating moves every
// standard time at once instead of inviting a partial re-typing.
//
// The confidence interval on each element answers the question a standard
// time is normally quoted without: how many cycles would we need to have
// timed for this number to be worth defending? At 30 cycles the walk
// element is precise to about 5.4%, so the study is six cycles short of
// the plus-or-minus 5% the method sheet asks for.
work_study pick_pack {
title: "Pick and pack, ambient zone — element time study"
operation: "Order picking to tote and pack-out, 3.4 lines per order average"
site: "Regional distribution centre, ambient zone B"
method: "Direct time study, continuous timing, BS 3138 element definitions"
observer: "Industrial engineering, 2026-02-24 to 2026-02-26"
rating_scale: "British Standard, 100 = standard rating"
rating: 105
rating_factor: = rating / 100
relaxation_allowance: 11%
contingency_allowance: 3%
total_allowance: = relaxation_allowance + contingency_allowance
allowance_factor: = 1 + total_allowance / 100[%]
lines_per_order: 3.4
shift_length: 7.5
precision_target: 5%
}
work_element walk_to_bin {
of: pick_pack
description: "Walk from the previous bin face to the next pick face"
observations: 30
frequency: 3.4
observed_mean: 0.420 min
observed_sd: 0.061 min
t_critical: 2.045 source "Student t, two-sided 95%, 29 df"
basic_time: = observed_mean * pick_pack.rating_factor
standard_time: = basic_time * pick_pack.allowance_factor
time_per_order: = standard_time * frequency
standard_error: = observed_sd / sqrt(observations)
ci_half_width: = t_critical * standard_error
precision: = pct(ci_half_width, observed_mean)
observations_needed: = ceil((t_critical * observed_sd / (0.05 * observed_mean)) ^ 2)
}
work_element locate_and_scan {
of: pick_pack
description: "Read the pick label, scan the location barcode"
observations: 30
frequency: 3.4
observed_mean: 0.280 min
observed_sd: 0.042 min
t_critical: 2.045 source "Student t, two-sided 95%, 29 df"
basic_time: = observed_mean * pick_pack.rating_factor
standard_time: = basic_time * pick_pack.allowance_factor
time_per_order: = standard_time * frequency
standard_error: = observed_sd / sqrt(observations)
ci_half_width: = t_critical * standard_error
precision: = pct(ci_half_width, observed_mean)
observations_needed: = ceil((t_critical * observed_sd / (0.05 * observed_mean)) ^ 2)
}
work_element pick_and_place {
of: pick_pack
description: "Grasp the item, confirm quantity, place in the tote"
observations: 30
frequency: 3.4
observed_mean: 0.190 min
observed_sd: 0.031 min
t_critical: 2.045 source "Student t, two-sided 95%, 29 df"
basic_time: = observed_mean * pick_pack.rating_factor
standard_time: = basic_time * pick_pack.allowance_factor
time_per_order: = standard_time * frequency
standard_error: = observed_sd / sqrt(observations)
ci_half_width: = t_critical * standard_error
precision: = pct(ci_half_width, observed_mean)
observations_needed: = ceil((t_critical * observed_sd / (0.05 * observed_mean)) ^ 2)
}
work_element pack_and_label {
of: pick_pack
description: "Transfer the tote to carton, void fill, seal and label — once per order"
observations: 20
frequency: 1
observed_mean: 0.860 min
observed_sd: 0.145 min
t_critical: 2.093 source "Student t, two-sided 95%, 19 df"
basic_time: = observed_mean * pick_pack.rating_factor
standard_time: = basic_time * pick_pack.allowance_factor
time_per_order: = standard_time * frequency
standard_error: = observed_sd / sqrt(observations)
ci_half_width: = t_critical * standard_error
precision: = pct(ci_half_width, observed_mean)
observations_needed: = ceil((t_critical * observed_sd / (0.05 * observed_mean)) ^ 2)
}
work_element dispatch_scan {
of: pick_pack
description: "Scan to the dispatch lane and release the order — once per order"
observations: 20
frequency: 1
observed_mean: 0.240 min
observed_sd: 0.038 min
t_critical: 2.093 source "Student t, two-sided 95%, 19 df"
basic_time: = observed_mean * pick_pack.rating_factor
standard_time: = basic_time * pick_pack.allowance_factor
time_per_order: = standard_time * frequency
standard_error: = observed_sd / sqrt(observations)
ci_half_width: = t_critical * standard_error
precision: = pct(ci_half_width, observed_mean)
observations_needed: = ceil((t_critical * observed_sd / (0.05 * observed_mean)) ^ 2)
}
standard_output pick_pack_output {
of: pick_pack
// Named one by one rather than rolled up with sum(kind:work_element,
// …). The aggregate reads better and is what a study of forty elements
// would need, but time_per_order is itself DERIVED — basic time, times
// the allowance factor, times frequency — and the roll-up is taken
// before those derivations resolve, so it returns zero and the whole
// chain below it divides by nothing. Five elements is few enough to
// name, and naming them is also the audit trail a time study is for.
standard_minutes_per_order: = walk_to_bin.time_per_order + locate_and_scan.time_per_order + pick_and_place.time_per_order + pack_and_label.time_per_order + dispatch_scan.time_per_order
orders_per_hour: = 60[min] / standard_minutes_per_order
orders_per_shift: = orders_per_hour * pick_pack.shift_length
current_actual_per_shift: 78
performance_index: = pct(current_actual_per_shift, orders_per_shift)
labour_minutes_per_line: = standard_minutes_per_order / pick_pack.lines_per_order
}
// The walk element is the one with the spread, so it is the one drawn.
// Thirty timed cycles, split by picker, with every reading shown.
distribution walk_observations {
title: "Walk-to-bin element — 30 timed cycles"
kind: raincloud
unit: "min"
whisker: tukey
jitter: true
n: 30
group picker_a {
label: "Picker A"
values: [0.38, 0.45, 0.34, 0.44, 0.29, 0.47, 0.41, 0.36, 0.49, 0.40, 0.33, 0.49, 0.42, 0.31, 0.46]
n: 15
mean: 0.4027
}
group picker_b {
label: "Picker B"
values: [0.45, 0.39, 0.50, 0.42, 0.36, 0.50, 0.43, 0.47, 0.37, 0.48, 0.41, 0.47, 0.35, 0.44, 0.52]
n: 15
mean: 0.4373
}
}
note allowance_basis {
text: "The 11% relaxation allowance is the site agreement figure for ambient picking with no lifting above shoulder height. It is a negotiated number, not a measured one, and it is worth more than every element time in this study put together: a one point change in it moves the standard time by about 0.05 minutes per order."
anchor: pick_pack
}
view times: raincloud(walk_observations)
caption times_caption {
of: times
title: "Walk element, by picker"
text: "Every timed cycle of the walk-to-bin element, split by picker. The spread, not the mean, is what decides how many cycles the study needs."
statistics: "Box shows median and hinges with Tukey whiskers; all 30 observations are drawn."
n_statement: "n = 30 cycles, 15 per picker, both rated at 105."
style: journal
}