#!/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=`dirname "$0"` # Specify the tournament here TOURNAMENT= # Version information VERSION="0.5" argv0=${0##*/} function 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 exit "${1:-0}" } function version { exec echo "${argv0}-${VERSION}" } function setup_repo { 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 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 white= black= result= game_date= # Lines with game info local output_lines= while read line; do # Read 'tour_num' if [[ -z $tour_num ]]; then [[ $line =~ ^"Тур №"([0-9]+) ]] && local tour_num=${BASH_REMATCH[1]} continue fi # Read 'date_beg' and 'date_end' if [[ -z $date_beg || -z $date_end ]]; then if [[ $line =~ ^"Время проведения:"\ +$date_re\ +-\ +$date_re ]]; then # Use short dates local date_beg=${BASH_REMATCH[1]}.${BASH_REMATCH[2]} local date_end=${BASH_REMATCH[4]}.${BASH_REMATCH[5]} fi continue fi # 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 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)" echo -en "$output_lines" | 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 =~ ^${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 =~ ^-[apflhv]$ ]] && die "Option -${opt}: argument not found" [[ $opt == f && ! $OPTARG =~ ^(term|html|lor)$ ]] && die "Incorrect FORMAT specified" } FORMAT=term SHOW_ALL=false 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 ;; v) version ;; *) usage 1 ;; esac done shift $(($OPTIND - 1)) setup_repo show_tour_sequence $@ exit 0