inc/helpers.php
Snapshot 2026.09.17-a2894de (current) · 54 lines · 2,944 bytes · tree · plain text
SHA-256
287c881d9ae5317f72bc074f3c4ffda0f3677e944590fef8ad180551c47b4fd9Functions: h L9-L10 · stream_by_code L11-L15 · visible L16-L18 · series L19-L27 · latest L28-L32 · mode_badge L33-L37 · inst_status_badge L38-L42 · json_series L43-L45 · instrument_card L46-L54
| 1 | <?php |
| 2 | require_once __DIR__.'/db.php'; |
| 3 | |
| 4 | /* Reserved status palette (validated, dark surface) */ |
| 5 | const C_GOOD='#0ca30c'; const C_WARN='#fab219'; const C_SERIOUS='#ec835a'; const C_CRIT='#d03b3b'; |
| 6 | /* Fixed categorical order (validated dark palette) */ |
| 7 | const SERIES=['#3987e5','#d95926','#199e70','#c98500','#d55181','#008300','#9085e9','#e66767']; |
| 8 | |
| 9 | function h(?string $s): string { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); } |
| 10 | |
| 11 | function stream_by_code(string $code): ?array { |
| 12 | $q=db()->prepare('SELECT s.*, i.name inst_name, i.product, i.vendor_link, i.data_path, i.zone, i.cadence_min, i.status inst_status |
| 13 | FROM streams s JOIN instruments i ON i.id=s.instrument_id WHERE s.code=?'); |
| 14 | $q->execute([$code]); $r=$q->fetch(); return $r?:null; |
| 15 | } |
| 16 | function visible(array $s): bool { return $s['visibility']==='public'; } |
| 17 | |
| 18 | /* Fetch series honouring placeholder/live mode: live mode excludes placeholder rows. */ |
| 19 | function series(array $stream, string $from, string $to, int $maxpts=800): array { |
| 20 | $ph = $stream['mode']==='placeholder' ? 1 : 0; |
| 21 | $q=db()->prepare('SELECT ts,value FROM readings WHERE stream_id=? AND is_placeholder=? AND ts BETWEEN ? AND ? ORDER BY ts'); |
| 22 | $q->execute([$stream['id'],$ph,$from,$to]); |
| 23 | $rows=$q->fetchAll(); |
| 24 | $n=count($rows); |
| 25 | if($n>$maxpts){ $step=(int)ceil($n/$maxpts); $rows=array_values(array_filter($rows,fn($k)=>$k%$step===0,ARRAY_FILTER_USE_KEY)); } |
| 26 | return $rows; |
| 27 | } |
| 28 | function latest(array $stream): ?array { |
| 29 | $ph = $stream['mode']==='placeholder' ? 1 : 0; |
| 30 | $q=db()->prepare('SELECT ts,value FROM readings WHERE stream_id=? AND is_placeholder=? ORDER BY ts DESC LIMIT 1'); |
| 31 | $q->execute([$stream['id'],$ph]); $r=$q->fetch(); return $r?:null; |
| 32 | } |
| 33 | function mode_badge(array $stream): string { |
| 34 | return $stream['mode']==='live' |
| 35 | ? '<span class="badge badge-live">LIVE DATA</span>' |
| 36 | : '<span class="badge badge-ph">PLACEHOLDER DATA</span>'; |
| 37 | } |
| 38 | function inst_status_badge(string $st): string { |
| 39 | $map=['ok'=>['OK',C_GOOD],'late'=>['LATE',C_WARN],'silent'=>['SILENT',C_SERIOUS],'fault'=>['FAULT',C_CRIT],'pending'=>['PENDING','#6b7480']]; |
| 40 | [$t,$c]=$map[$st]??['?','#6b7480']; |
| 41 | return '<span class="dot" style="background:'.$c.'"></span><span class="statustext">'.$t.'</span>'; |
| 42 | } |
| 43 | function json_series(array $rows): string { |
| 44 | return json_encode(array_map(fn($r)=>[substr($r['ts'],0,16),(float)$r['value']],$rows)); |
| 45 | } |
| 46 | function instrument_card(array $s): string { |
| 47 | $link=$s['vendor_link']?'<a href="'.h($s['vendor_link']).'" rel="noopener" target="_blank">'.h($s['vendor_link']).'</a>':''; |
| 48 | return '<div class="instcard"><div class="instlabel">Instrument</div>' |
| 49 | .'<div class="instname">'.h($s['product']).'</div>' |
| 50 | .'<div class="instmeta">'.h($s['inst_name']).' · '.h($s['zone']).'</div>' |
| 51 | .'<div class="instmeta">Data path: '.h($s['data_path']).' · Cadence: every '.h((string)$s['cadence_min']).' min</div>' |
| 52 | .'<div class="instmeta">'.$link.'</div></div>'; |
| 53 | } |
| 54 | |
Lines can be cited as inc/helpers.php L120-L140, platform code 2026.09.17-a2894de; add #L120-L140 to this page's address to highlight them. Source shown for scrutiny of the research platform. All rights reserved. Not offered as installable software.