/*
	Prototype definition for the User objects used in IGN scripts.

	*** IGN_Core.js must be executed prior to executing this script
	*** IGN_String.js must be executed prior to executing this script
	*** IGN_Number.js must be executed prior to executing this script
	*** IGN_Array.js must be executed prior to executing this script
	*** IGN_UserColors.js must be executed prior to executing this script

	Author: OldManLink (Peter Hugosson-Miller)
	Creation date: 2004-07-02
	Version: 1.0
*/

User = function()					// The prototype comes into existence
{
	this.oldPPW = Number.MAX_VALUE;	// Initialize the default old value of Posts/WUL
}


User.milestones = new Array();
User.milestones[0] = 0;
User.milestones[1] = 50;
User.milestones[2] = 250;
User.milestones[3] = 500;
User.milestones[4] = 1000;
User.milestones[5] = 5000;
User.milestones[6] = 10000;
User.milestones[7] = 20000;
User.milestones[8] = 30000;
User.milestones[9] = 40000;
User.milestones[10] = 50000;

User.listHeaders = new Object();
User.listHeaders['NORMAL'] = new Object();
User.listHeaders['NORMAL']['POST'] = new Object();
User.listHeaders['NORMAL']['POST']['NORMAL'] = '[color=blue]Post Count Update:[/color]\nRank/Rank Change/Post Count/Post Count Increase/Username';
User.listHeaders['NORMAL']['POST']['CHANGES'] = 'Top Spammers list\n[color=blue]Changes in Post Count Update:[/color]\nRank/Rank Change/Post Count/Post Count Increase/Username';
User.listHeaders['NORMAL']['WUL'] = new Object();
User.listHeaders['NORMAL']['WUL']['NORMAL'] = '[color=blue]WUL Count Update:[/color]\nRank/Rank Change/WUL Count/Change from Previous MU/Username';
User.listHeaders['NORMAL']['WUL']['CHANGES'] = 'Top Popularity gainers\n[color=blue]Changes in WUL Count Update:[/color]\nRank/Rank Change/WUL Count/Change from Previous MU/Username';
User.listHeaders['NORMAL']['PPW'] = new Object();
User.listHeaders['NORMAL']['PPW']['NORMAL'] = '[color=blue]Post per WUL (PPW) Update:[/color]\nRank/Rank Change/PPW/Change from Previous MU/Username';
User.listHeaders['NORMAL']['PPW']['CHANGES'] = 'Top post quality improvers\n[color=blue]Changes in Post per WUL (PPW) Update:[/color]\nRank/Rank Change/PPW/Change from Previous MU/Username';
User.listHeaders['NORMAL']['MS'] = new Object();
User.listHeaders['NORMAL']['MS']['NORMAL'] = '[color=blue]Milestones reached since previous MU:[/color]\nMilestone/Username';

var tUserName = '[/b][link=http://club.ign.com/b/about?username=OldManLink][b]User Name[/b][/link]';
User.listHeaders['SIMPLE'] = new Object();
User.listHeaders['SIMPLE']['POST'] = new Object();
User.listHeaders['SIMPLE']['POST']['NORMAL'] = 'Rank. [difference in rank] Post Count ' + tUserName + '[b] (difference in post count)';
User.listHeaders['SIMPLE']['POST']['CHANGES'] = 'Top Spammers list\nRank. [difference in rank] Post Count ' + tUserName + '[b] (difference in post count)';
User.listHeaders['SIMPLE']['WUL'] = new Object();
User.listHeaders['SIMPLE']['WUL']['NORMAL'] = 'Rank. [difference in rank] WUL Count ' + tUserName + '[b] (difference in WUL count)';
User.listHeaders['SIMPLE']['WUL']['CHANGES'] = 'Top Popularity gainers\nRank. [difference in rank] WUL Count ' + tUserName + '[b] (difference in WUL count)';
User.listHeaders['SIMPLE']['PPW'] = new Object();
User.listHeaders['SIMPLE']['PPW']['NORMAL'] = 'Rank. [difference in rank] Posts Per WUL ' + tUserName + '[b] (difference in PPW)';
User.listHeaders['SIMPLE']['PPW']['CHANGES'] = 'Top post quality improvers\nRank. [difference in rank] Posts Per WUL ' + tUserName + '[b] (difference in PPW)';
User.listHeaders['SIMPLE']['MS'] = new Object();
User.listHeaders['SIMPLE']['MS']['NORMAL'] = 'Milestones reached since previous MU:\nMilestone ' + tUserName + '[b]';

