lorchess/schedule

305 lines
9.2 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# Copyright 2014 Vladimir Ivanov <ivvl82@gmail.com>
# Distributed under the terms of the GNU General Public License v2
# REPO_DIR="https://github.com/fat0troll/lorchess"
REPO_DIR=
# Specify the tournament here
TOURNAMENT=
# Version information
VERSION="0.6"
argv0=${0##*/}
function usage {
cat <<EOF
List games on tours of tournament
Usage: $argv0 [options] [tours]
Put the script under the root directory of your repository or set
inner variable REPO_DIR to point to your local or remote GitHub
repository. If the tournament is not the last one (default), store
its sub-directory in inner variable TOURNAMENT.
Tournament tours are restricted to sequence 'tours' given in the
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 all started tours (use '-f' to
see future tours too). By default, only unaccomplished games are
listed.
Options:
-a List accomplished games too
-f Allow to display future tours
-p PLAYER Show game if PLAYER is a part of a player's name
-o 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
exit "${1:-0}"
}
function version {
exec echo "${argv0}-${VERSION}"
}
function setup_repo {
[[ -z $REPO_DIR ]] && REPO_DIR=`dirname "$0"`
CURL_OPTS="-q --fail --location --silent"
# If no tournament given, set it to the last one
if [[ -z $TOURNAMENT ]]; then
if [[ $REPO_DIR =~ ^https://github\.com/(.*) ]]; then
REPO_API="https://api.github.com/repos/${BASH_REMATCH[1]}/contents"
local year=$(curl $CURL_OPTS $REPO_API \
| sed -En "/\"path\":/h;/\"type\": \"dir\"/{g;p;}" \
| sed -En "s|.*\"([0-9]{4})\".*|\1|p" | tail -1)
TOURNAMENT=$(curl $CURL_OPTS ${REPO_API}/${year} \
| sed -En "/\"path\":/h;/\"type\": \"dir\"/{g;p;}" \
| sed -En "s|.*\"(${year}/[0-9]-.*)\".*|\1|p" | tail -1)
REPO_URL="${REPO_DIR}/raw/master"
else
local year_dir=$(ls -1 -d ${REPO_DIR}/[0-9][0-9][0-9][0-9]/ | tail -1)
TOURNAMENT=$(ls -1 -d ${year_dir}[0-9]-*/ | tail -1 \
| sed -E "s|${REPO_DIR}/(.*)|\1|")
# Remove the trailing slash
TOURNAMENT=${TOURNAMENT%/}
# Convert REPO_DIR to an absolute path
[[ ! $REPO_DIR =~ ^/ ]] && REPO_DIR=$(cd $REPO_DIR; pwd)
REPO_URL="file://${REPO_DIR}"
fi
fi
}
function show_tour_sequence {
local tour_seq=$@
# If no tour sequence given, set it to all tours
if [[ -z $tour_seq ]]; then
if [[ $REPO_DIR =~ ^https://github\.com/ ]]; then
tour_seq=$(curl $CURL_OPTS ${REPO_API}/${TOURNAMENT}/tours \
| sed -En "/\"path\":/h;/\"type\": \"dir\"/{g;p;}" \
| sed -En "s|.*\"${TOURNAMENT}/tours/([0-9]{2})\".*|\1|p")
else
tour_seq=$(ls -1 -d ${REPO_DIR}/${TOURNAMENT}/tours/[0-9][0-9]/ \
| sed -E "s|${REPO_DIR}/${TOURNAMENT}/tours/([0-9]{2})/|\1|")
fi
else
# Don't care about the begging of an explicitly specified tour
SHOW_FUTURE=true
fi
for tour in $tour_seq; do
# Change tour numbers: '1' -> '01', '2' -> '02', and so on
tour=$(printf "%02g" $tour)
# *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 tour_info=$(curl $CURL_OPTS --write-out '\n' \
${REPO_URL}/${TOURNAMENT}/tours/${tour}/tour_info)
[[ -n $tour_info ]] && output_tour_info
done
}
function output_tour_info {
local date_re="([0-9?]{2})\.([0-9?]{2})\.([0-9?]{4})"
local res_re="(1-0|1/2|0-1)"
local tour_num= date_beg= date_end=
local white= black= result= game_date=
# Lines with game info
local output_lines=
while read line; do
# Read the number of tour
get_tour_num
# Read the begging and end of tour
get_tour_dates
# Keep game info if needed, and store it in variables 'white',
# 'black', 'result', and 'game_date'
if keep_game_info; then
output_lines+=$(sed -E "s/^$date_re\ +//" <<< "$line")
# Append the link of game to the end of output line
if $SHOW_LINK; then
[[ -n $result ]] && append_game_url
fi
output_lines+="\n"
fi
done <<< "$tour_info"
[[ -n $output_lines ]] && eval info_output_$FORMAT
}
function get_tour_num {
if [[ -z $tour_num ]]; then
[[ $line =~ ^"Тур №"([0-9]+) ]] && tour_num=${BASH_REMATCH[1]}
continue
fi
}
function get_tour_dates {
if [[ -z $date_beg || -z $date_end ]]; then
if [[ $line =~ ^"Время проведения:"\ +($date_re)\ +-\ +($date_re) ]]; then
date_beg=${BASH_REMATCH[1]} date_end=${BASH_REMATCH[5]}
if ! $SHOW_FUTURE; then
# Unknown beginning of tour
[[ $date_beg =~ \? ]] && break
# The date of tour later than today
local date_tour=$(sed -E "s/${date_re}/\3-\2-\1/" <<< $date_beg)
local date_unix=$(date -d $date_tour +%s) this_unix=$(date +%s)
(( date_unix > this_unix )) && break
fi
# Use short dates
date_beg=${date_beg::5} date_end=${date_end::5}
fi
continue
fi
}
function keep_game_info {
local keep=1
if [[ $line =~ ^$date_re\ +([^\ ]+)\ +-\ +([^\ ]+)(\ +$res_re)? ]]; then
white=${BASH_REMATCH[4]} black=${BASH_REMATCH[5]} result=${BASH_REMATCH[7]}
game_date=${BASH_REMATCH[3]}-${BASH_REMATCH[2]}-${BASH_REMATCH[1]}
# 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
}
function append_game_url {
local tour=$(printf "%02g" "$tour_num")
local game_dir=${game_date}-${white}-vs-${black}
local game_url=$(curl $CURL_OPTS \
${REPO_URL}/${TOURNAMENT}/tours/${tour}/${game_dir}/1.pgn \
| grep -Eo "\[Site \"[a-z]+:[^\"]+\"\]" \
| sed -E "s/\[Site \"([a-z]+:[^\"]+)\"\]/\1/")
output_lines+=" $game_url"
}
function info_output_term {
echo -n "$(tput setaf 2)${tour_num} тур "
echo "$(tput setaf 6)(${date_beg} - ${date_end})$(tput sgr0)"
for line in "$(echo -e "$output_lines")"; 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 =~ ^${res_re}$ ]] && continue
line=$(sed -E "s/(${name})/$(tput setaf 1)\1$(tput sgr0)/g" <<< "$line")
done
fi
# Highlight result
line=$(sed -E "s~ ${res_re}( |$)~ $(tput setaf 6)\1$(tput sgr0)\2~g" <<< "$line")
echo "$line"
done
echo
}
function info_output_lor {
echo "[b]${tour_num} тур (${date_beg} - ${date_end})[/b]"
echo "[list]"
echo -en "$output_lines" | while read white hyphen black result url; do
[[ -n $url ]] && result="[url=${url}]${result}[/url]"
echo " [*] [user]${white}[/user] - [user]${black}[/user] ${result}"
done
echo "[/list]"
echo
}
function 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 "$output_lines" | while read white hyphen black result url; do
[[ $result == 1/2 ]] && result=½-½
[[ -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
}
function die {
echo "$@" 1>&2
exit 1
}
function checkargs {
[[ $OPTARG =~ ^-[afpolhv]$ ]] && die "Option -${opt}: argument not found"
[[ $opt == o && ! $OPTARG =~ ^(term|html|lor)$ ]] && die "Incorrect FORMAT specified"
}
FORMAT=term
SHOW_ALL=false
SHOW_FUTURE=false
SHOW_LINK=false
while getopts afp:o:lhv opt; do
case $opt in
a) SHOW_ALL=true
;;
f) SHOW_FUTURE=true
;;
p) checkargs
PLAYER=$OPTARG
;;
o) checkargs
FORMAT=$OPTARG
;;
l) SHOW_LINK=true
;;
h) usage
;;
v) version
;;
*) usage 1
;;
esac
done
shift $(($OPTIND - 1))
setup_repo
show_tour_sequence $@
exit 0