123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- #!/bin/bash
- usage() {
- (( $# > 0 )) && echo -e "$@"
- echo "
- Creates a Supertuxkart Grand Prix
- Without options:
- Create a randomized Grand Prix of ALL tracks (both addon and builtin).
- Dates and times refer to file timestamps, i.e. when the track
- was locally installed, not when it was first published.
- Dependencies: xml (xmlstarlet) and coreutils.
- -d int Pick tracks from the latest int days
- -n int Choose the newest int tracks.
- A negative number means oldest int tracks
- Options -d and -n refer to the installation date and also includes manually
- installed tracks. They also cannot be combined.
- -R Do NOT randomize chosen tracks
- (undefined result - most likely alphabetical)
- -g str A comma-separated list of groups to include.
- Defaults to \"$groups\"
- -a Pick only addon tracks
- -b Pick only bultin tracks
- -p str Use a prefix other than $prefix
- Options -a and -b cannot be combined.
- If not specified, the default is to pick from all tracks."
- exit 1
- }
- is_valid() {
- local track="$dir/$1/track.xml"
- [ -r "$track" ] \
- && ! [[ "$(xml sel -t -v '//@internal' "$track")" == Y ]] \
- && ! [[ "$(xml sel -t -v '//@soccer' "$track")" == Y ]] \
- && ! [[ "$(xml sel -t -v '//@arena' "$track")" == Y ]]
- }
- is_latest() {
- # $1 is the directory of the track
- [[ "$days" == all ]] && return 0
- local file_time="$(get_time "$1")"
- if ((file_time >= latest_time)); then
- echo "$(date -d @$file_time) - $1"
- return 0
- else
- return 1
- fi
- }
- is_groups() {
- local track="$dir/$1/track.xml"
- for group in ${groups//,/ }; do
- [[ "$(xml sel -t -v '//@groups' "$track")" == *"$group"* ]] && return 0
- done
- return 1
- }
- get_tracks() {
- # $1 is the prefix "addon_", or nothing
- cd "$dir" || usage "Cannot cd to $dir"
- for i in *; do
- is_valid "$i" && is_groups "$i" && is_latest "$i" && grow_array "$i" "$1"
- done
- }
- grow_array() {
- # $1 is the directory of the track
- # $2 is the prefix "addon_", or nothing
- local x i="$2$1"
- x="$(xml sel -t -v '//@default-number-of-laps' "$dir/$1/track.xml")" || x=3
- i="<track id=\"$i\" laps=\"$x\" reverse=\"false\" />"
- ((number!=0)) && array=( "${array[@]}" "$(get_time "$1") $i" ) || array=( "${array[@]}" "$i" )
- }
- get_time() {
- # $1 is the directory of the track
- # accumulate all possible file times
- local file_times=() file i file_time=0
- for file in scene graph quad materials track; do
- file="$dir/$1/$file.xml"
- # stat gives more choice than 'date -r', 3 different file times in seconds since epoch
- [ -r "$file" ] && file_times=( ${filetimes[@]} $(stat --printf '%W %Y %Z' "$file") )
- done
- # we simply choose the _newest_ file time
- # this also applies if we use choose oldest tracks
- for i in ${file_times[@]}; do
- (( i > file_time )) && file_time="$i"
- done
- echo "$file_time"
- }
- echo_array() {
- if ((number!=0)); then
- IFS=$'\n'
- ((number>0)) && array=($(sort -nr <<<"${array[*]}")) || array=($(sort -n <<<"${array[*]}"))
- unset IFS
- for ((i=0;i<${number#-};i++)); do
- echo "${array[i]#* }"
- done
- else
- for ((i=0;i<${#array[@]};i++)); do
- echo "${array[i]}"
- done
- fi
- }
- # dependency checks
- for dep in xml date; do
- type -f $dep >/dev/null || usage
- done
- # default values
- addons=1
- builtins=1
- days=all
- random=1
- number=0
- oldest=0
- prefix=/usr/share
- groups=standard,Add-Ons
- re='^[+-]?[1-9][0-9]*$'
- homedir="$HOME/.local/share/supertuxkart"
- [ -w "$homedir/grandprix" ] || usage "Cannot access $homedir/grandprix for writing - does it exist?"
- while getopts "d:n:p:Rabg:h" option; do
- case "$option" in
- d)
- [[ "$number" != 0 ]] && usage "You cannot use both -d and -n"
- # regex that means positive integer but not 0
- [[ "$OPTARG" =~ ^[1-9][0-9]*$ ]] || usage "Not a valid number: $OPTARG"
- days="$OPTARG"
- latest_time="$(date -d "now - $days days" +%s)"
- ;;
- n)
- [[ "$days" != all ]] && usage "You cannot use both -n and -d"
- # regex that means positive or negative integer but not 0
- [[ "$OPTARG" =~ ^[+-]?[1-9][0-9]*$ ]] || usage "Not a valid number: $OPTARG"
- number="$OPTARG"
- ;;
- p)
- prefix="$OPTARG"
- [ -d "$prefix" ] || usage "The prefix $prefix is not a directory on this machine."
- ;;
- R)
- random=0
- ;;
- a)
- builtins=0
- [[ "$addons" == 0 ]] && usage "You cannot use both -a and -b"
- ;;
- b)
- addons=0
- [[ "$builtins" == 0 ]] && usage "You cannot use both -a and -b"
- ;;
- g)
- groups="$OPTARG"
- ;;
- h|*)
- usage
- ;;
- esac
- done
- # optional dependency checks
- if [[ "$random" == 1 ]]; then
- type -f shuf >/dev/null || usage
- fi
- if [[ "$days" != all ]]; then
- type -f stat >/dev/null || usage
- fi
- prompt="Creating"
- [[ "$random" == 0 ]] && prompt="$prompt non-randomized"
- prompt="$prompt GrandPrix with"
- if [[ "$number" == 0 ]]; then
- [[ "$days" == all ]] && prompt="$prompt tracks from any date" || prompt="$prompt tracks updated during the last $days days"
- else
- ((number<0)) && prompt="$prompt ${number#-} oldest tracks" || prompt="$prompt $number newest tracks"
- fi
- [[ "$builtins" == 0 ]] && prompt="$prompt (add-ons only)"
- [[ "$addons" == 0 ]] && prompt="$prompt (built-ins only)"
- [[ "$groups" != "standard,Add-Ons" ]] && prompt="${prompt}, groups: $groups"
- echo "${prompt}."
- read -p "Proceed (Enter/Ctrl-c)? "
- file="$homedir/grandprix/usr_gp_$(date +'%Y%m%d-%H%M%S').grandprix"
- [ -e "$file" ] && usage "Filename\n$file\nalready exists - how weird is that!"
- array=()
- if [[ "$builtins" == 1 ]]; then
- dir="$prefix/supertuxkart/data/tracks"
- get_tracks
- fi
- if [[ "$addons" == 1 ]]; then
- dir="$homedir/addons/tracks"
- get_tracks "addon_"
- fi
- if (( ${#array[@]} > 0 )); then
- name="tracks ($(date '+%b %-d'))"
- #~ [[ "$days" != all ]] && name="tracks last ${days}d $name"
- [[ "$addons" == 0 ]] && name="built-in $name"
- [[ "$builtins" == 0 ]] && name="add-on $name"
- #~ [[ "$random" == 1 ]] && name="random $name"
- ((number<0)) && name="oldest $name"
- ((number!=0)) && name="${number#-} $name" || name="${#array[@]} $name"
- start="\n<supertuxkart_grand_prix name=\"$name\">\n"
- end="\n</supertuxkart_grand_prix>\n"
- {
- echo -e "$start"
- if [[ "$random" == 0 ]]; then
- echo_array
- else
- echo_array | shuf
- fi
- echo -e "$end"
- } > "$file"
- echo -e "\nGenerated GrandPrix \"$name\"\nSaved to ~${file#$HOME}"
- else
- echo "No tracks, no GrandPrix!"
- exit 1
- fi
|