313 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			313 lines
		
	
	
		
			9.5 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_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 [[ $REPO_DIR =~ ^https://github\.com/(.*) ]]; then
 | 
						||
        REPO_API="https://api.github.com/repos/${BASH_REMATCH[1]}/contents"
 | 
						||
        REPO_URL="${REPO_DIR}/raw/master"
 | 
						||
 | 
						||
        # If no tournament given, set it to the last one
 | 
						||
        if [[ -z $TOURNAMENT ]]; then
 | 
						||
            local year=$(curl $CURL_OPTS $REPO_API \
 | 
						||
                | sed -En "/\"path\":/h;/\"type\": \"dir\"/ \
 | 
						||
                    {g;s|.*\"([0-9]{4})\".*|\1|p;}" | tail -1)
 | 
						||
            TOURNAMENT=$(curl $CURL_OPTS ${REPO_API}/${year} \
 | 
						||
                | sed -En "/\"path\":/h;/\"type\": \"dir\"/ \
 | 
						||
                    {g;s|.*\"(${year}/[0-9]-.*)\".*|\1|p;}" | tail -1)
 | 
						||
        fi
 | 
						||
    else
 | 
						||
        # Convert REPO_DIR to an absolute path
 | 
						||
        [[ ! $REPO_DIR =~ ^/ ]] && REPO_DIR=$(cd $REPO_DIR; pwd)
 | 
						||
 | 
						||
        REPO_URL="file://${REPO_DIR}"
 | 
						||
 | 
						||
        # If no tournament given, set it to the last one
 | 
						||
        if [[ -z $TOURNAMENT ]]; then
 | 
						||
            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|")
 | 
						||
        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;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 score_re="(1|½|0|\+|−)"
 | 
						||
    local res_re="${score_re}-${score_re}"
 | 
						||
    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
 | 
						||
                [[ $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 =~ \? ]] && exit 0
 | 
						||
 | 
						||
                if date --version >/dev/null 2>&1; then
 | 
						||
                    local date_beg_gnu=$(sed -E "s/${date_re}/\3-\2-\1/" <<< $date_beg)
 | 
						||
                    local date_tour=$(date -d $date_beg_gnu +%s)
 | 
						||
                else
 | 
						||
                    local date_beg_bsd=$(sed -E "s/${date_re}/-v\3y -v\2m -v\1d/" <<< $date_beg)
 | 
						||
                    local date_tour=$(date $date_beg_bsd +%s)
 | 
						||
                fi
 | 
						||
                local date_this=$(date +%s)
 | 
						||
 | 
						||
                # The date of tour later than today
 | 
						||
                (( date_tour > date_this )) && exit 0
 | 
						||
            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]}-${BASH_REMATCH[8]}
 | 
						||
        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
 | 
						||
                [[ $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 \
 | 
						||
        | sed -En "s/\[Site \"([a-z]+:[^\"]+)\"\]/\1/p")
 | 
						||
    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)/" <<< "$line")
 | 
						||
            done
 | 
						||
        fi
 | 
						||
 | 
						||
        # Highlight result
 | 
						||
        line=$(sed -E "s/ ${res_re}( |$)/ $(tput setaf 6)\1-\2$(tput sgr0)\3/" <<< "$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
 | 
						||
        [[ -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
 |