1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
//! # Lean Value Stream Metrics
//!
//! Every flow metric in this crate descends from the five baseline
//! measurements of classical Lean value stream mapping, developed at Toyota
//! and generalized across manufacturing, operations, and service delivery
//! long before software adopted them: lead time, process time, cycle time,
//! percent complete and accurate (%C/A), and takt time. This module
//! implements %C/A, rolled throughput yield, and takt time — the three that
//! do not already have a direct home elsewhere in this crate.
//!
//! ## Formula
//!
//! ```text
//! %C/A = usable units without rework / total units × 100%
//! Rolled throughput yield = %C/A(stage 1) × %C/A(stage 2) × ... × %C/A(stage N)
//! Takt time = available working time / customer demand over that period
//! ```
//!
//! ## Why it matters
//!
//! %C/A measures something the flow metrics do not: how much of what a
//! stage produces is actually usable by the next stage without being sent
//! back. Rolled up across a multi-stage value stream (rolled throughput
//! yield), it reveals how rework compounds invisibly across handoffs: three
//! stages each individually running at 90% complete-and-accurate compound to
//! roughly 73% overall — a number that looks nothing like any single
//! stage's own report and is usually the more honest one. Takt time
//! reframes capacity planning around real customer demand rather than
//! existing pace.
//!
//! ## Example
//!
//! ```rust
//! use software_engineering::lean_value_stream_metrics::{
//! percent_complete_and_accurate, rolled_throughput_yield, takt_time,
//! };
//!
//! // A stage that produces 90 usable units out of 100: 90% C/A.
//! let stage_pca = percent_complete_and_accurate(90.0, 100.0).unwrap();
//! assert!((stage_pca - 90.0).abs() < 1e-9);
//!
//! // Three stages each at 90% C/A compound to about 73% rolled throughput yield.
//! let rty = rolled_throughput_yield(&[0.90, 0.90, 0.90]);
//! assert!((rty - 0.729).abs() < 1e-9);
//!
//! // 400 minutes of available working time against demand for 20 units: 20 min/unit.
//! let takt = takt_time(400.0, 20.0).unwrap();
//! assert_eq!(takt, 20.0);
//! ```
//!
//! ## Pitfalls
//!
//! - **Measuring %C/A only at final delivery**, the chapter's central
//! gaming vector: a team can report a high final-stage %C/A while earlier
//! stages quietly produce rework fixed before anyone measures it. Roll
//! %C/A up multiplicatively across every stage instead.
//! - **Setting takt time from current capacity instead of real customer
//! demand** defeats the purpose of the metric, which is to reveal a gap
//! between demand and capacity.
//! - **Reporting %C/A without pairing it against flow velocity** allows a
//! rising throughput number to hide a falling rework rate.
//!
//! ## Sources
//!
//! - Rother, Mike, and John Shook. *Learning to See: Value Stream Mapping to
//! Create Value and Eliminate Muda*. Lean Enterprise Institute, 1999.
//! - Ohno, Taiichi. *Toyota Production System: Beyond Large-Scale
//! Production*. Productivity Press, 1988.
//!
//! Topic doc: 02-08-lean-value-stream-metrics.md
/// Percent complete and accurate (%C/A): the share of a stage's output that
/// a downstream team can use without rework.
///
/// Measure %C/A at each stage individually so it can be rolled up
/// multiplicatively into [`rolled_throughput_yield`] — measuring it only at
/// final delivery hides rework introduced and caught earlier in the stream.
///
/// # Arguments
///
/// * `usable_without_rework` — units the downstream stage can process
/// without sending them back.
/// * `total_units` — total units the stage produced.
///
/// # Returns
///
/// `Some(percentage)` (e.g. `90.0` for 90%), or `None` when `total_units`
/// is zero.
///
/// # Examples
///
/// ```rust
/// use software_engineering::lean_value_stream_metrics::percent_complete_and_accurate;
///
/// let pca = percent_complete_and_accurate(90.0, 100.0).unwrap();
/// assert!((pca - 90.0).abs() < 1e-9);
/// assert_eq!(percent_complete_and_accurate(90.0, 0.0), None);
/// ```
/// Rolled throughput yield: the product of every stage's %C/A fraction
/// across a multi-stage value stream.
///
/// Three stages each individually running at 90% complete-and-accurate
/// compound to roughly 73% overall, a number that looks nothing like any
/// single stage's own report and is usually the more honest one.
///
/// # Arguments
///
/// * `stage_pca_fractions` — each stage's %C/A expressed as a fraction
/// (e.g. `0.9` for 90%), in stage order.
///
/// # Returns
///
/// The product of all fractions. An empty slice returns `1.0` (the identity
/// for multiplication — no stages, no compounding loss).
///
/// # Examples
///
/// ```rust
/// use software_engineering::lean_value_stream_metrics::rolled_throughput_yield;
///
/// let rty = rolled_throughput_yield(&[0.90, 0.90, 0.90]);
/// assert!((rty - 0.729).abs() < 1e-9);
///
/// assert_eq!(rolled_throughput_yield(&[]), 1.0);
/// ```
/// Takt time: the maximum acceptable time to complete a unit to cleanly
/// match customer demand.
///
/// Calculate takt time from real customer demand data, deliberately
/// independent of how fast the team happens to be able to work today. A
/// cycle time exceeding takt time is concrete, quantified evidence of a
/// capacity shortfall.
///
/// # Arguments
///
/// * `available_working_time` — total working time available in the period
/// (any consistent time unit).
/// * `customer_demand` — number of units demanded over that same period.
///
/// # Returns
///
/// `Some(takt time)` per unit, or `None` when `customer_demand` is zero.
///
/// # Examples
///
/// ```rust
/// use software_engineering::lean_value_stream_metrics::takt_time;
///
/// // 400 minutes of available time to meet demand for 20 units: 20 min/unit.
/// assert_eq!(takt_time(400.0, 20.0), Some(20.0));
/// assert_eq!(takt_time(400.0, 0.0), None);
/// ```