/* Copyright 2004 Louis Jean­Richard (www.ljr.ch). All Rights Reserved. */
//	-----------------------------------
function								message(str)
{
	window.defaultStatus = str
}
//	-----------------------------------
function                                quoted(s)
{
	return '"' + s + '"'
}
//	-----------------------------------
function                                sQuoted(s)
{
	return "'" + s + "'"
}

//	-----------------------------------
function   							packBinary(binaryString)
{
	var maxBit = CODE_STRING.length >> 1
	var last = binaryString.length
	var flag = binaryString.split("")
	var codedString = ""
	var n = 0, bit = maxBit
	for(var cell=0; cell < last; cell++) {
		if (flag[cell] == '1')
			n += bit
		if (bit > 1)
			bit >>= 1
		else {
			codedString += CODE_CHAR[n]
			n = 0
			bit = maxBit
		}
	}
	if (bit < maxBit)
		codedString += CODE_CHAR[n]

	return codedString
}

//	-----------------------------------
function   							unpackBinary(codedString)
{
	var maxBit = CODE_STRING.length >> 1
	var last = codedString.length
	var codedChar = codedString.split("")
	var binaryString = ""
	for(var c=0; c < last; c++) {
		var n = CODE_STRING.indexOf(codedChar[c])
		var bit = maxBit
		while (bit > 0) {
			if (n < bit)
				binaryString += '0'
			else {
				binaryString += '1'
				n -= bit
			}
			bit >>= 1
		}
	}

	return binaryString
}

//	-----------------------------------
function					randomInteger(lowBound, highBound)
{
	with(Math)
		return lowBound - 1
			+ round(0.5 + random()*(highBound - lowBound + 1))
}

//	-----------------------------------
function								permutations(n, r)
{
	if (r == undefined)
		r = n
	if (n == 0)
		return 1

	if (r == 0)
		return 0

    var factorial = 1
    while (r > 0) {
        factorial *= n
        n--
		r--
    }

	return factorial
}

//	-----------------------------------
function								combinations(n, k)
{
    if (k > n)
		return 0

	if (2 * k > n)
		k = n - k
    var num = 1
    var den = 1
    while (k > 0) {
        num *= n
        n--
		den *= k
		k--
    }

	return (num / den)
}


//	============================================================
//							B R O W S E R
//	============================================================

function                                Browser()
{
	// Netscape, Mozilla
	this.isNS4 = (document.layers) ? true : false
//	this.isNS4 = (window.Event) ? true : false
	this.isNS6 = (!document.all && document.getElementById) ? true : false
	this.isGecko = (window.navigator.userAgent.indexOf("Gecko/") > 0)

	// Internet Explorer
	this.isIE4 = (document.all && !document.getElementById) ? true : false
	this.isIE5 = (document.all && document.getElementById) ? true : false

	this.isIE = this.isIE4 || this.isIE5
	this.isNS = this.isNS4 || this.isNS6 || this.isGecko

}

var browser = new Browser()


//	============================================================
//							C H R O N O
//	============================================================

function								systime()
{
	var dt = new Date()
	return dt.getTime()// milliseconds
}

function								time()
{
	return Math.floor(systime() / 1000)	// seconds
}

function								Chrono()
{
	this.startTime = 0
	this.reading = 0
	this.previous_reading = 0
	this.running = false
	this.seconds = 0
	this.timed_event = null
}

//	-----------------------------------
function								elapsedChrono()
{
	if (this.running)
	{
		this.previous_reading = this.reading
		this.reading = time() - this.startTime
	}
	return this.reading
}
Chrono.prototype.elapsed = elapsedChrono

//	-----------------------------------
function								elapsedMinutesChrono()
{
	var seconds = this.elapsed()
	return Math.floor(seconds / 60) + ':'
		+ (100 + (seconds % 60)).toString().substr(1,2)
}
Chrono.prototype.elapsedMinutes = elapsedMinutesChrono

//	-----------------------------------
function								startChrono(timeUpdate)
{
	if (this.running)
		return

	this.startTime = time()
	this.running = true
	if (timeUpdate != undefined)
		this.timed_event = setInterval(timeUpdate, 1000)
}
Chrono.prototype.start = startChrono

//	-----------------------------------
function								stopChrono()
{
	if (!this.running)
		return

	clearTimeout(this.timed_event)
	void (this.elapsed())
	this.running = false
}
Chrono.prototype.stop = stopChrono


//	============================================================
//						P E R M U T A T I O N
//	============================================================

function								Permutation(n, r)
{
	if ((r == undefined) || (r > n))
		r = n
	this.pool = n
	this.subset = r
	this.permutations = permutations(n, r)
	this.index = new Array(r + 1)
	var i = 0
	while (i <= r) {
		this.index[i] = i
		i++
	}
	if (r < n)
		this.comb = new Combination(n, r)
}

