Files
kit-busrouter/syno-balance/bin/lib-score.sh
T
allen f15ac69925 feat: kit-busrouter v2.0 — complete Synology + GL fleet router platform
Includes:
- package/ GL-XE3000 kit-busrouter (opkg)
- scripts/provision.sh (GL) and provision-synology.sh (Synology)
- syno-balance/ — new WAN balancer replacing aiwanbal (SmartWAN adapter)
- kit-connect/ — unified connectivity SPK (Tailscale + reverse SSH)
- docs/deployment/synology-rt2600ac-checklist.md — 62-point checklist
- docs/provisioning/device-identity.md — fleet identity spec
- docs/pilot/checklist.md — field pilot validation
- x4078_20260721.dss — reference config backup

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-22 00:07:14 +00:00

52 lines
2.3 KiB
Bash
Executable File

#!/bin/sh
# lib-score.sh — PURE per-metric + composite WAN scoring (ported from aiwanbal §2.3).
# No side effects: args in, single integer 0..100 on stdout.
# POSIX/ash-safe; integer/float math delegated to awk (available on OpenWrt).
#
# Scoring anchors (spec §2.3):
# latency 5ms -> 100 , 200ms -> 0
# download 25 -> 100 , 0.5 -> 0 (MB/s)
# upload 12.5 -> 100 , 0.5 -> 0 (MB/s)
# jitter 1ms -> 100 , 50ms -> 0
# loss 0% -> 100 , 40% -> 0
# signal -65 -> 100 , -95 -> 0 (dBm)
# clamp a numeric value to 0..100 and round half-up to an integer
_clamp() {
awk -v v="$1" 'BEGIN{ if(v<0)v=0; if(v>100)v=100; printf "%d", (v+0.5) }'
}
# read one value from stdin and clamp/round it (pipe helper)
_pipeclamp() { read v; _clamp "$v"; }
score_latency() { awk -v x="$1" 'BEGIN{ print 100*(200-x)/(200-5) }' | _pipeclamp; }
score_download() { awk -v x="$1" 'BEGIN{ print 100*(x-0.5)/(25-0.5) }' | _pipeclamp; }
score_upload() { awk -v x="$1" 'BEGIN{ print 100*(x-0.5)/(12.5-0.5) }' | _pipeclamp; }
score_jitter() { awk -v x="$1" 'BEGIN{ print 100*(50-x)/(50-1) }' | _pipeclamp; }
score_loss() { awk -v x="$1" 'BEGIN{ print 100*(40-x)/40 }' | _pipeclamp; }
score_signal() { awk -v x="$1" 'BEGIN{ print 100*(x-(-95))/((-65)-(-95)) }' | _pipeclamp; }
# Weighted 6-factor composite score.
# args: lat dl up jitter loss signal(optional)
# weights: latency35 dl25 up10 jit10 loss10 sig10.
# When signal is empty (no modem), its 10 points redistribute to latency(+5)
# and download(+5) so the remaining weights still total 100.
score_composite() {
sl=$(score_latency "$1"); sd=$(score_download "$2"); su=$(score_upload "$3")
sj=$(score_jitter "$4"); sp=$(score_loss "$5")
if [ -n "$6" ]; then
ss=$(score_signal "$6"); wsig=10; wlat=35; wdl=25
else
ss=0; wsig=0; wlat=40; wdl=30 # redistribute signal weight
fi
awk -v sl="$sl" -v sd="$sd" -v su="$su" -v sj="$sj" -v sp="$sp" -v ss="$ss" \
-v wlat="$wlat" -v wdl="$wdl" -v wsig="$wsig" 'BEGIN{
t=(sl*wlat + sd*wdl + su*10 + sj*10 + sp*10 + ss*wsig)/100
printf "%d",(t+0.5) }'
}
# Rolling average of N samples (integer, round half-up). Args: sample...
rolling_avg() {
awk 'BEGIN{ n=ARGC-1; s=0; for(i=1;i<ARGC;i++) s+=ARGV[i]; printf "%d",(s/n+0.5) }' "$@"
}