201 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			201 lines
		
	
	
		
			5.2 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
 | 
						|
 | 
						|
REPODIR="`dirname $0`"
 | 
						|
TOURNAMENT="2014/3-fallenleaves"
 | 
						|
 | 
						|
# Config file for players
 | 
						|
ply_ini="${REPODIR}/${TOURNAMENT}/players.ini"
 | 
						|
 | 
						|
# Version information
 | 
						|
VERSION="0.1"
 | 
						|
 | 
						|
argv0="${0##*/}"
 | 
						|
 | 
						|
usage() {
 | 
						|
    cat <<EOF
 | 
						|
Store a chess game played on lichess.org
 | 
						|
 | 
						|
Usage:
 | 
						|
  $argv0 -t <num> <url>
 | 
						|
  $argv0 -h
 | 
						|
  $argv0 -v
 | 
						|
 | 
						|
The first form fills the result of a chess game and stores its PGN
 | 
						|
file. Assumes that the game is available at <url> (lichess.org) and
 | 
						|
corresponds to tournament tour <num>.
 | 
						|
 | 
						|
The second form shows this help output. The third form shows version
 | 
						|
information.
 | 
						|
EOF
 | 
						|
 | 
						|
    exit "${1:-0}"
 | 
						|
}
 | 
						|
 | 
						|
version() {
 | 
						|
    exec echo "${argv0}-${VERSION}"
 | 
						|
}
 | 
						|
 | 
						|
game_get_players() {
 | 
						|
    # Extract players on Lichess
 | 
						|
    local w_lichess=$(sed -En "s/\[White \"([^\"]*)\"\]/\1/p" < "$tmp_pgn")
 | 
						|
    local b_lichess=$(sed -En "s/\[Black \"([^\"]*)\"\]/\1/p" < "$tmp_pgn")
 | 
						|
 | 
						|
    # Get names of white and black players
 | 
						|
    local counter=1 players=()
 | 
						|
    game_parse_config
 | 
						|
    while eval "config_section_player${counter}" 2>/dev/null; do
 | 
						|
        players+=("$name")
 | 
						|
        [[ "$lichess" == "$w_lichess" ]] && white="$name"
 | 
						|
        [[ "$lichess" == "$b_lichess" ]] && black="$name"
 | 
						|
        counter=$((counter+1))
 | 
						|
    done
 | 
						|
    [[ -z "$white" ]] && fix_white_player
 | 
						|
    [[ -z "$black" ]] && fix_black_player
 | 
						|
}
 | 
						|
 | 
						|
game_parse_config() {
 | 
						|
    # Copy player INI file to the temporary location
 | 
						|
    # NOTE: an empty line is added to the file beginning in order to
 | 
						|
    # match the only first occurrence for non-GNU sed
 | 
						|
    echo > "$tmp_ini"
 | 
						|
    cat "$ply_ini" >> "$tmp_ini"
 | 
						|
 | 
						|
    # Remove tabs or spaces around the `='
 | 
						|
    sed -i".prev" -E "s/[[:blank:]]*=[[:blank:]]*/=/g" "$tmp_ini"
 | 
						|
 | 
						|
    # Transform section labels into function declaration
 | 
						|
    sed -i".prev" -E "1,/^\[.*\]/s/^\[([^]]*)\]/config_section_\1() {/g" "$tmp_ini"
 | 
						|
    sed -i".prev" -E "s/^\[([^]]*)\]/}\\"$'\n'"config_section_\1() {/g" "$tmp_ini"
 | 
						|
    echo -e "\n}" >> "$tmp_ini"
 | 
						|
 | 
						|
    # Load the file
 | 
						|
    source "$tmp_ini"
 | 
						|
}
 | 
						|
 | 
						|
fix_white_player() {
 | 
						|
    local number
 | 
						|
    echo "Lichess player '${w_lichess}' not found."
 | 
						|
    choose_player
 | 
						|
    white="${players[$number]}"
 | 
						|
}
 | 
						|
 | 
						|
fix_black_player() {
 | 
						|
    local number
 | 
						|
    echo "Lichess player '${b_lichess}' not found."
 | 
						|
    choose_player
 | 
						|
    black="${players[$number]}"
 | 
						|
}
 | 
						|
 | 
						|