var tUserName = '[/b][link=http://club.ign.com/b/about?username=OldManLink][b]USERNAME[/b][/link]';
User.listHeaders['VESTI'] = new Object();
User.listHeaders['VESTI']['POST'] = new Object();
User.listHeaders['VESTI']['POST']['NORMAL'] = 'RANK | POSTCOUNT | ' + tUserName + '[b] | POSTCOUNT INCREASE | RANK CHANGE';
User.listHeaders['VESTI']['POST']['CHANGES'] = 'Top Spammers list\nRANK | POSTCOUNT | ' + tUserName + '[b] | POSTCOUNT INCREASE | RANK CHANGE';
User.listHeaders['VESTI']['WUL'] = new Object();
User.listHeaders['VESTI']['PPW'] = new Object();
User.listHeaders['VESTI']['MS'] = new Object();

User.fromInfoString = function(userInfoString)
{/*
	Parse the supplied information string into the expected tokens, and if
	successful create a User instance and return it.
	Otherwise, return null.
*/
	var tUser = null;
	var tTokens=userInfoString.match(/([0-9]+)\s+([0-9]+)\s+(\S*)/);
	if (tTokens != null)
	{
		tUser = new User();
		tUser.postCount=tTokens[1];
		tUser.wulCount=tTokens[2];
		tUser.userName=tTokens[3];
	}
	return tUser;

}


User.fromInfoStrings = function(MUStats)
{/*
	Parse the string <MUStats> to obtain an Array of
	users with user name, post count and WUL count.
	Return the resulting Array if sucessful.
	Return null otherwise.
*/
	var tUsers = null;
	var tLines=MUStats.match(/^.*$/gm);
	var tSuccess=tLines.length > 0;

	if (tSuccess)
	{
		tUsers = new Array();
		tLines.iterate( function(line)
			{
				var tUser = User.fromInfoString(line);
				if (tUser != null)
				{
					if(tUsers[tUser.userName + '_'] == null)
					{
						tUsers[tUsers.length]=tUser;
						tUsers[tUser.userName + '_']=tUser;
					}
					else
						User.transcript.value += 'Warning: duplicate user \'' + line + '\' - ignored.\n';
				}
			});

		tUsers.sort(User.sortFunction);
		tUsers.iterate( function(user, index)
		{
			user.saveRank(index + 1);
		});

	}
	return tUsers;
}

User.sortFunction = function(a, b)
{/*
	Return the difference between two attributes, selected according to the
	value of listType.
	POST - Return the difference between the postCount values of the two User objects.
	WUL - Return the difference between the wulCount values of the two User objects.
	PPW - Return the difference between the PPW values of the two User objects.
	MS - Return the difference between the 'NewMilestone' values of the two User objects.
*/
	switch(User.listType)
	{
		case 'POST':	return b.postCount - a.postCount;
		case 'WUL':		return b.wulCount - a.wulCount;
		case 'PPW':		return a.getPPW() - b.getPPW();
		case 'MS':		return b.getNewMilestone() - a.getNewMilestone();
		default:		return 0;
	}
}

User.sortDeltaFunction = function(a, b)
{/*
	Return the difference between two attributes, selected according to the
	value of listType.
	POST - Return the difference between the getDiffPOSTString values of the two User objects.
	WUL - Return the difference between the getDiffWULString values of the two User objects.
	PPW - Return the difference between the getDiffPPWString values of the two User objects.
	MS - Return the difference between the 'NewMilestone' values of the two User objects.
*/
	switch(User.listType)
	{
		case 'POST':	return b.getDiffPOST() - a.getDiffPOST();
		case 'WUL':		return b.getDiffWUL() - a.getDiffWUL();
		case 'PPW':		return a.getDiffPPW() - b.getDiffPPW();
		default:		return 0;
	}
}

User.setListStyle = function(option)
{/*
	Set the current list style, selected by the user.
	This will cause the lines of the list to be coloured and padded, or not.
	Return true if a list was selected, false otherwise.
*/
	this.listStyle = option;
	if(option == 'NULL')
	{
		this.transcript.value='Nothing selected';
		return false;
	}
	else
	{
		this.transcript.value='';
		return true;
	}
}

User.setListType = function(option)
{/*
	Set the current list type, selected by the user.
	This will cause the various Arrays of Users to be sorted according to
	appropriate attributes for the list to be generated.
	Return true if a list was selected, false otherwise.
*/
	this.listType = option;
	if(option == 'NULL')
	{
		this.transcript.value='Nothing selected';
		return false;
	}
	else
	{
		this.transcript.value='';
		return true;
	}
}

User.setListSort = function(option)
{/*
	Set the current list sort, selected by the user.
	This will cause the various Arrays of Users to be sorted according to
	differences between appropriate attributes for the list to be generated.
	Return true if a list was selected, false otherwise.
*/
	this.listSort = option;
	if(option == 'NULL')
	{
		this.transcript.value='Nothing selected';
		return false;
	}
	else
	{
		this.transcript.value='';
		return true;
	}
}

