Bash script to calculate script speed

I wanted to calculate the script speed for a large number of funscripts so I produced this Bash script. Probably far from perfect (not sure how script speed is usually calculated?) but works and maybe could be useful for someone else.

Prerequisites
Assumes running a Bash command prompt (like the macOS Terminal app). You also need to have jq installed. Instructions for mac to install homebrew and jq:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew install jq

The script: calculate_speed.sh
Copy paste the code below into a file called something like calculate_speed.sh:

#!/bin/bash

# Check if a file name is provided as an argument
if [ -z "$1" ]; then
    echo "Usage: $0 <json_file>"
    exit 1
fi

# Check if jq is installed
if ! command -v jq &> /dev/null; then
    echo "jq is not installed. Please install jq to process JSON."
    exit 1
fi

# Extract the 'at' and 'pos' values from the JSON file
times_and_positions=$(jq -r '.actions[] | "\(.at) \(.pos)"' "$1")

# Initialize variables
prev_time=0
prev_pos=0
first=1
speeds=()

# Calculate speed between consecutive actions
while read -r line; do
    IFS=' ' read -r current_time current_pos <<< "$line"

    if [ "$first" -eq 1 ]; then
        first=0
    else
        # Calculate speed as delta position / delta time (ensure no division by zero)
        delta_time=$((current_time - prev_time))

        if [ "$delta_time" -ne 0 ]; then
            delta_pos=$((current_pos - prev_pos))

            if [ "$delta_pos" -lt 0 ]; then
              delta_pos_abs=$((delta_pos * -1))
            else
              delta_pos_abs=$delta_pos
            fi

            speed=$(bc -l <<< "(($delta_pos_abs)) / $delta_time")

            speeds+=($speed)
        fi
    fi

    prev_time=$current_time
    prev_pos=$current_pos

done <<< "$times_and_positions"

# Sort the speeds array to find the median
sorted_speeds=($(printf '%s\n' "${speeds[@]}" | sort -n))

# Calculate median
len=${#sorted_speeds[@]}
if [ $((len % 2)) -eq 1 ]; then
    median=${sorted_speeds[$((len / 2))]}
else
    mid=$((len / 2))
    median=$(bc -l <<< "((${sorted_speeds[$mid]} + ${sorted_speeds[$((mid - 1))]} ) / 2) * 1000")
fi

# Output the median speed
echo "$median"

You also need to make the file executable:
chmod +x calculate_speed.sh

Usage
Run the script with a funscript file as input to get the speed:
./calculate_speed.sh myscript.funscript

2 Likes