1
Fork 0

Script 'game-add': small but useful improvements made.

master
vonavi 2014-12-10 23:09:24 +03:00
parent 75363e622c
commit 42f22c274e
1 changed files with 72 additions and 79 deletions

151
game-add
View File

@ -20,7 +20,7 @@ function usage {
Store chess games played on lichess.org Store chess games played on lichess.org
Usage: Usage:
$argv0 [options] -t <num> [<url>] $argv0 [options] -t <num> <url>...
$argv0 -h $argv0 -h
$argv0 -v $argv0 -v
@ -28,7 +28,7 @@ Usage:
inner variable REPO_DIR to it. If the tournament is not the last one inner variable REPO_DIR to it. If the tournament is not the last one
(default), store its sub-directory in inner variable TOURNAMENT. (default), store its sub-directory in inner variable TOURNAMENT.
The first form fills the results of chess games and stores its PGN The first form fills the results of chess games and stores their PGN
files, assuming that all the games were played by the same pair of files, assuming that all the games were played by the same pair of
players on tour <num> of the tournament. The PGN files are sorted by players on tour <num> of the tournament. The PGN files are sorted by
their timestamps, unless '-u' is set. Each game should be available their timestamps, unless '-u' is set. Each game should be available
@ -100,12 +100,47 @@ function game_tmp_pgns {
$SORT_GAMES && TMP_PGN_FILES=$(xargs -n1 <<< "$TMP_PGN_FILES" | sort | xargs) $SORT_GAMES && TMP_PGN_FILES=$(xargs -n1 <<< "$TMP_PGN_FILES" | sort | xargs)
} }
function game_get_players { function game_get_info {
# Make an associative array from Lichess nicks to players' names # Get the names of players, whose games are in PGN files
declare -A NAMES=()
game_assoc_names
local ply_names= local ply_names=
game_get_names
# Select the names of two players
local players=( $(echo -en "$ply_names" | sort -u) )
[[ ${#players[@]} == 2 ]] || die "Players of the games are not the same."
# Find the white and black players
local line0=$(grep " ${players[0]} " $tour_info)
local line1=$(grep " ${players[1]} " $tour_info)
[[ $line0 == $line1 ]] \
|| die "No game between ${players[0]} and ${players[1]} found in ${tour_info}."
[[ $line0 =~ ^((${date_re})\ +([^\ ]+)\ +-\ +([^\ ]+))(.*)$ ]]
white=${BASH_REMATCH[3]}
black=${BASH_REMATCH[4]}
# Additional information about the game record
rec_length=${#BASH_REMATCH[1]}
game_date=${BASH_REMATCH[2]}
res_old=$(xargs <<< ${BASH_REMATCH[5]})
game_validate
if ! $ADD_GAMES || [[ $game_date =~ \? ]]; then
local fst_pgn=$(awk '{print $1}' <<< "$TMP_PGN_FILES")
local date=$(sed -En "s/\[Date \"([^\"]*)\"\]/\1/p" $fst_pgn)
game_date=${date:8:2}.${date:5:2}.${date::4}
fi
}
function game_get_names {
# Make an associative array from Lichess nicks to players' names
game_parse_config
local sections=$(grep -o "config_section_player[0-9]*" $tmp_ini)
declare -A NAMES=()
for sect in $sections; do
eval $sect
NAMES+=( [$lichess]=$name )
done
for pgn in $TMP_PGN_FILES; do for pgn in $TMP_PGN_FILES; do
# Extract players on Lichess # Extract players on Lichess
local wt_lichess=$(sed -En "s/\[White \"([^\"]*)\"\]/\1/p" $pgn) local wt_lichess=$(sed -En "s/\[White \"([^\"]*)\"\]/\1/p" $pgn)
@ -114,29 +149,6 @@ function game_get_players {
game_add_player $wt_lichess game_add_player $wt_lichess
game_add_player $bk_lichess game_add_player $bk_lichess
done done
# Select the names of two players
local players=( $(echo -en "$ply_names" | sort -u) )
[[ ${#players[@]} == 2 ]] || die "Players of the games are not the same."
# Find the white and black players
local line=$(grep -E "( ${players[0]} | ${players[1]} )" $tour_info)
[[ -n $line && $(wc -l <<< "$line") == 1 ]] \
|| die "No game between ${players[0]} and ${players[1]} found in ${tour_info}."
[[ $line =~ ^${date_re}\ +([^\ ]+)\ +-\ +([^\ ]+)(.*)$ ]]
white=${BASH_REMATCH[1]}
black=${BASH_REMATCH[2]}
res_old=$(xargs <<< ${BASH_REMATCH[3]})
game_validate
}
function game_assoc_names {
game_parse_config
local sections=$(grep -o "config_section_player[0-9]*" $tmp_ini)
for sect in $sections; do
eval $sect
NAMES+=( [$lichess]=$name )
done
} }
function game_parse_config { function game_parse_config {
@ -167,8 +179,8 @@ function game_add_player {
local lichess_ply=$1 local lichess_ply=$1
local ply=${NAMES[$lichess_ply]} local ply=${NAMES[$lichess_ply]}
while [[ ! " ${NAMES[@]} " =~ \ $ply\ ]]; do while [[ ! " ${NAMES[@]} " =~ \ $ply\ ]]; do
echo "The list of players:" echo -n "The list of players:"
echo "${NAMES[@]}" | tr ' ' '\n' | sed "s/^/$(tput setaf 6)*$(tput sgr0) /" sed "s/ /\\"$'\n'"$(tput setaf 6)*$(tput sgr0) /g" <<< " ${NAMES[@]}"
echo -n "Type the name of ${lichess_ply}> " echo -n "Type the name of ${lichess_ply}> "
read ply read ply
done done
@ -177,21 +189,25 @@ function game_add_player {
function game_validate { function game_validate {
# By default, other games between the players are not allowed # By default, other games between the players are not allowed
if [[ -n $res_old ]]; then if ! $ADD_GAMES && ! $CLEANUP_GAMES; then
$ADD_GAMES || $CLEANUP_GAMES || die "Results of some games already stored." if ! [[ $game_date =~ \? && -z $res_old ]]; then
local index=$(wc -w <<< "$res_old") die "Some games between ${white} and ${black} already recorded."
else fi
local index=0
fi fi
# Players' sides should interchange # Players' sides should interchange
local length=$(echo -en "$ply_names" | wc -l) local length=$(echo -en "$ply_names" | wc -l)
if $ADD_GAMES && [[ -n $res_old ]]; then
local residue=$(( $(wc -w <<< "$res_old") % 2 ))
else
local residue=0
fi
local ply_ordered= local ply_ordered=
for ((i = index; i < length; i++)); do for ((i = 0; i < length; i++)); do
if (( i % 2 == 1 )); then if (( i % 2 == residue )); then
ply_ordered="${white}\n${black}\n" ply_ordered+="${white}\n"
else else
ply_ordered="${black}\n${white}\n" ply_ordered+="${black}\n"
fi fi
done done
if [[ "$ply_names" != "$ply_ordered" ]]; then if [[ "$ply_names" != "$ply_ordered" ]]; then
@ -203,7 +219,6 @@ function game_validate {
} }
function game_store_pgns { function game_store_pgns {
local pgn_index=0
game_dir=$(ls -1 -d 2>/dev/null \ game_dir=$(ls -1 -d 2>/dev/null \
${REPO_DIR}/${TOURNAMENT}/tours/${TOUR}/*-${white}-vs-${black}) ${REPO_DIR}/${TOURNAMENT}/tours/${TOUR}/*-${white}-vs-${black})
if $CLEANUP_GAMES && [[ -n $game_dir ]]; then if $CLEANUP_GAMES && [[ -n $game_dir ]]; then
@ -211,46 +226,29 @@ function game_store_pgns {
game_dir= game_dir=
fi fi
local pgn_index=0
if [[ -z $game_dir ]]; then if [[ -z $game_dir ]]; then
# Get the game date local date=${game_date:6:4}-${game_date:3:2}-${game_date::2}
date= game_dir=${REPO_DIR}/${TOURNAMENT}/tours/${TOUR}/${date}-${white}-vs-${black}
game_get_date
game_date=$(tr '.' '-' <<< "$date")
game_dir=${REPO_DIR}/${TOURNAMENT}/tours/${TOUR}/${game_date}-${white}-vs-${black}
echo "Creating directory ${game_dir}..." echo "Creating directory ${game_dir}..."
mkdir "$game_dir" mkdir "$game_dir"
else else
$ADD_GAMES || die "Directory ${game_dir} already exist." $ADD_GAMES || die "Directory ${game_dir} already exist."
local old_pgns=$(ls -1 -p 2>/dev/null ${game_dir}/[0-9]*.pgn | grep -v "/$") local old_pgns=$(ls -1 -p 2>/dev/null ${game_dir}/*.pgn)
[[ -n $old_pgns ]] && pgn_index=$(wc -l <<< "$old_pgns") [[ -n $old_pgns ]] && pgn_index=$(wc -l <<< "$old_pgns")
fi fi
for pgn in $TMP_PGN_FILES; do for pgn in $TMP_PGN_FILES; do
(( pgn_index += 1 )) (( pgn_index += 1 ))
echo "Storing file ${game_dir}/${pgn_index}.pgn..."
cp $pgn ${game_dir}/${pgn_index}.pgn cp $pgn ${game_dir}/${pgn_index}.pgn
done done
} }
function game_get_date {
local fst_pgn others
read fst_pgn others <<< "$TMP_PGN_FILES"
date=$(sed -En "s/\[Date \"([^\"]*)\"\]/\1/p" $fst_pgn)
}
function game_update_info { function game_update_info {
local length_max=0 # Get the maximal length of game records, excepting results
while read line; do local length_max=$(grep -Eo "^${date_re} +[^ ]+ +- +[^ ]+" $tour_info \
[[ $line =~ ^((${date_re})\ +([^\ ]+)\ +-\ +([^\ ]+)) ]] | awk '{print length}' | sort -nr | head -1)
# Get the maximal length of game records, excepting results
local length=${#BASH_REMATCH[1]}
(( $length > $length_max )) && length_max=$length
if [[ ${BASH_REMATCH[3]} == $white && ${BASH_REMATCH[4]} == $black ]]; then
local length_rec=${#BASH_REMATCH[1]} game_date=${BASH_REMATCH[2]}
fi
done < $tour_info
local result= local result=
for pgn in $TMP_PGN_FILES; do for pgn in $TMP_PGN_FILES; do
@ -258,18 +256,11 @@ function game_update_info {
[[ $res == 1/2-1/2 ]] && res=1/2 # representation of a draw [[ $res == 1/2-1/2 ]] && res=1/2 # representation of a draw
result+=" $res" result+=" $res"
done done
$ADD_GAMES && [[ -n $res_old ]] && result=" ${res_old}${result}"
if $ADD_GAMES && [[ -n $res_old ]]; then local spaces=$(( length_max - rec_length ))
result=" ${res_old}${result}"
else
date=
game_get_date
game_date=${date:8:2}.${date:5:2}.${date::4}
fi
local spaces=$(( length_max - length_rec ))
local sep=$(printf "%${spaces}s" " ") local sep=$(printf "%${spaces}s" " ")
echo "Updating ${tour_info}..." echo "Updating file ${tour_info}..."
sed -E -i.orig \ sed -E -i.orig \
"s|^${date_re}( +${white} +- +${black}).*|${game_date}\1${sep}${result}|" \ "s|^${date_re}( +${white} +- +${black}).*|${game_date}\1${sep}${result}|" \
$tour_info $tour_info
@ -277,7 +268,7 @@ function game_update_info {
} }
function game_git_commit { function game_git_commit {
git --git-dir=${REPO_DIR}/.git add ${game_dir}/[0-9]*.pgn $tour_info git --git-dir=${REPO_DIR}/.git add ${game_dir}/*.pgn $tour_info
git --git-dir=${REPO_DIR}/.git commit -m "Tour ${TOUR#0}: ${white} vs. ${black}." git --git-dir=${REPO_DIR}/.git commit -m "Tour ${TOUR#0}: ${white} vs. ${black}."
git --git-dir=${REPO_DIR}/.git push git --git-dir=${REPO_DIR}/.git push
} }
@ -310,11 +301,13 @@ done
shift $(($OPTIND - 1)) shift $(($OPTIND - 1))
# For now, tour number should be given explicitly # For now, tour number should be given explicitly
[[ -z $TOUR || $# == 0 ]] && usage 1 [[ -z $TOUR || $# == 0 ]] && usage 1
# Don't add and clean up games simultaneously
$ADD_GAMES && $CLEANUP_GAMES && usage 1
game_setup game_setup
git --git-dir=${REPO_DIR}/.git pull # synchronize the repository git --git-dir=${REPO_DIR}/.git pull # synchronize the repository
game_tmp_pgns $@ game_tmp_pgns $@
game_get_players game_get_info
game_store_pgns game_store_pgns
game_update_info game_update_info
game_git_commit game_git_commit