User.getListTitle = function()
{/*
	Return the title to be displayed above the generated list, depending on
	the currently selected list type.
*/
	if(User.listSort == 'CHANGES')
	{
		tPrefix = 'Changes in ';
	}
	else
	{
		tPrefix = '';
	}
	switch(User.listType)
	{
		case 'POST':	return tPrefix +'Post count ranking calculated from above input';
		case 'WUL':		return tPrefix +'WUL count ranking calculated from above input';
		case 'PPW':		return tPrefix +'Posts Per WUL ranking calculated from above input';
		case 'MS':		return 'Milestones reached since previous MU';
		default:		return 'Nothing selected to generate';
	}
}


User.getListHeader = function()
{/*
	Return the header to be printed above the generated list, depending on
	the currently selected list type ans style.
*/
	var tHeader = User.listHeaders[User.listStyle][User.listType][User.listSort];
	if (tHeader == null)
	{
		tHeader = 'Not Implemented yet!\n';
	}
	else
	{
		tHeader = tHeader.markupPair('b');
		if((User.listStyle == 'NORMAL') || (User.listStyle == 'VESTI') || (User.listType == 'MS'))
		{
			tHeader += '\n\n';
		}

		if((User.listStyle == 'SIMPLE') && (User.listType != 'MS'))
		{
			tHeader += '[ol]';
		}
	}
	return tHeader;
}


User.getListFooter = function()
{/*
	Return the footer to be printed beneath the generated list, depending on
	the currently selected list style.
*/
	var tFooter = '';

	if((User.listStyle == 'SIMPLE') && (User.listType != 'MS'))
	{
		tFooter += '[/ol]\n';
	}
	return tFooter;

}


User.htmlLinkString = function(userInfoString)
{/*
	Return the HTML code to print the supplied user's link to a document.
*/
	var tUser = null;
	var tColors = null;
	var tLink = '<b>ERROR: "' + userInfoString + '"</b>';
	var tTokens2=userInfoString.match(/(\S*)/);
	tUser = User.fromInfoString('0 0 ' + tTokens2[1]);

	if (tTokens2[0] != userInfoString)
	{
		var tTokens8=userInfoString.match(/(\S*) (\S*) (\S*) (\S*) (\S*) (\S*) (\S*)/);
		var tColorsString = tTokens8[2] + ' ' +tTokens8[3] + ' ' +tTokens8[4];
		tColorsString += ' ' +tTokens8[5] + ' ' +tTokens8[6] + ' ' +tTokens8[7];
		tColors = UserColors.fromInfoString(tColorsString);
	}
	tUser.vipColors = tColors;

	return tUser.htmlLinkString();
}


User.prototype.saveRank = function(rank)
{/*
	Save my current rank, depending on the value of listType.
	POST - save the supplied rank as rankPOST.
	WUL - save the supplied rank as rankWUL
	PPW - save the supplied rank as rankPPW.
	MS - silently ignore the supplied rank.
*/
	var tIgnore = 0;
	switch(User.listType)
	{
		case 'POST':	this.rankPOST = rank; break;
		case 'WUL':		this.rankWUL = rank; break;
		case 'PPW':		this.rankPPW = rank; break;
		case 'MS':		tIgnore = rank; break;
		default:		alert('No list type selected');
	}
}


User.prototype.getPPW = function()
{/*
	Calculate and save my Posts Per WUL (PPW). If my WUL count is 0, save a
	suitably big number to represent infinity.

	If my PPW has already been calculated, return the cached value instead of
	calculating it. This is to speed up sorting.

	Return the resulting value.
*/
	if(this.ppw == null)
	{
		if(this.wulCount > 0)
			this.ppw = (Math.round(this.postCount * 100 / this.wulCount)) / 100;
		else
			this.ppw = Number.MAX_VALUE;
	}
	return this.ppw;
}


User.prototype.getMilestone = function()
{/*
	Calculate and save my 'Milestone' status. If I have achieved a milestone,
	save the index of that milestone.
	Otherwise, save 0 as my 'Milestone' status.

	If my 'Milestone' status has already been calculated, return the cached value
	instead of calculating it. This is to speed up sorting.

	Return the resulting value.
*/
	if(this.milestone == null)
	{
		var tSelf = this;
		this.milestone = 0;
		User.milestones.iterate( function(postCount, index)
		{
			if (tSelf.postCount >= postCount)
			{
				tSelf.milestone = index;
			}
		});
	}
	return this.milestone;
}

