287 lines
7.8 KiB
Bash
Executable File
287 lines
7.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# Copyright 2014 Vladimir Ivanov <ivvl82@gmail.com>
|
||
# Distributed under the terms of the GNU General Public License v2
|
||
|
||
# REPO="https://raw.githubusercontent.com/fat0troll/lorchess/master"
|
||
REPO="`dirname $0`"
|
||
TOURNAMENT="2014/3-fallenleaves"
|
||
|
||
# Version information
|
||
VERSION="0.4"
|
||
|
||
argv0="${0##*/}"
|
||
|
||
usage() {
|
||
cat <<EOF
|
||
List games on tours of tournament
|
||
|
||
Usage: $argv0 [options] [tours]
|
||
Tournament tours are restricted to sequence \`tours' given in
|
||
Bash-style syntax, i.e., \`tours' may include explicit numbers
|
||
(tours=1 3), intervals (tours={1..5}), or any combination of them.
|
||
If no tours are specified, display each tour until an empty
|
||
\`tour_info' is found. By default, only unaccomplished games are
|
||
listed.
|
||
|
||
Inner variable REPO points to the root of repository; its default
|
||
value of \`dirname \$0\` can be replaced by a URL link, absolute or
|
||
relative path. Inner variable TOURNAMENT specifies the sub-directory
|
||
of tournament.
|
||
|
||
Options:
|
||
-a List accomplished games too
|
||
-p PLAYER Show game if PLAYER is a part of a player's name
|
||
-f FORMAT Specify the output format; FORMAT is \`term'
|
||
(default), \`html', or \`lor'
|
||
-l Add the URL link to game (if accomplished)
|
||
-h Show this help output
|
||
-v Show version information
|
||
EOF
|
||
}
|
||
|
||
version() {
|
||
echo "${argv0}-${VERSION}"
|
||
}
|
||
|
||
show_tour_sequence() {
|
||
local tour_info
|
||
|
||
# Reduce REPO to a canonical form
|
||
convert_repo_url
|
||
|
||
if [[ -n "$@" ]]; then
|
||
for num in $@; do
|
||
fetch_tour_info "$num" && output_tour_info
|
||
done
|
||
else
|
||
# If the tour numbers were not passed as arguments, exit once
|
||
# the first non-existing 'tour_info' is reached
|
||
num=1
|
||
while fetch_tour_info "$num"; do
|
||
output_tour_info
|
||
num=$((num+1))
|
||
done
|
||
fi
|
||
}
|
||
|
||
fetch_tour_info() {
|
||
# Change tour numbers: '1' -> '01', '2' -> '02', and so on
|
||
local tour=$(printf "%02g" "$1")
|
||
|
||
# *NOTE* The incorporation of a newline at the end of 'tour_info'
|
||
# (--write-out '\n') is important and allows one to read the last
|
||
# line with no trailing '\n'
|
||
local info_url="${REPO}/${TOURNAMENT}/tours/${tour}/tour_info"
|
||
tour_info="$(curl -q --fail --location --silent --write-out '\n' $info_url)"
|
||
return `[[ -n "$tour_info" ]]`
|
||
}
|
||
|
||
output_tour_info() {
|
||
local tour_num date_beg date_end
|
||
local white black result game_date game_url
|
||
# Lines with game info
|
||
local output_lines=""
|
||
|
||
while read line; do
|
||
# Read 'tour_num'
|
||
get_tour_num "$line" && continue
|
||
# Read 'date_beg' and 'date_end'
|
||
get_tour_dates "$line" && continue
|
||
|
||
# Keep game info if needed, and store it in variables 'white',
|
||
# 'black', 'result', and 'game_date'
|
||
if keep_game_info "$line"; then
|
||
# Fix result
|
||
case "$result" in
|
||
"1:0") result="1-0" ;;
|
||
"0:1") result="0-1" ;;
|
||
"0.5:0.5") result="1/2" ;;
|
||
esac
|
||
|
||
# Store the link to game in 'game_url'
|
||
game_url=""
|
||
if $SHOW_LINK; then
|
||
[[ -n "$result" ]] && store_game_url
|
||
fi
|
||
|
||
output_lines+="${white} ${black} ${result} ${game_url}\n"
|
||
fi
|
||
done <<< "$tour_info"
|
||
|
||
[[ -n "$output_lines" ]] && eval "info_output_$FORMAT \"${output_lines}\""
|
||
}
|
||
|
||
convert_repo_url() {
|
||
if [[ ! "$REPO" =~ ^(https?|file):// ]]; then
|
||
if [[ ! "$REPO" =~ ^/ ]]; then
|
||
# REPO is a relative path
|
||
base_dir="$(dirname $0)"
|
||
REPO="$(cd ${base_dir}/${REPO}; pwd)"
|
||
fi
|
||
|
||
REPO="file://${REPO}"
|
||
fi
|
||
}
|
||
|
||
get_tour_num() {
|
||
if [[ "$1" =~ "Тур №"([0-9]+) ]]; then
|
||
tour_num="${BASH_REMATCH[1]}"
|
||
return 0
|
||
else
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
get_tour_dates() {
|
||
local date_re="[0-9?]{2}\.[0-9?]{2}\.[0-9?]{4}"
|
||
|
||
if [[ "$1" =~ "Время проведения:"\ *($date_re)\ *[-—]\ *($date_re) ]]; then
|
||
date_beg="${BASH_REMATCH[1]}" date_end="${BASH_REMATCH[2]}"
|
||
# Use short dates
|
||
date_beg="${date_beg::5}" date_end="${date_end::5}"
|
||
return 0
|
||
else
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
keep_game_info() {
|
||
local date_re="([0-9?]{2})\.([0-9?]{2})\.([0-9?]{4})"
|
||
local res_re="(0|1|0\.5):(0|1|0\.5)"
|
||
local line="$1" keep=1
|
||
|
||
if [[ "$line" =~ ($date_re)\ *[-—]\ *([^\ ]+)\ *($res_re)?\ *([^\ ]+) ]]; then
|
||
white="${BASH_REMATCH[5]}"
|
||
black="${BASH_REMATCH[9]}"
|
||
result="${BASH_REMATCH[6]}"
|
||
game_date="${BASH_REMATCH[4]}-${BASH_REMATCH[3]}-${BASH_REMATCH[2]}"
|
||
|
||
# If the player was passed as an argument, check if it is his game or not
|
||
if [[ -z "$PLAYER" || "$white" =~ "$PLAYER" || "$black" =~ "$PLAYER" ]]; then
|
||
if $SHOW_ALL; then
|
||
keep=0
|
||
else
|
||
# Keep line if the game is not finished
|
||
[[ -z "$result" ]] && keep=0
|
||
fi
|
||
fi
|
||
fi
|
||
|
||
return $keep
|
||
}
|
||
|
||
store_game_url() {
|
||
local tour=$(printf "%02g" "$tour_num")
|
||
local game_dir="${game_date}-${white}-vs-${black}"
|
||
local pgn_url="${REPO}/${TOURNAMENT}/tours/${tour}/${game_dir}/1.pgn"
|
||
|
||
while read line; do
|
||
# Search for a URL inside PGN file
|
||
[[ "$line" =~ "[Site \""([a-z]+:[^\"]+)"\"]" ]]
|
||
game_url="${BASH_REMATCH[1]}"
|
||
[[ -n "$game_url" ]] && break
|
||
done <<< "$(curl -q --fail --location --silent $pgn_url)"
|
||
}
|
||
|
||
info_output_term() {
|
||
echo -n "$(tput setaf 2)${tour_num} тур "
|
||
echo "$(tput setaf 6)(${date_beg} - ${date_end})$(tput sgr0)"
|
||
|
||
echo -en "$1" | column -t | while IFS= read line; do
|
||
# Highlight player's name
|
||
if [[ -n "$PLAYER" ]]; then
|
||
players=$(grep -o "[^ ]*${PLAYER}[^ ]*" <<< "$line")
|
||
for name in $players; do
|
||
# PLAYER is a part of 'game_url' or 'result'
|
||
[[ "$name" =~ ^http:// || "$name" =~ ^(1-0|0-1|1/2)$ ]] && continue
|
||
|
||
line=$(sed -E "s/(${name})/$(tput setaf 1)\1$(tput sgr0)/g" <<< "$line")
|
||
done
|
||
fi
|
||
|
||
# Highlight result
|
||
line=$(sed -E "s/ (1-0|0-1|1\/2)( |$)/ $(tput setaf 6)\1$(tput sgr0)\2/g" <<< "$line")
|
||
|
||
echo "$line"
|
||
done
|
||
|
||
echo
|
||
}
|
||
|
||
info_output_lor() {
|
||
echo "[b]${tour_num} тур (${date_beg} - ${date_end})[/b]"
|
||
echo "[list]"
|
||
|
||
echo -en "$1" | while read white black result url; do
|
||
[[ -n "$url" ]] && result="[url=${url}]${result}[/url]"
|
||
|
||
echo " [*] [user]${white}[/user] - [user]${black}[/user] ${result}"
|
||
done
|
||
|
||
echo "[/list]"
|
||
echo
|
||
|
||
}
|
||
|
||
info_output_html() {
|
||
echo "<div class=\"tour-info\">"
|
||
echo " <table class=\"table table-condensed\">"
|
||
echo " <caption>"
|
||
echo " <strong>${tour_num} тур (${date_beg} - ${date_end})</strong>"
|
||
echo " </caption>"
|
||
echo " <tbody>"
|
||
|
||
echo -en "$1" | while read white black result url; do
|
||
[[ -n "$url" ]] && result="<a href=\"${url}\">${result}</a>"
|
||
|
||
echo " <tr>"
|
||
echo " <td>${white} - ${black}</td><td class=\"result\">${result}</td>"
|
||
echo " </tr>"
|
||
done
|
||
|
||
echo " </tbody>"
|
||
echo " </table>"
|
||
echo "</div>"
|
||
echo
|
||
}
|
||
|
||
checkargs() {
|
||
if [[ "$OPTARG" =~ ^-[apflhv]$ ]]; then
|
||
echo "Option -${opt}: argument not found" 1>&2
|
||
exit 1
|
||
fi
|
||
if [[ "$opt" == f && ! "$OPTARG" =~ ^(term|html|lor)$ ]]; then
|
||
echo "Incorrect FORMAT specified" 1>&2
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
SHOW_ALL=false
|
||
PLAYER=""
|
||
FORMAT=term
|
||
SHOW_LINK=false
|
||
|
||
while getopts "ap:f:lhv" opt; do
|
||
case "$opt" in
|
||
a) SHOW_ALL=true
|
||
;;
|
||
p) checkargs
|
||
PLAYER="$OPTARG"
|
||
;;
|
||
f) checkargs
|
||
FORMAT="$OPTARG"
|
||
;;
|
||
l) SHOW_LINK=true
|
||
;;
|
||
h) usage && exit 0
|
||
;;
|
||
v) version && exit 0
|
||
;;
|
||
esac
|
||
done
|
||
|
||
shift $(($OPTIND - 1))
|
||
show_tour_sequence "$@"
|
||
|
||
exit 0
|