//	-----------------------------------
function								displayPermutation()
{
	var output = '['
	var last = this.index.length
	for (var i=1; i < last; i++)
		output += this.index[i] + ', '
	return output + this.index[i] + ']'
}
Permutation.prototype.toString = displayPermutation

//	-----------------------------------
function								resetPermutation()
{
	var i = this.index.length
	while (i > 0) {
		i--
		this.index[i] = i
	}
	if (this.subset < this.pool)
		this.comb.reset()
}
Permutation.prototype.reset = resetPermutation

//	-----------------------------------
function 								arrayPermutation()
{
	return this.index.clone()
}
Permutation.prototype.array = arrayPermutation

//	-----------------------------------
//	based on code by Glenn Rhoads and Edsger W. Dijkstra
function								nextPermutation()
{
	var ii = this.subset
	var i = ii
	var j = ii
	var m = ii
	while (i > 1) {
		i--
		if (this.index[i] < this.index[ii]) {
			// swap
			var x = this.index[i]
			while (this.index[j] < x)
				j--
			this.index[i] = this.index[j]
			this.index[j] = x
			// reverse
			while (m > ii) {
				x = this.index[ii]
				this.index[ii] = this.index[m]
				this.index[m] = x
				m--
				ii++
			}
			this.index[0]++
			return true
		}
		ii--
	}
	if ((this.subset == this.pool) || !this.comb.next())
		return false	// this is the last permutation!
	var i = this.index.length
	while (i > 1) {
		i--
		this.index[i] = this.comb.index[i]
	}
	this.index[0]++

	return true
}
Permutation.prototype.next = nextPermutation

//	-----------------------------------
function								randomPermutation()
{
	var r = this.subset
	var i = this.index.length
	if (r == this.pool) {
		while (i > 0) {
			i--
			this.index[i] = i
		}
	}
	else {
		this.comb.random()
		while (i > 0) {
			i--
			this.index[i] = this.comb.index[i]
		}
	}
	var e = randomInteger(0, r)
	var p = randomInteger(1, r)
	while (e > 0) {
		var q = p
		var p = randomInteger(1, r)
		var x = this.index[p]
		this.index[p] = this.index[q]
		this.index[q] = x
		e--
	}
}
Permutation.prototype.random = randomPermutation

//	============================================================
//					C O M B I N A T I O N S
//	============================================================

function								Combination(n, k)
{
	if ((k == undefined) || (k > n))
		k = n
	this.pool = n
	this.subset = k
	this.index = new Array(k + 1)
	this.combinations = combinations(n, k)
	this.bitset = new Array(n)
	this.reset()
}

//	-----------------------------------
function 								arrayCombination()
{
	return this.index.clone()
}
Combination.prototype.array = arrayCombination

//	-----------------------------------
function								displayCombination()
{
	var output = '{'
	var last = this.subset
	for (var i=1; i < last; i++)
		output += this.index[i] + ', '

	return output + this.index[i] + '}'
}
Combination.prototype.toString = displayCombination

//	-----------------------------------
function								nextCombination()
{
	var n = this.pool
	var k = this.subset
	var bitset = this.bitset
	var c = k
	var i = 0
	while (c < n) {
		if (bitset[i]) {
			bitset[i] = false
			c--
			i++
		}
		else {
			c++
			bitset[i] = true
			var i = 0
			if (c == k) {
				var j = 0
				while (j < k)
					if (bitset[i]) {
						i++
						j++
						this.index[j] = i
					}
					else
						i++
				this.index[0]++

				return true
			}
		}
	}

	return false	// this is the last combination
}
Combination.prototype.next = nextCombination

//	-----------------------------------
function								randomCombination()
{
	if (this.combinations == 1)
		return

	var perm = new Permutation(this.pool)
	perm.random()
	var i = this.bitset.length
	while (i > 0) {
		i--
		this.bitset[i] = false
	}
	var i = this.index.length
	while (i > 1) {
		i--
		var j = perm.index[i]
		this.index[i] = j
		this.bitset[j - 1] = true
	}
	this.index[0] = 0
	this.index.sort()
}
Combination.prototype.random = randomCombination

//	-----------------------------------
function								resetCombination()
{
	var k = this.subset
	var i = this.bitset.length
	while (i > k) {
		i--
		this.bitset[i] = false
	}
	this.index[i] = i
	while (i > 0) {
		i--
		this.bitset[i] = true
		this.index[i] = i
	}
}
Combination.prototype.reset = resetCombination


///	============================================================
//								A R R A Y
//	============================================================