User.prototype.getNewMilestone = function()
{/*
	Calculate and save my 'New Milestone' status. If I have achieved a new
	milestone, since the previous MU save the index of that milestone.
	Otherwise, save 0 as my 'Milestone' status.

	If my 'New Milestone' status has already been calculated, return the cached value
	instead of calculating it. This is to speed up sorting.

	Return the resulting value.
*/
	if((this.newMilestone == null) && (this.oldUser != null))
	{
		if (this.getMilestone() > this.oldUser.getMilestone())
		{
			this.newMilestone = this.getMilestone();
		} else {
			this.newMilestone = 0;
		}
	}
	return this.newMilestone;
}

User.prototype.chooseIcon = function()
{/*
	Cause the currently logged in IGN User to use my icon, if I have one. This is done by executing a POST
	to http://boards.ign.com/user_icons.asp with the parameter 'icon' set to my iconId. If my iconId is not
	set, alert the user. The above POST command must belong to a form which has been set as 'chooseIconForm'
	on myself before this method is called.
*/
	var tSuccess = false;
	if(this.iconId == null)
	{
		alert('No icon to choose!');
	}
	else
	{
		if(this.chooseIconForm == null)
		{
			// This is where the alternative code for icon testing will go
		}
		else
		{
			alert('Choosing icon ' + this.iconId + ' (' + this.iconUrl + ').');
			this.chooseIconForm.icon.value = this.iconId;
			this.chooseIconForm.submit();
			tSuccess = true;
		}
	}
	return tSuccess;
}

User.prototype.getStarUrl = function()
{/*
	Return the url of my current star, based on my post count.
*/
	var tMilestone = this.getMilestone();
	var tURL = 'http://media.ign.com/boards/images/';
//	var tURL = 'http://i12.photobucket.com/albums/a240/H3y-Koole/Stars/';
	if(tMilestone >0){
		if(tMilestone == 1)
		{
			tMilestone = '';
		};
		tURL += 'star' + tMilestone + '.gif';
	} else {
		tURL = 'http://media.ign.com/images/hub/pixy.gif';
	};
	return tURL;
}

User.prototype.getRegisteredDateString = function()
{/*
	Return a String describing when I was registered, in IGN format.
*/
	var tMonths = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
	var tYear = '' + this.dateRegistered.getYear();
	if(tYear > 99){
		tYear -= 100;
	};
	tYear = ('' + tYear).markupPadded(2, '0', false);
	return tMonths[this.dateRegistered.getMonth()] + ' ' + tYear;
}

User.prototype.getPostHeader = function( postId, posted, subject, edited, editCount)
{/*
	Return a String which is the post header on the IGN boards.
*/
	var tHeader = '';
	tHeader += '\t<!-- Begin Post ' + postId + ' -->\n';
	tHeader += '\t\t<!-- Icon, post count and header -->\n';
	tHeader += '\t\t<tr align="left" valign="top" class="BoardRowA">\n';

	tHeader += '\t\t\t<!-- Icon and post count -->\n';
	tHeader += '\t\t\t<td class="BoardRowA" rowspan=3 width="17%">\n';
	tHeader += '\t\t\t\t' + this.htmlLinkString(postId);
	tHeader += '&nbsp;<a href="http://boards.ign.com/help/default.asp?goto=faqs%2Easp%23stars">';
	tHeader += "<img align=absmiddle src='" + this.getStarUrl() + "' border=0 hspace=0 vspace=0 alt='";
	tHeader += (1 * this.postCount).commatize() + " posts'></a><br>\n";
	tHeader += '\t\t\t\t<span style="font-size: 8pt;">\n';
	tHeader += '\t\t\t\t\t<a class="BoardRowBLink" href="http://users.ign.com/collection/';
	tHeader += this.userName + '"><font size="1">collection (' + this.collectionSize + ')</font></a> | \n'
	tHeader += '\t\t\t\t\t<a class="BoardRowBLink" href="http://users.ign.com/wishlist/';
	tHeader += this.userName + '"><font size="1">wishlist (' + this.wishlistSize + ')</font></a><br>';
	tHeader += '\t\t\t\t<span style="font-weight: bold;">Posts:</span> ';
	tHeader += (1 * this.postCount).commatize() + '<br><span style="font-weight: bold;">Registered:</span> ';
	tHeader += this.getRegisteredDateString() + '<br>\n';
	tHeader += '\t\t\t\t</span>\n';
	tHeader += '\t\t\t\t<img border=0 hspace=8 vspace=8 src="' + this.iconUrl + '" width="80" height="80" alt="' +
	  this.iconId + '" name="' + this.iconId + '" id="' + this.iconId + '" class="IconImage" onClick="' + this.userName +
	  '.chooseIcon()" />\n';
	tHeader += '\t\t\t</td>\n';

	tHeader += '\t\t\t<!-- Post header -->\n';
	tHeader += '\t\t\t<td class="BoardRowA" colspan=2 width="83%">\n';
	tHeader += '\t\t\t\t<span style="font-weight: bold;">Date Posted:</span> ' + posted + '\n';
	tHeader += '\t\t\t\t<span style="font-weight: bold;">Subject:</span> ' + subject + '\n';

	if(edited != null){
		tHeader += ' - ';
		tHeader += '\t\t\t\t<span style="font-weight: bold;">Date Edited:</span> ' + edited;
		tHeader += ' (' + editCount + ' edit';
		if(editCount > 1){
			tHeader += 's';
		}
		tHeader += ' total)\n';
		tHeader += '\t\t\t\t<span style="font-weight: bold;">Edited By:</span>\n';
		tHeader += '\t\t\t\t' + this.htmlLinkString() + '\n';
	};
	tHeader += '\t\t\t</td>\n';
	tHeader += '\t\t</tr>\n';

	return tHeader;
}