choose_player() {
 | 
						|
    echo "Please choose a proper name from the list below:"
 | 
						|
    for ((i=0; i<${#players[@]}; ++i)); do
 | 
						|
        echo "$((i+1)) ${players[$i]}"
 | 
						|
    done \
 | 
						|
        | column -t \
 | 
						|
        | sed -E "s/^([0-9]*)/$(tput setaf 6)\1$(tput sgr0)/g" # highlight number
 | 
						|
    echo -n "Put number> "
 | 
						|
    read number
 | 
						|
 | 
						|
    if (( "$number" < 1 || "$number" > ${#players[@]} )); then
 | 
						|
        die "Incorrect player number."
 | 
						|
    fi
 | 
						|
    number=$((number-1))
 | 
						|
}
 | 
						|
 | 
						|
game_add_to_repo() {
 | 
						|
    local date_re="[0-9?]{2}\.[0-9?]{2}\.[0-9?]{4}"
 | 
						|
    # Check if the tour number is correct
 | 
						|
    local correct=false
 | 
						|
    while IFS= read line; do
 | 
						|
        if [[ "$line" =~ ${date_re}\ *[-—]\ *${white}\ *${black} ]]; then
 | 
						|
            correct=true
 | 
						|
            break
 | 
						|
        fi
 | 
						|
    done < "$tour_info"
 | 
						|
    if ! $correct; then
 | 
						|
        die "Game '${white} vs. ${black}' not found in ${tour_info}."
 | 
						|
    fi
 | 
						|
 | 
						|
    [[ -d "$pgn_dir" ]] && die "Directory ${pgn_dir} already exist."
 | 
						|
    echo "Creating directory ${pgn_dir}..."
 | 
						|
    mkdir -p "$pgn_dir"
 | 
						|
 | 
						|
    echo "Storing PGN file..."
 | 
						|
    cp "$tmp_pgn" "${pgn_dir}/1.pgn"
 | 
						|
 | 
						|
    echo "Updating tour_info..."
 | 
						|
    local game_date="${pgn_date:8:2}.${pgn_date:5:2}.${pgn_date::4}"
 | 
						|
    local result=$(sed -En "s/\[Result \"([^\"]*)\"\]/\1/p" < "$tmp_pgn")
 | 
						|
    case "$result" in
 | 
						|
        "1-0")     result="1:0" ;;
 | 
						|
        "0-1")     result="0:1" ;;
 | 
						|
        "1/2-1/2") result="0.5:0.5" ;;
 | 
						|
    esac
 | 
						|
 | 
						|
    sed -i".orig" \
 | 
						|
        -E "s/${date_re}( *[-—] *)${white} *${black}/${game_date}\1${white} ${result} ${black}/g" \
 | 
						|
        "$tour_info"
 | 
						|
    rm "${tour_info}.orig"
 | 
						|
}
 | 
						|
 | 
						|
game_git_commit() {
 | 
						|
    git pull
 | 
						|
    git add "${pgn_dir}/1.pgn" "$tour_info"
 | 
						|
    git commit -m "Tour ${TOUR#0}: ${white} vs. ${black}."
 | 
						|
    git push
 | 
						|
}
 | 
						|
 | 
						|
die() {
 | 
						|
    echo "$@" 1>&2
 | 
						|
    exit 1
 | 
						|
}
 | 
						|
 | 
						|
checkargs() {
 | 
						|
    if [[ "$opt" == t && "$OPTARG" =~ ^[0-9]+$ ]]; then
 | 
						|
        TOUR=$(printf "%02g" "$OPTARG")
 | 
						|
    fi
 | 
						|
}
 | 
						|
 | 
						|
TOUR=""
 | 
						|
while getopts "t:hv" opt; do
 | 
						|
    case "$opt" in
 | 
						|
        t) checkargs ;;
 | 
						|
        h) usage ;;
 | 
						|
        v) version ;;
 | 
						|
        *) usage 1 ;;
 | 
						|
    esac
 | 
						|
done
 | 
						|
 | 
						|
shift $(($OPTIND - 1))
 | 
						|
# For now, tour number should be given explicitly
 | 
						|
[[ -z "$TOUR" || -z "$1" ]] && usage 1
 | 
						|
 | 
						|
tour_info="${REPODIR}/${TOURNAMENT}/tours/${TOUR}/tour_info"
 | 
						|
[[ ! -f "$tour_info" ]] && die "File ${tour_info} not found."
 | 
						|
 | 
						|
# Temporary files
 | 
						|
tmp_ini=$(mktemp -t `basename $ply_ini`.XXXXXX)
 | 
						|
tmp_pgn=$(mktemp -t pgn.XXXXXX)
 | 
						|
trap "rm ${tmp_ini} ${tmp_ini}.prev ${tmp_pgn}" EXIT
 | 
						|
 | 
						|
# Download PGN file
 | 
						|
[[ "$1" =~ ^(http://[^/]*)/([^/]*) ]]
 | 
						|
pgn_url="${BASH_REMATCH[1]}/${BASH_REMATCH[2]::8}/pgn"
 | 
						|
curl -q --fail --location --silent "$pgn_url" > "$tmp_pgn" \
 | 
						|
    || die "PGN file not found."
 | 
						|
 | 
						|
white="" black=""
 | 
						|
game_get_players
 | 
						|
 | 
						|
# Extract the game date from PGN
 | 
						|
pgn_date=$(sed -En "s/\[Date \"([^\"]*)\"\]/\1/p" < "$tmp_pgn")
 | 
						|
pgn_date=$(tr '.' '-' <<< "$pgn_date")
 | 
						|
pgn_dir="${REPODIR}/${TOURNAMENT}/tours/${TOUR}/${pgn_date}-${white}-vs-${black}"
 | 
						|
 | 
						|
game_add_to_repo
 | 
						|
game_git_commit
 | 
						|
 | 
						|
exit 0
 |