refactor(stats): fix PHPDoc placement and naming in the price funnel
Move the collect() @param/@return block off the class docblock onto the method it describes (matching ExperimentFunnelCollector), rename the shadowing $high2 Wilson bound to $upper, and add array-shape docblocks to the CM moment helpers. No behaviour change.
This commit is contained in:
parent
f7cee87a2a
commit
327e9b1d8b
|
|
@ -154,8 +154,8 @@ class SendPriceExperimentFunnelReportCommand extends Command
|
|||
continue;
|
||||
}
|
||||
|
||||
[$low, $high2] = $this->significance->wilsonInterval($k, $n);
|
||||
$lines[] = sprintf(' %-8s %6s [%6s – %6s] (n=%d)', $label, $this->percent($k / $n), $this->percent($low), $this->percent($high2), $n);
|
||||
[$lower, $upper] = $this->significance->wilsonInterval($k, $n);
|
||||
$lines[] = sprintf(' %-8s %6s [%6s – %6s] (n=%d)', $label, $this->percent($k / $n), $this->percent($lower), $this->percent($upper), $n);
|
||||
$arms[$key] = new BinomialProportion($label, $k, $n);
|
||||
}
|
||||
|
||||
|
|
@ -171,12 +171,19 @@ class SendPriceExperimentFunnelReportCommand extends Command
|
|||
return $lines;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $row
|
||||
*/
|
||||
private function cmMean(array $row): float
|
||||
{
|
||||
return $row['assignedMature'] > 0 ? (float) $row['contributionMarginCents'] / $row['assignedMature'] : 0.0;
|
||||
}
|
||||
|
||||
/** Sample variance (n−1) of per-user CM, from the accumulated moments. */
|
||||
/**
|
||||
* Sample variance (n−1) of per-user CM, from the accumulated moments.
|
||||
*
|
||||
* @param array<string, mixed> $row
|
||||
*/
|
||||
private function cmVariance(array $row): float
|
||||
{
|
||||
$n = (int) $row['assignedMature'];
|
||||
|
|
|
|||
|
|
@ -31,23 +31,6 @@ use Laravel\Cashier\Subscription;
|
|||
* Enable Banking actually bills us; API-key providers are free). It is symmetric
|
||||
* across arms, so it biases absolute CM but not the between-arm comparison. Make it
|
||||
* per-provider only if absolute margin ever needs to be trusted.
|
||||
*
|
||||
* @param int $costPerConnectionCents flat estimated monthly cost per active connection
|
||||
* @return array{
|
||||
* startedAt: ?CarbonImmutable,
|
||||
* currency: string,
|
||||
* revenueAvailable: bool,
|
||||
* costPerConnectionCents: int,
|
||||
* decisionWindowDays: int,
|
||||
* variants: array<string, array{
|
||||
* assigned: int, activated: int, subscribed: int,
|
||||
* assignedMature: int, activatedMature: int, convertedMature: int, activeMature: int,
|
||||
* payerCount: int, payerConnectionSum: int,
|
||||
* conversionRate: ?float,
|
||||
* mrrCents: int, costCents: int, contributionMarginCents: int,
|
||||
* cmPerAssignedCents: ?int, cmSumSq: float, connectionsPerPayer: ?float,
|
||||
* }>
|
||||
* }
|
||||
*/
|
||||
class PriceExperimentFunnelCollector
|
||||
{
|
||||
|
|
@ -56,6 +39,24 @@ class PriceExperimentFunnelCollector
|
|||
|
||||
public function __construct(private MonthlyEquivalentPrices $prices) {}
|
||||
|
||||
/**
|
||||
* @param int $costPerConnectionCents flat estimated monthly cost per active connection
|
||||
* @return array{
|
||||
* startedAt: ?CarbonImmutable,
|
||||
* currency: string,
|
||||
* revenueAvailable: bool,
|
||||
* costPerConnectionCents: int,
|
||||
* decisionWindowDays: int,
|
||||
* variants: array<string, array{
|
||||
* assigned: int, activated: int, subscribed: int,
|
||||
* assignedMature: int, activatedMature: int, convertedMature: int, activeMature: int,
|
||||
* payerCount: int, payerConnectionSum: int,
|
||||
* conversionRate: ?float,
|
||||
* mrrCents: int, costCents: int, contributionMarginCents: int,
|
||||
* cmPerAssignedCents: ?int, cmSumSq: float, connectionsPerPayer: ?float,
|
||||
* }>
|
||||
* }
|
||||
*/
|
||||
public function collect(int $costPerConnectionCents = 40): array
|
||||
{
|
||||
$startedValue = config('subscriptions.price_experiment.started_at');
|
||||
|
|
|
|||
Loading…
Reference in New Issue