User.prototype.getSignatureString = function()
{/*
	Return a String containing my post signature, in IGN format.
*/
	var tSignature = '';
	tSignature +='<p></p><span class="SignatureTitle">-----signature-----</span>';
	tSignature += '<div class="SignatureText">' + this.signatureText + '</div>';
	return tSignature;
}

User.prototype.getPostFooter = function()
{/*
	Return a String which is the post footer on the IGN boards.
*/
	var tFooter = '';
	tFooter +='\t\t<!-- Post Footer -->\n';
	tFooter +='\t\t<tr align="right"valign="bottom">\n';
	tFooter +='\t\t\t<td colspan=2 class="BoardRowB">\n';
	tFooter +='\t\t\t\t<a class="BoardRowBLink" href="http://boards.ign.com/user_watch_update.asp?usr=962510" >WUL Me</a> |\n';
	tFooter +='\t\t\t\t<a class="BoardRowBLink" href="http://boards.ign.com/pm_send.asp?usr=962510">Private Message</a> |\n';
	tFooter +='\t\t\t\t<a class="BoardRowBLink" href="http://boards.ign.com/user_posts.asp?usr=962510">Post History</a>\n';
	tFooter +='\t\t\t</td>\n';
	tFooter +='\t\t</tr>\n';
	return tFooter;
}

User.prototype.writePost = function(postText, postId, posted, subject, edited, editCount)
{/*
	Write the supplied post to the current document.
*/
	document.write(this.getPostHeader( postId, posted, subject, edited, editCount));
	document.write('\t\t<!-- Post Body -->\n\t\t<tr valign=top>\n\t\t\t<td class="BoardRowB" colspan=2 width="83%">\n');
	document.write(postText);
	document.write(this.getSignatureString());
	document.write('\t\t\t</td>\n\t\t</tr>\n');
	document.write(this.getPostFooter());
	document.write('\n\t<!-- End Post ' + postId + ' -->\n\n');
	return this;
}

/*
***
***	 BEGIN POST String Routines
***
*/

User.prototype.getDiffPOST = function()
{/*
	Return the difference in my POST count since the previous
	MU, or 0 if I was not on the previous MU.
*/
	var tOldPost = 0;
	var tDiffPOST = 0;
	if(this.oldUser != null)
	{
		tOldPost = this.oldUser.postCount;
		tDiffPOST = this.postCount - tOldPost;
	}
	return tDiffPOST;
}


User.prototype.getDiffPOSTString = function()
{/*
	Return a String representing the difference in my POST count since the previous
	MU.
*/
	var tOldPost = 0;
	if(this.oldUser != null)
	{
		var tDiffPOST = this.getDiffPOST();
		if (User.listStyle == 'NORMAL')
		{
			tDiffPOST = tDiffPOST.rankMarkup(4, Number.rankColours, 0);
		}
		if (User.listStyle == 'SIMPLE')
		{
			var tSign = tDiffPOST.signCharacter();
			if(tSign == 'x')
			{
				tSign = '+';
			}
			tDiffPOST = '(' + tSign + Math.abs(tDiffPOST) + ')';
		}
		if (User.listStyle == 'VESTI')
		{
			tDiffPOST = tDiffPOST.commatize();
		}

	}
	else
	{
		tDiffPOST = '"NEW"'.markupPair('color=DarkBlue');
		if (User.listStyle == 'VESTI')
		{
			tDiffPOST = 'n00b';
		}
	}
	return tDiffPOST;
}


User.prototype.getRankDiffPOSTString = function()
{/*
	Return a String representing the difference in my POST count ranking since the
	previous MU.
*/
	var tOldRankPost = this.rankPOST;
	if(this.oldUser != null)
	{
		tOldRankPost = this.oldUser.rankPOST;
	}
	var tRankDiff = tOldRankPost - this.rankPOST;
	if (User.listStyle == 'NORMAL')
	{
		tRankDiff = tRankDiff.rankMarkup(3, Number.rankColours, 0);
	}
	if (User.listStyle == 'SIMPLE')
	{
		var tSign = tRankDiff.signCharacter();
		var tSimpleSign = tSign;
		if(tSimpleSign == 'x')
		{
			tSimpleSign = '+';
		}
		tRankDiff = '[' + tSimpleSign + Math.abs(tRankDiff) + ']';
		if(tSign != 'x')
		{
			tRankDiff = tRankDiff.markupPair('color=' + Number.rankColours[tSign]);
		}
	}
	if (User.listStyle == 'VESTI')
	{
			tRankDiff = tRankDiff.commatize();
	}

	return tRankDiff;
}


