#!/usr/bin/env bash # Copyright 2015 Vladimir Ivanov # Distributed under the terms of the GNU General Public License v2 REPO_DIR= # Specify the tournament here TOURNAMENT= # Version information VERSION="0.1" argv0=${0##*/} # Fix the notation of decimal point export LANG=en_US.UTF-8 function usage { cat <1; --range )); do # Peek a random position from 0 to `range' local rand_value=$RANDOM local norm_rand_value=$(bc -l <<< "($rand_value / 32768) * $range") local rand_idx=$(printf "%.0f" $norm_rand_value) # Place the value at the position to the end of range local tmp=${rand_array[range]} rand_array[range]=${rand_array[rand_idx]} rand_array[rand_idx]=$tmp done # Randomize the order of players for (( idx=0; idx<${#rand_array[@]}; ++idx )); do local rand_idx=${rand_array[idx]} NAMES[idx]=${TMP_NAMES[rand_idx]} done echo "$(tput setaf 2)New randomized list of players:$(tput sgr0)" for (( idx=0; idx<${#NAMES[@]}; ++idx )); do echo "$(tput setaf 2)$(( idx+1 )).$(tput sgr0) ${NAMES[idx]}" done rr_update_ini else NAMES=( ${TMP_NAMES[@]} ) fi } function rr_update_ini { local answer echo -n "Update 'players.ini'? (Y/n)> " read answer [[ $answer =~ ^(Y|y|Yes|yes)$ ]] || return # Extract INI blocks from config declare -a ini_array local ini_block= while read line; do if [[ $line =~ ^\[player[0-9]+\]$ ]]; then # Close the previous INI block if [[ -n $ini_block ]]; then ini_array+=( "$ini_block" ) ini_block= fi fi [[ $line =~ ^\ *$ ]] || ini_block+="${line}\n" done <"$ply_ini" [[ -n $ini_block ]] && ini_array+=( "$ini_block" ) echo "Updating ${ply_ini}..." mv "$ply_ini" "${ply_ini}.orig" for (( idx=0; idx<${#rand_array[@]}; ++idx )); do local rand_idx=${rand_array[idx]} echo -en "${ini_array[rand_idx]}" \ | sed "s/^\[player$(( rand_idx+1 ))\]$/[player$(( idx+1 ))]/" >> "$ply_ini" (( idx < ${#rand_array[@]} - 1 )) && echo >> "$ply_ini" done } function rr_gen_table1 { local ply_num= idx= next_idx= # Number of table cells local cell_total=$(bc <<< "$PLY_MAX * ($PLY_MAX + 1)") # First pass: fill the table with 'PLY_MAX' for (( round=0; round < PLY_MAX; ++round )); do idx=$(bc <<< "($PLY_MAX + 1) * $round + ($round + 1) % 2") TABLE1[idx]=$PLY_MAX done # Second pass: fill the table with players in ascending order ply_num=0 for (( pair=0; pair < cell_total/2; ++pair )); do idx=$(( 2 * pair )) next_idx=$(( 2 * pair + 1 )) if [[ -z ${TABLE1[idx]} ]]; then TABLE1[idx]=$ply_num else TABLE1[next_idx]=$ply_num fi ply_num=$(( (ply_num + 1) % PLY_MAX )) done # Second pass: fill the table with players in descending order ply_num=$(( PLY_MAX - 1 )) for (( idx=0; idx < cell_total; ++idx )); do if [[ -z ${TABLE1[idx]} ]]; then TABLE1[idx]=$ply_num ply_num=$(( PLY_MAX - 1 - (PLY_MAX - ply_num) % PLY_MAX )) fi done } function rr_gen_table2 { # Number of table cells local cell_total=$(bc <<< "$PLY_MAX * ($PLY_MAX + 1)") # Alter white and black players in the second half of tournament for (( pair=0; pair < cell_total/2; ++pair )); do local idx=$(( 2 * pair )) local next_idx=$(( 2 * pair + 1 )) TABLE2+=( ${TABLE1[next_idx]} ${TABLE1[idx]} ) done } function rr_gen_tours { declare -a tour_table local tour_num=0 ply_num=0 for ply in ${TABLE1[@]} ${TABLE2[@]}; do tour_table+=($ply) (( ply_num++ )) if (( ply_num > PLY_MAX )); then rr_gen_tour_info # Start new tour (( tour_num++ )) ply_num=0 tour_table=() fi done } function rr_gen_tour_info { # Change tour numbers: '1' -> '01', '2' -> '02', and so on local tour=$(printf "%02g" $(( tour_num + 1 ))) mkdir -p "${REPO_DIR}/${TOURNAMENT}/tours/${tour}" local tour_info=${REPO_DIR}/${TOURNAMENT}/tours/${tour}/tour_info echo "Generating ${tour_info}..." # Create header ( echo "Тур №$(( tour_num + 1 ))" echo "==========" echo echo "Время проведения: ??.??.???? - ??.??.????" echo ) >> "$tour_info" # Create pairs for (( pair=0; pair < (PLY_MAX+1)/2; ++pair )); do local idx=$(( 2 * pair )) local next_idx=$(( 2 * pair + 1 )) local white_ply=${tour_table[idx]} local black_ply=${tour_table[next_idx]} echo "${NAMES[white_ply]} - ${NAMES[black_ply]}" done | column -t | sed "s/ - /-/; s/^/??.??.???? /" >> "$tour_info" } function die { echo "$@" >&2 exit 1 } RAND_ORDER=false while getopts rhv opt; do case $opt in r) RAND_ORDER=true ;; h) usage ;; v) version ;; *) usage 1 ;; esac done shift $(( $OPTIND - 1 )) rr_setup declare -a NAMES rr_get_names # The number of players should be even PLY_MAX=$(( ${#NAMES[@]} + ${#NAMES[@]} % 2 - 1 )) declare -a TABLE1 TABLE2 rr_gen_table1 # first half of tournament rr_gen_table2 # second half of tournament rr_gen_tours exit 0