Harden published curriculum and student flows
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
/** Pure watch-v1 measurement rules. This measures playback evidence, not attention. */
|
||||
final class WatchIntervalPolicy
|
||||
{
|
||||
public static function evaluate(
|
||||
string $previousType,
|
||||
string $eventType,
|
||||
int $previousPositionMs,
|
||||
int $positionMs,
|
||||
int $serverDeltaSeconds,
|
||||
int $durationMs,
|
||||
string $fundingSource
|
||||
): array {
|
||||
if ($eventType !== 'heartbeat' || !in_array($previousType, ['start', 'heartbeat', 'resume'], true)) {
|
||||
return ['seconds' => 0, 'status' => 'excluded', 'reason' => 'non_contiguous_event'];
|
||||
}
|
||||
if ($fundingSource === 'none') {
|
||||
return ['seconds' => 0, 'status' => 'excluded', 'reason' => 'unfunded_session'];
|
||||
}
|
||||
if ($durationMs <= 0 || $positionMs > $durationMs) {
|
||||
return ['seconds' => 0, 'status' => 'review', 'reason' => 'position_out_of_bounds'];
|
||||
}
|
||||
$clientDeltaMs = $positionMs - $previousPositionMs;
|
||||
if ($clientDeltaMs < 1000 || $clientDeltaMs > 90000 || $serverDeltaSeconds < 1 || $serverDeltaSeconds > 90) {
|
||||
return ['seconds' => 0, 'status' => 'review', 'reason' => 'implausible_delta'];
|
||||
}
|
||||
$seconds = min((int)floor($clientDeltaMs / 1000), $serverDeltaSeconds, 60);
|
||||
if ($seconds <= 0) return ['seconds' => 0, 'status' => 'excluded', 'reason' => 'zero_interval'];
|
||||
return ['seconds' => $seconds, 'status' => 'measured', 'reason' => 'contiguous_heartbeat'];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user