
# Usage: calc_metric <target> <wait-time> [<metric_offset>]
calc_metric() {
	local ping_result avg_delay packet_loss_rate
	local filename="/tmp/cost.$1"

	# Send a probe every 2 seconds
	if ! ping_result="`pingstat \"$1\" $2 2`"; then
		# Node is down...
		rm -f "$filename"
		echo 65535 > "$filename"
		return
	fi

	# 从ping结果中提取平均延迟和丢包率
	avg_delay="`printf %s \"$ping_result\" | sed -En 's#^(round-trip|rtt) min/avg/max/(stddev|mdev) = [0-9.]+/([0-9.]+)(/[0-9.]+){2} ms\$#\\3#p'`"
	if
		if [ -n "$avg_delay" ]; then
			packet_loss_rate="`printf %s \"$ping_result\" | sed -En 's/.+ ([0-9.]+)% packet loss(\$|,.+)/\\1/p'`"
			if [ -n "$packet_loss_rate" ]; then
				false
			elif printf %s "$packet_loss_rate" | grep -Eq -- "-- somebody.+ packets!"; then
				packet_loss_rate=0
				false
			fi
		fi
	then
		printf 'Failed to parse ping(8) output:\n%s\n' "$ping_result" 1>&2
		rm -f "$filename"
		echo 65535 > "$filename"
		return
	fi

	# 设置参数值

	# gamma 调整丢包率的影响，使之成为一个非线性的因素。具体来说，它决定了
	# 丢包率被提升到 delta 次方后的影响强度。通过调整 gamma 可以控制丢包率
	# 在整体度量值中的相对权重，从而在某种程度上模拟丢包对网络性能的实际影
	# 响。
	local gamma=0.2

	# delta 是丢包率影响的非线性调节器。将丢包率提升到 delta 次方可以让我
	# 们模拟丢包率增加对网络性能影响的加速或减速效应。例如，一个较高的
	# delta 值意味着随着丢包率的增加delta 量值的贡献将超线性增长，
	# 反映了在丢包率较高时对性能的更大影响。
	local delta=3

	# theta 直接乘丢包率，代表了丢包本身对延迟的直接加成影响。这反映了每个
	# 百分比的丢包对总延迟的直接贡献，模拟了由于丢包导致的重传等待时间。
	# 通过调整 theta, 我们可以控制丢包率对度量值的线性贡献，
	# 以此来模拟重传对延迟的影响。
	local theta=10

	# 以毫秒为单位的延迟阈值，该值以内视为等效。
	local fine_grain_delay_step=40

	# 用于微调最终的度量值计算
	local metric_offset=${3:-0}

	rm -f "$filename"
	printf %s\\n \
		"metric = $avg_delay + $gamma * ($packet_loss_rate ^ $delta) + $theta * $packet_loss_rate" \
		"scale = 0" \
		"metric = metric / 1 + 1 - (metric % 1 == 0)" \
		"metric = metric / $fine_grain_delay_step + 1" \
		"metric = metric + $metric_offset" \
		"if(metric > 65535) metric = 65535" \
		"if(metric <= 0) metric = 1" \
		"metric" \
			| bc > "$filename"
}