User.prototype.getMUPOSTString = function()
{/*
	Return a String representation of myself suitable for pasting into an IGN
	Members' Update (MU). Provide information about my current and previous POST counts.

	[b][color=#c1c2c9]0[/color]10.[color=#c1c2c9]0[/color][color=#c1c2c9]i[/color][color=red]-005[/color][/b]
	[color=#c1c2c9]0[/color] 125.72 [color=#c1c2c9]i[/color][color=green]-00.77[/color] -
	[link=http://users.ign.com/about/nintendospy][b]nintendospy[/b][/link]


*/
	var tPOSTRankString = '';
	if (User.listStyle == 'NORMAL')
	{
		tPOSTRankString += ('' + this.rankPOST + '.').markupPadded(4, '0', true);
		tPOSTRankString += ''.markupPadded(1, '0', true);
		tPOSTRankString += this.getRankDiffPOSTString();
		tPOSTRankString = tPOSTRankString.markupPair('b') + ' ';
	}
	if (User.listStyle == 'SIMPLE')
	{
		tPOSTRankString = '[li]' + this.getRankDiffPOSTString();
	}
	if (User.listStyle == 'VESTI')
	{
		tPOSTRankString = this.rankPOST.commatize() + ' >> ';
	}

	tPOSTString = '';
	if (User.listStyle == 'NORMAL')
	{
		tPOSTString = ' ' + ('' + this.postCount).markupPadded(6, '0', true);
		tPOSTString += ' ' + this.getDiffPOSTString();
	}
	if (User.listStyle == 'SIMPLE')
	{
		tPOSTString = ' ' + (1 * this.postCount).commatize() + ' ' + this.userLinkString() + ' ' + this.getDiffPOSTString() + '[/li]';
	}
	if (User.listStyle == 'VESTI')
	{
		tPOSTString = (1 * this.postCount).commatize() + ' >> ' + this.userName + ' >> ' + this.getDiffPOSTString() + ' >> ' + this.getRankDiffPOSTString() + '\n';
	}

	return tPOSTRankString + tPOSTString;
}

/*
***
***	 END POST String Routines
***
*/

/*
***
***	 BEGIN WUL String Routines
***
*/

User.prototype.getDiffWUL = function()
{/*
	Return the difference in my WUL count since the previous MU,
	or 0 if I was not on the previous MU
*/
	var tOldWUL = 0;
	var tDiffWUL = 0;
	if(this.oldUser != null)
	{
		tOldWUL = this.oldUser.wulCount;
		tDiffWUL = this.wulCount - tOldWUL;
	}
	return tDiffWUL;
}


User.prototype.getDiffWULString = function()
{/*
	Return a String representing the difference in my WUL count since the previous
	MU.
*/
	var tDiffWUL = 0;
	if(this.oldUser != null)
	{
		tDiffWUL = this.getDiffWUL();
		if (User.listStyle == 'NORMAL')
		{
			tDiffWUL = tDiffWUL.rankMarkup(4, Number.rankColours, 0);
		}
		else
		{
			var tSign = tDiffWUL.signCharacter();
			if(tSign == 'x')
			{
				tSign = '+';
			}
			tDiffWUL = '(' + tSign + Math.abs(tDiffWUL) + ')';
		}
	}
	else
	{
		tDiffWUL = '"NEW"'.markupPair('color=DarkBlue');
	}
	return tDiffWUL;
}


User.prototype.getRankDiffWULString = function()
{/*
	Return a String representing the difference in my WUL count ranking since the
	previous MU.
*/
	var tOldRankWUL = this.rankWUL;
	if(this.oldUser != null)
	{
		tOldRankWUL = this.oldUser.rankWUL;
	}
	var tRankDiff = tOldRankWUL - this.rankWUL;
	if (User.listStyle == 'NORMAL')
	{
		tRankDiff = tRankDiff.rankMarkup(3, Number.rankColours, 0);
	}
	else
	{
		var tSign = tRankDiff.signCharacter();
		var tSimpleSign = tSign;
		if(tSimpleSign == 'x')
		{
			tSimpleSign = '+';
		}
		tRankDiff = '[' + tSimpleSign + Math.abs(tRankDiff) + ']';
		if(tSign != 'x')
		{
			tRankDiff = tRankDiff.markupPair('color=' + Number.rankColours[tSign])
		}
	}
	return tRankDiff;
}


