#!/usr/bin/ruby

print "This script attempts to prove if there is one logical order per set.\n"

testcase = {}

# add your logical ordering as a 'test'. the script will shuffle it and attempt
# to return it to the original configuration.

# simple replica = 8, this example is 8 because of brick1 or brick2 count
testcase['test1'] = []
testcase['test1'].push( {'host' => 'annex1.example.com', 'path' => '/data/brick1'} )
testcase['test1'].push( {'host' => 'annex2.example.com', 'path' => '/data/brick1'} )
testcase['test1'].push( {'host' => 'annex3.example.com', 'path' => '/data/brick1'} )
testcase['test1'].push( {'host' => 'annex4.example.com', 'path' => '/data/brick1'} )
testcase['test1'].push( {'host' => 'annex5.example.com', 'path' => '/data/brick1'} )
testcase['test1'].push( {'host' => 'annex6.example.com', 'path' => '/data/brick1'} )
testcase['test1'].push( {'host' => 'annex7.example.com', 'path' => '/data/brick1'} )
testcase['test1'].push( {'host' => 'annex8.example.com', 'path' => '/data/brick1'} )

testcase['test1'].push( {'host' => 'annex1.example.com', 'path' => '/data/brick2'} )
testcase['test1'].push( {'host' => 'annex2.example.com', 'path' => '/data/brick2'} )
testcase['test1'].push( {'host' => 'annex3.example.com', 'path' => '/data/brick2'} )
testcase['test1'].push( {'host' => 'annex4.example.com', 'path' => '/data/brick2'} )
testcase['test1'].push( {'host' => 'annex5.example.com', 'path' => '/data/brick2'} )
testcase['test1'].push( {'host' => 'annex6.example.com', 'path' => '/data/brick2'} )
testcase['test1'].push( {'host' => 'annex7.example.com', 'path' => '/data/brick2'} )
testcase['test1'].push( {'host' => 'annex8.example.com', 'path' => '/data/brick2'} )

# replica = 4
testcase['test2'] = []
testcase['test2'].push( {'host' => 'annex1.example.com', 'path' => '/data/brick1'} )
testcase['test2'].push( {'host' => 'annex2.example.com', 'path' => '/data/brick1'} )
testcase['test2'].push( {'host' => 'annex3.example.com', 'path' => '/data/brick1'} )
testcase['test2'].push( {'host' => 'annex4.example.com', 'path' => '/data/brick1'} )

testcase['test2'].push( {'host' => 'annex1.example.com', 'path' => '/data/brick2'} )
testcase['test2'].push( {'host' => 'annex2.example.com', 'path' => '/data/brick2'} )
testcase['test2'].push( {'host' => 'annex3.example.com', 'path' => '/data/brick2'} )
testcase['test2'].push( {'host' => 'annex4.example.com', 'path' => '/data/brick2'} )

testcase['test2'].push( {'host' => 'annex1.example.com', 'path' => '/data/brick3'} )
testcase['test2'].push( {'host' => 'annex2.example.com', 'path' => '/data/brick3'} )
testcase['test2'].push( {'host' => 'annex3.example.com', 'path' => '/data/brick3'} )
testcase['test2'].push( {'host' => 'annex4.example.com', 'path' => '/data/brick3'} )

testcase['test2'].push( {'host' => 'annex1.example.com', 'path' => '/data/brick4'} )
testcase['test2'].push( {'host' => 'annex2.example.com', 'path' => '/data/brick4'} )
testcase['test2'].push( {'host' => 'annex3.example.com', 'path' => '/data/brick4'} )
testcase['test2'].push( {'host' => 'annex4.example.com', 'path' => '/data/brick4'} )

# chained configuration replica=3 (not recommended)
testcase['test3'] = []
testcase['test3'].push( {'host' => 'annex1.example.com', 'path' => '/data/brick1'} )
testcase['test3'].push( {'host' => 'annex2.example.com', 'path' => '/data/brick1'} )
testcase['test3'].push( {'host' => 'annex3.example.com', 'path' => '/data/brick1'} )

testcase['test3'].push( {'host' => 'annex4.example.com', 'path' => '/data/brick2'} )
testcase['test3'].push( {'host' => 'annex1.example.com', 'path' => '/data/brick2'} )
testcase['test3'].push( {'host' => 'annex2.example.com', 'path' => '/data/brick2'} )