function cloneArray()
{
	return this.slice(0, this.length)
}
Array.prototype.clone = cloneArray


//	============================================================
//								H T M L
//	============================================================

//	-----------------------------------
function								htmlDisplay(name, label)
{
	if (label == undefined)
		label = name

	return label
		+ '<input class="display"'
		+ ' type="text" readonly="readonly" id='
		+ quoted(name)  + ' name=' + quoted(name)  + ' />\n'
}

//	-----------------------------------
function					htmlInput(name, label, maxLength)
{
	if (label == undefined)
		label = name
	var output = label + '<input class="input"'
	output += ' type="text" id=' + quoted(name)
	output += ' name=' + quoted(name)
	if (maxLength != undefined)
		output += ' maxlength=' + quoted(maxLength)

	return output + ' />\n'
}


//	============================================================
//							S E L E C T O R
//	============================================================
var	selectorCount = 0

function   				Selector(onChange, preselected)
{
//	the options to be used are listed after the second argument
	var last = arguments.length - 2
	this.option = new Array(last)
	for(var i=0; i < last; i++)
		this.option[i] = arguments[i + 2]
	this.onChange = onChange
	this.preselected = preselected
	this.selected = this.option[this.preselected]
}

//	-----------------------------------
function							htmlListSelector(formName)
{
	selectorCount++
	var selectorName = 'selector' + selectorCount
	this.index = 'document.' + formName
		+ '.' + selectorName + '.selectedIndex'
	var output = "<select name=" + quoted(selectorName)
	output += " size='1' onchange='javascript:"
	output += this.onChange + "()'>"
	for (var i=0; i < this.option.length; i++)
	{
		if (i == this.preselected)
			output += '<option selected="selected">'
		else
			output += '<option>'
		output += this.option[i].optionText
		output += '</option>'
	}
	output += "</select>\n"

	return output
}
Selector.prototype.htmlList = htmlListSelector
//	-----------------------------------
function						htmlRadioSelector(formName)
{
	if (!browser.isGecko)
		return this.htmlList(formName)

	selectorCount++
	var groupName = 'selector' + selectorCount
	var radioGroup =
		'document.' + formName + '.' + groupName + '['
	var output = ""
	for (var i=0; i < this.option.length; i++)
	{
		if (i > 0)
			output += '<br />'
		output += '<input class="radio" type="radio"'
		if (i == this.preselected)
			output += ' checked="checked"'
		var id = quoted(groupName + i)
		output += ' name=' + quoted(groupName)
			+ ' value=' + quoted(i)
			+ ' onchange=' + sQuoted(this.onChange + '()')
			+ ' id=' + id
			+ ' />'
			+ '<label for=' + id + ' >'
			+ this.option[i].optionText
			+ "</label>\n"
		this.option[i].checked = radioGroup + i + '].checked'
	}

	return output
}
Selector.prototype.htmlRadio = htmlRadioSelector

//	-----------------------------------
function								readSelector()
{
	if (this.index == undefined) {
		var optionIndex = 0
		while (!eval(this.option[optionIndex].checked))
			optionIndex++
	}
	else {
		var optionIndex = eval(this.index)
		if (optionIndex < 0)
			return
	}
	this.selected = this.option[optionIndex]
}
Selector.prototype.read = readSelector

//	-----------------------------------
function								checkSelector(optionIndex)
{
	if (this.index == undefined) {
		for (var i=0; i < this.option.length; i++)
			if (i == optionIndex)
				eval(this.option[i].checked+'=true')
			else
				eval(this.option[i].checked+'=false')
	}
	else {
	}
}
Selector.prototype.check = checkSelector


//	============================================================
//							P R E L O A D
//	============================================================

function								Preload(directory)
{
	this.directory = directory
	this.image = new Array()
}

//	-----------------------------------
function				loadPreload(rootName, images, extension)
{
	var path = this.directory + rootName
	var i = this.image.length
	for (var n = 0; n < images; n++) {
		this.image[i] = new Image()
		this.image[i].src = path + n + extension
		i++
	}
}
Preload.prototype.load = loadPreload

//	-----------------------------------
function						displayPreload(name, imageIndex)
{
	document.images[name].src = this.image[imageIndex].src
}
Preload.prototype.display = displayPreload

//	-----------------------------------
function				htmlPreload(name, imageIndex, isBlock){
	var output = '<img'
	if (name != '')
		output += ' name=' + quoted(name)
	output += ' src=' + quoted(this.image[imageIndex].src)
	if (isBlock)
		output += ' style="display: block"'

	return   output + ' />'
}
Preload.prototype.html = htmlPreload

//	-----------------------------------
//	fine