User.prototype.getMUWULString = function()
{/*
	Return a String representation of myself suitable for pasting into an IGN
	Members' Update (MU). Provide information about my current and previous WUL counts.

	[b][color=#c1c2c9]0[/color]10.[color=#c1c2c9]0[/color][color=#c1c2c9]i[/color][color=red]-005[/color][/b]
	[color=#c1c2c9]0[/color] 125.72 [color=#c1c2c9]i[/color][color=green]-00.77[/color] -
	[link=http://users.ign.com/about/nintendospy][b]nintendospy[/b][/link]


*/
	var tWULRankString = '';
	if (User.listStyle == 'NORMAL')
	{
		tWULRankString += ('' + this.rankWUL + '.').markupPadded(4, '0', true);
		tWULRankString += ''.markupPadded(1, '0', true);
		tWULRankString += this.getRankDiffWULString();
		tWULRankString = tWULRankString.markupPair('b') + ' ';
	}
	else
	{
		tWULRankString += '[li]' + this.getRankDiffWULString();
	}

	tWULString = '';
	if (User.listStyle == 'NORMAL')
	{
		tWULString += ('' + this.wulCount).markupPadded(5, '0', true);
		tWULString += ' ' + this.getDiffWULString();
	}
	else
	{
		tWULString += ' ' + (1 * this.wulCount).commatize() + ' ' + this.userLinkString() + ' ' + this.getDiffWULString() + '[/li]';
	}

	return tWULRankString + tWULString;
}

/*
***
***	 END WUL String Routines
***
*/

/*
***
***	 BEGIN PPW String Routines
***
*/

User.prototype.getPPWString = function()
{/*
	Return my Posts Per WUL in a form suitable for displaying.
	If my PPW is approximately infinity (Number.MAX_VALUE), return '___.__'
	Otherwise return my PPW displayed with two decimals.
*/
	var tPPW = this.getPPW();
	var tPPWString = '';
	if(tPPW != Number.MAX_VALUE)
		tPPWString = tPPW.stringWithDecimals(2);
	else
		tPPWString='__.__';

	return tPPWString;
}


User.prototype.getDiffPPW = function()
{/*
	Return the difference in my PPW since the previous MU,
	or 0 if I was not on the previous MU
*/
	var tOldPPW = Number.MAX_VALUE;
	var tDiffPPW = 0;
	if(this.oldUser != null)
	{
		tOldPPW = this.oldUser.getPPW();
		tDiffPPW = this.getPPW() - tOldPPW;

		if((tOldPPW == Number.MAX_VALUE) && (tDiffPPW != 0))
		{
			tDiffPPW = 0 - this.getPPW();
		}
		if((this.getPPW() == Number.MAX_VALUE) && (tDiffPPW != 0))
		{
			tDiffPPW = tOldPPW;
		}
	}
	return tDiffPPW;
}


User.prototype.getDiffPPWString = function()
{/*
	Return the difference in my PPW since the previous
	MU.
*/
	var tDiffPPW = 0;
	if(this.oldUser != null)
	{
		tDiffPPW = this.getDiffPPW();
		if (User.listStyle == 'NORMAL')
		{
			tDiffPPW = tDiffPPW.rankMarkup(5, Number.wulColours, 2);
		}
		else
		{
			var tSign = tDiffPPW.signCharacter();
			if(tSign == 'x')
			{
				tSign = '+';
			}
			tDiffPPW = '(' + tSign + Math.abs(tDiffPPW).stringWithDecimals(2) + ')';
		}
	}
	else
	{
		tDiffPPW = '"NEW"'.markupPair('color=DarkBlue');
	}
	return tDiffPPW;
}


User.prototype.getRankDiffPPWString = function()
{/*
	Return a String representing the difference in my PPW ranking since the
	previous MU.
*/
	var tOldRankPPW = this.rankPPW;
	if(this.oldUser != null)
	{
		tOldRankPPW = this.oldUser.rankPPW;
	}
	var tRankDiff = tOldRankPPW - this.rankPPW;
	if (User.listStyle == 'NORMAL')
	{
		tRankDiff = tRankDiff.rankMarkup(3, Number.rankColours, 0);
	}
	else
	{
		var tSign = tRankDiff.signCharacter();
		var tSimpleSign = tSign;
		if(tSimpleSign == 'x')
		{
			tSimpleSign = '+';
		}
		tRankDiff = '[' + tSimpleSign + Math.abs(tRankDiff) + ']';
		if(tSign != 'x')
		{
			tRankDiff = tRankDiff.markupPair('color=' + Number.rankColours[tSign])
		}
	}
	return tRankDiff;

}