testcase['test3'].push( {'host' => 'annex3.example.com', 'path' => '/data/brick3'} )
testcase['test3'].push( {'host' => 'annex4.example.com', 'path' => '/data/brick3'} )
testcase['test3'].push( {'host' => 'annex1.example.com', 'path' => '/data/brick3'} )

testcase['test3'].push( {'host' => 'annex2.example.com', 'path' => '/data/brick4'} )
testcase['test3'].push( {'host' => 'annex3.example.com', 'path' => '/data/brick4'} )
testcase['test3'].push( {'host' => 'annex4.example.com', 'path' => '/data/brick4'} )

# replica = 2, odd server count. note: without padding, this fails
testcase['test4'] = []
testcase['test4'].push( {'host' => 'annex1.example.com', 'path' => '/data/brick01'} )
testcase['test4'].push( {'host' => 'annex2.example.com', 'path' => '/data/brick01'} )

testcase['test4'].push( {'host' => 'annex3.example.com', 'path' => '/data/brick02'} )
testcase['test4'].push( {'host' => 'annex4.example.com', 'path' => '/data/brick02'} )

testcase['test4'].push( {'host' => 'annex5.example.com', 'path' => '/data/brick03'} )
testcase['test4'].push( {'host' => 'annex1.example.com', 'path' => '/data/brick03'} )

testcase['test4'].push( {'host' => 'annex2.example.com', 'path' => '/data/brick04'} )
testcase['test4'].push( {'host' => 'annex3.example.com', 'path' => '/data/brick04'} )

testcase['test4'].push( {'host' => 'annex4.example.com', 'path' => '/data/brick05'} )
testcase['test4'].push( {'host' => 'annex5.example.com', 'path' => '/data/brick05'} )

testcase['test4'].push( {'host' => 'annex1.example.com', 'path' => '/data/brick06'} )
testcase['test4'].push( {'host' => 'annex2.example.com', 'path' => '/data/brick06'} )

testcase['test4'].push( {'host' => 'annex3.example.com', 'path' => '/data/brick07'} )
testcase['test4'].push( {'host' => 'annex4.example.com', 'path' => '/data/brick07'} )

testcase['test4'].push( {'host' => 'annex5.example.com', 'path' => '/data/brick08'} )
testcase['test4'].push( {'host' => 'annex1.example.com', 'path' => '/data/brick08'} )

testcase['test4'].push( {'host' => 'annex2.example.com', 'path' => '/data/brick09'} )
testcase['test4'].push( {'host' => 'annex3.example.com', 'path' => '/data/brick09'} )

testcase['test4'].push( {'host' => 'annex4.example.com', 'path' => '/data/brick10'} )
testcase['test4'].push( {'host' => 'annex5.example.com', 'path' => '/data/brick10'} )


tests = testcase.clone	# copy

result = {}

# apologies if the ruby is not optimal, i'm a puppet expert, not a ruby one :P
tests.keys.each do |group|

	tests[group] = tests[group].shuffle	# just to prove the algorithm works...

	collect = {}
	tests[group].each do |x|
		key = x['host']
		val = x['path']

		if not collect.has_key?(key)
			collect[key] = []	# initialize
		end

		collect[key].push(val)	# save in array
		# TODO: ensure this array is always sorted (we could also do this after
		# or always insert elements in the correct sorted order too :P)
		collect[key] = collect[key].sort
	end

	# we also could do this sort here...
	collect.keys.each do |x|
		collect[x] = collect[x].sort
	end

	final = []	# final order...
	while collect.size > 0
		collect.keys.sort.each do |x|

			# NOTE: this array should already be sorted!
			p = collect[x].shift	# assume an array of at least 1 element
			final.push( { 'host' => x, 'path' => p } )	# save

			if collect[x].size == 0		# maybe the array is empty now
				collect.delete(x)	# remove that empty list's key
			end

		end
	end

	# build final result
	result[group] = final.collect {|x| x['host']+':'+x['path'] }
	if not testcase[group] == final
		puts '# group: ' + group + ' failed!'
		puts testcase[group]
		puts '#'
		puts final
		puts "----------------------------------------------------------------\n"
	else
		puts '# group: ' + group + ' passed!'
	end
end

result.keys.each do |x|
	puts '# group: ' + x
	puts result[x]
	puts "----------------------------------------------------------------\n"
end

#puts result

