#!/bin/sh
# Usage: drawtickets TA1-TAn TB1-TBn ...
#
# Hit "enter" for each additional ticket required.
#
# Category: most disgusting.  Uses only sed, awk, and other typical
#	bash facilities.
#
# Shortcomings: If you generate -all- the possible tickets, it will
#	go into an infinite loop.

# Create temporary directory.  Crudely assume there are no existing
# "drawticket[0-9]*" files in /tmp...

T=/tmp/drawticket$$
trap 'rm -rf $T' 0
mkdir $T

# Parse and validate arguments
# First, validate numeric format for each range: /[0-9]+-[0-9]+/

echo "$@" | tr -s ' ' | tr ' ' '\012' | tr -d ',' > $T/ticketranges
sed -e 's/^[0-9]\+-[0-9]\+$//' < $T/ticketranges | \
	sed -e 's/^..*$/&: Range Error/' | grep '.' > $T/ticketerrs1
if test -s $T/ticketerrs1
then
	cat $T/ticketerrs1
	exit 1
fi

# Sort the ranges numerically to ease later range-overlap error checks.

sort +0n < $T/ticketranges > $T/sortedranges

# Create a file containing a awk program prefix

cat << '---EOF---' > $T/a0
BEGIN	{
	i=0;
---EOF---

# Build an awk program fragment to initialize arrays containing
# the ticket ranges.

sed -e 's/^\([^-]*\)-\(.*\)$/\tb[i]=\1;e[i]=\2;i++;/' < $T/sortedranges > $T/a1

# Create a file containing the awk program suffix.

cat << '---EOF---' > $T/a2
	nranges = i;
	error = 0;
	ntickets = 0;

	# Check for reversed ranges.

	for (i = 0; i < nranges; i++) {
		if (b[i] > e[i]) {
			print b[i] "-" e[i] ": Backwards range";
			error = 1;
		}
		s[i] = e[i] - b[i] + 1;
		ntickets += s[i];
	}

	# Check for overlapping ranges.

	for (i = 1; i < nranges; i++) {
		if (b[i] <= e[i-1]) {
			print b[i-1] "-" e[i-1] "/" b[i] "-" e[i] ": Overlapping ranges";
			error = 1;
		}
	}
	if (error) {
		exit;
	}
	print "Total number of tickets: " ntickets
	ticketseq = 0
	srand(systime())
	printf "Hit Enter to generate ticket:"
	}

	{
	startgen = systime()
	lastwarn = startgen
	generated = 0
	ntries = 0
	while (!generated) {

		# Let the user know if probes are failing...

		if (systime() - lastwarn >= 5) {
			lastwarn = systime()
			printf "Still searching, %d probes, %d seconds\r", \
				ntries, systime() - startgen
		}

		# Generate a ticket number

		ntries++
		ticketindex = int(rand() * ntickets)
		if ((drawn[ticketindex] != 1) && (ticketindex >= 0)) {

			# We haven't generated this one yet, convert
			# from index to ticket number.

			drawn[ticketindex] = 1
			ticketrangeindex = ticketindex
			for (i = 0; i < nranges; i++) {
				if (ticketrangeindex >= s[i]) {
					ticketrangeindex -= s[i]
				} else {
					generated = 1
					ticketseq++
					ticket = ticketrangeindex + b[i]
					print "Ticket " ticketseq ": " ticket
					printf "Hit Enter to generate ticket:"
					next
				}
			}

			# If the random number generator plus rounding
			# runs off the end, no problem, just generate
			# another random number.
		}
	}
	}

END	{
	print
	}
---EOF---
cat $T/a0 $T/a1 $T/a2 > $T/a
awk -f $T/a