User.prototype.getMUPPWString = function()
{/*
	Return a String representation of myself suitable for pasting into an IGN
	Members' Update (MU). Provide information about my current and previous PPW.

	[b][color=#c1c2c9]0[/color]10.[color=#c1c2c9]0[/color][color=#c1c2c9]i[/color][color=red]-005[/color][/b]
	[color=#c1c2c9]0[/color] 125.72 [color=#c1c2c9]i[/color][color=green]-00.77[/color] -
	[link=http://users.ign.com/about/nintendospy][b]nintendospy[/b][/link]


*/
	var tPPWRankString = '';
	if (User.listStyle == 'NORMAL')
	{
		tPPWRankString += ('' + this.rankPPW + '.').markupPadded(4, '0', true);
		tPPWRankString += ''.markupPadded(1, '0', true);
		tPPWRankString += this.getRankDiffPPWString();
		tPPWRankString = tPPWRankString.markupPair('b') + ' ';
	}
	else
	{
		tPPWRankString += '[li]' + this.getRankDiffPPWString();
	}

	tPPWString = '';
	if (User.listStyle == 'NORMAL')
	{
		tPPWString += (' ' + this.getPPWString()).markupPadded(8, '0', true);
		tPPWString += ' ' + this.getDiffPPWString();
	}
	else
	{
		tPPWString += ' ' + this.getPPWString() + ' ' + this.userLinkString() + ' ' + this.getDiffPPWString() + '[/li]';
	}

	return tPPWRankString + tPPWString;
}

/*
***
***	 END PPW String Routines
***
*/

/*
***
***	 BEGIN MS String Routines
***
*/

User.prototype.getMUMSString = function()
{/*
	Return my 'New Milestone' status in a form suitable for displaying.
	If I have reached a new milestone since the previous MU, show it.
	Otherwise return an empty string.
*/
	var tMSString = '';
	var tNewMilestone = this.getNewMilestone();
	if((tNewMilestone != 0) && (tNewMilestone != null))
	{

		tMSString += User.milestones[tNewMilestone];
		if(User.listStyle == 'NORMAL')
		{
			tMSString = tMSString.markupPadded(6, '0', true);
		}
		else
		{
			tMSString = '' + (User.milestones[tNewMilestone]).commatize();
		}
		tMSString += ' posts';
		if(User.listStyle == 'NORMAL')
		{
			tMSString = tMSString.markupPair('b');
		};
		if(User.listStyle == 'SIMPLE')
		{
			tMSString += ' ' + this.userLinkString() + '\n';
		};
	}
	return tMSString;
}

/*
***
***	 END MS String Routines
***
*/

User.prototype.getMUString = function()
{/*
	Return a String representation of myself suitable for pasting into an IGN
	Members' Update (MU). Include formatting and colours, using IGN markup,
	depending on the selected list style.
	The information contained in the string will depend on the currently
	selected list type.
*/
	var tMUString = '';
	switch(User.listType)
	{
		case 'POST':		tMUString = this.getMUPOSTString(); break;
		case 'WUL':		tMUString = this.getMUWULString(); break;
		case 'PPW':		tMUString = this.getMUPPWString(); break;
		case 'MS':		tMUString = this.getMUMSString(); break;
		default:		tMUString = 'This should never happen ;)';
	}

	if((tMUString != '') && (User.listStyle == 'NORMAL'))
	{
		tMUString += ' - ' + this.userLinkString() + '\n';
	}

	return tMUString;
}


User.prototype.aboutUrl = function()
{/*
	Return the url of my IGN profile.
*/
	return 'http://club.ign.com/b/about?username=' + this.userName;
}


User.prototype.cssStyle = function()
{/*
	Return the style string for printing my username.
*/
	if(this.vipColors == null)
	{
		tStyle = 'class="AuthorLink"';
	} else {
		tStyle = this.vipColors.getCssString();
	}
	return tStyle;
}


User.prototype.htmlLinkString = function(postId)
{/*
	Return the HTML code to print my user link to a document.
*/
	tLink = '<a ';
	if(postId != null)
	{
		tLink += 'name="' + postId + '" ';
	}
	return tLink + 'href="' + this.aboutUrl() + '" ' + this.cssStyle() + '>' + this.userName + '</a>';
}


User.prototype.userColorsString = function()
{/*
	Return my user name in a form suitable for displaying.
	Use IGN markup to add colors information.
*/
	if (this.vipColors == null)
	return this.userName.markupPair('b');
	else return this.vipColors.getMarkupColors(this.userName);
}


User.prototype.userLinkString = function()
{/*
	Return my user name in a form suitable for displaying.
	Use IGN markup to add link information.
*/
	var tUserLinkString = 'link=' + this.aboutUrl();
	return this.userColorsString().markupPair(tUserLinkString);
}


