#ifndef PCTS
#define PCTS
extern const apstring COMBINED;
extern const apstring SINGLE;
extern const apstring DOUBLE;
extern apstring header(apstring);
extern apstring footer();
extern apstring linklist(int);
extern apstring playstyles(apstring);
extern apstring bannertitles(apstring, int);
extern apstring get_grade_image(apstring grade);

void loudmouth(usermaster &allusers, const apstring filename, apstring title);
	//prints lists of comment counts by SP / all / DP by count

void loudmouthp(usermaster &allusers, const apstring filename, apstring title);
	//prints lists of comment counts by SP / all / DP by percentage

void loudmouthw(usermaster &allusers, const apstring filename, apstring title);
	//prints lists of comment counts by SP / all / DP by percentage * count

void picurls(usermaster &allusers, const apstring filename, apstring title);
	//prints lists of comment counts by SP / all / DP by count

void picurlsp(usermaster &allusers, const apstring filename, apstring title);
	//prints lists of comment counts by SP / all / DP by percentage

void picurlsw(usermaster &allusers, const apstring filename, apstring title);
	//prints lists of comment counts by SP / all / DP by percentage * count

void sauna(usermaster &allusers, const apstring filename, apstring title);

////////////////////////////////
//BEGIN SONGPAGE DEFINITIONS
////////////////////////////////

void songpage(songmaster &allsongs, const apstring filename, apstring title, apstring sorttype);

apstring num2grade(double value);

////////////////////////////////
//END OF DEFINITIONS
////////////////////////////////

void loudmouth(usermaster &allusers, const apstring filename, apstring title)
//basically this is exactly the same as dj_point_totals, except it sorts the ranking by
//number of combos rather than djpoints.
{
	allusers.calc_comments();

	int stylecount=1+8;
	apvector <apstring> stylename(stylecount);
	apvector <apstring> fileextension(stylename.length());

   stylename[0]="All Styles"; fileextension[0]="_all.html";
   stylename[1]="3rd Style"; fileextension[1]="_3rd.html"; 	//do not change these extensions
   stylename[2]="4th style"; fileextension[2]="_4th.html";  //song wrapper depends on them
   stylename[3]="5th Style"; fileextension[3]="_5th.html"; 	//to match with fields in STYLES
   stylename[4]="6th Style"; fileextension[4]="_6th.html";	//tag in song entries
   stylename[5]="7th Style"; fileextension[5]="_7th.html";
   stylename[6]="8th Style"; fileextension[6]="_8th.html";
   stylename[7]="9th Style"; fileextension[7]="_9th.html";
   stylename[8]="10th Style"; fileextension[8]="_10th.html";

   for(int ii=0; ii<stylename.length(); ii++)
   {

	for(int mode=0; mode<3; mode++)
   {
//   	cout<<"ii="<<ii<<endl;
   	if(ii==0)
	   	allusers.sortby("comments",mode);
      else
         allusers.sortby("comments"+substring(fileextension[ii],0,"."),mode);

      apstring working_filename=filename;
      working_filename+=fileextension[ii];

      apstring spacer; //to be used in version linklist below
           if(mode==0) {spacer=COMBINED; working_filename+=COMBINED;}
      else if(mode==1) {spacer=SINGLE;   working_filename+=SINGLE;}
      else if(mode==2) {spacer=DOUBLE;   working_filename+=DOUBLE;}


	   ofstream ouf; ouf.open(working_filename.c_str());

	   ouf<<header(title);

      ouf<<linklist(mode);

		ouf<<bannertitles("LOUDMOUTH AWARDS",mode);

      ouf<<"<h2>"<<stylename[ii]<<" Ranking</h2>";

		ouf<<playstyles(filename+fileextension[ii]);

      ouf<<"<p><table border><tr>";
      for(int iii=0; iii<stylecount; iii++)						//version linklist
      	ouf<<"<td><a href=\""<<filename<<fileextension[iii]<<spacer<<"\">"<<stylename[iii]<<"</a></td>";
      ouf<<"</tr></table><p>";

	   int width=5;
	   ouf<<tablestart("border")
         <<td(6,"Rank")<<td(12,"User")<<td(12,"Comments")
         <<td(width,gif("AAA"))<<td(width,gif("AA"))<<td(width,gif("A"))<<td(width,gif("B"))
         <<td(width,gif("C"))<<td(width,gif("D"))<<td(width,gif("E"))<<td(width,gif("F"))
			<<td(width)<<td(width,"P")<<td(width,"FC")<<td(width,"clr")<<td(width,"play")
			<<td(width,"total");

		int rank=0;
		for(int i=0; i<allusers.userlist.length(); i++)
      	if((ii==0 && allusers.userlist[i].data[_("comments")][mode]>0) ||
      	   (ii==1 && allusers.userlist[i].data[_("comments_3rd")][mode]>0) ||
      	   (ii==2 && allusers.userlist[i].data[_("comments_4th")][mode]>0) ||
      	   (ii==3 && allusers.userlist[i].data[_("comments_5th")][mode]>0) ||
      	   (ii==4 && allusers.userlist[i].data[_("comments_6th")][mode]>0) ||
      	   (ii==5 && allusers.userlist[i].data[_("comments_7th")][mode]>0) ||
      	   (ii==6 && allusers.userlist[i].data[_("comments_8th")][mode]>0) ||
      	   (ii==7 && allusers.userlist[i].data[_("comments_9th")][mode]>0) ||
      	   (ii==8 && allusers.userlist[i].data[_("comments_10th")][mode]>0))
         {
		      ouf<<tr()
	            <<td(d2a(++rank))
	            <<djlink(allusers.userlist[i]);
            switch(ii) //output appropriate count
            {
            	case 0: ouf<<td("<font color=#ffcc44>"+d2a(allusers.userlist[i].data[_("comments")][mode])); break;
            	case 1: ouf<<td("<font color=#ffcc44>"+d2a(allusers.userlist[i].data[_("comments_3rd")][mode])); break;
            	case 2: ouf<<td("<font color=#ffcc44>"+d2a(allusers.userlist[i].data[_("comments_4th")][mode])); break;
            	case 3: ouf<<td("<font color=#ffcc44>"+d2a(allusers.userlist[i].data[_("comments_5th")][mode])); break;
            	case 4: ouf<<td("<font color=#ffcc44>"+d2a(allusers.userlist[i].data[_("comments_6th")][mode])); break;
            	case 5: ouf<<td("<font color=#ffcc44>"+d2a(allusers.userlist[i].data[_("comments_7th")][mode])); break;
            	case 6: ouf<<td("<font color=#ffcc44>"+d2a(allusers.userlist[i].data[_("comments_8th")][mode])); break;
            	case 7: ouf<<td("<font color=#ffcc44>"+d2a(allusers.userlist[i].data[_("comments_9th")][mode])); break;
            	case 8: ouf<<td("<font color=#ffcc44>"+d2a(allusers.userlist[i].data[_("comments_10th")][mode])); break;
         	}
            ouf<<td(d2a(allusers.userlist[i].data[_("AAA_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("AA_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("A_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("B_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("C_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("D_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("E_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("F_count")][mode]))
		         <<td()
		      	<<td(d2a(allusers.userlist[i].data[_("perfect")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("combo")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("clear")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("play")][mode]))
		         <<td(d2a(allusers.userlist[i].data[_("perfect")][mode]+allusers.userlist[i].data[_("combo")][mode]+allusers.userlist[i].data[_("clear")][mode]+allusers.userlist[i].data[_("play")][mode]));
         }

	   ouf<<tableend();

	   ouf<<footer();

	   ouf.close();
	}
   }
}

void picurls(usermaster &allusers, const apstring filename, apstring title)
//basically this is exactly the same as dj_point_totals, except it sorts the ranking by
//number of combos rather than djpoints.
{
	allusers.calc_picurls();
	for(int mode=0; mode<3; mode++)
   {
   	for(int STEP=65535; STEP>=1; STEP/=2)							//sort users by points for each mode
		   for(int h=0; h<STEP; h++)										//using shell sort
			   for(int i=STEP+h; i<allusers.userlist.length(); i+=STEP)
			   {
			   	int j=i;
			   	while(j>=STEP && allusers.userlist[j].data[_("picurls")][mode]>allusers.userlist[j-STEP].data[_("picurls")][mode])
			      {
			      	swap(allusers.userlist[j],allusers.userlist[j-STEP]);
			         j-=STEP;
			      }
			   }


   	apstring working_filename=filename;
           if(mode==0) working_filename+=COMBINED;
      else if(mode==1) working_filename+=SINGLE;
      else if(mode==2) working_filename+=DOUBLE;

	   ofstream ouf; ouf.open(working_filename.c_str());

	   ouf<<header(title);

      ouf<<linklist(mode);

		ouf<<bannertitles("CAMERA WHORE AWARDS",mode);

		ouf<<playstyles(filename);

	   int width=5;
	   ouf<<tablestart("border")
         <<td(6,"Rank")<<td(12,"User")<<td(12,"Images")
         <<td(width,gif("AAA"))<<td(width,gif("AA"))<<td(width,gif("A"))<<td(width,gif("B"))
         <<td(width,gif("C"))<<td(width,gif("D"))<<td(width,gif("E"))<<td(width,gif("F"))
			<<td(width)<<td(width,"P")<<td(width,"FC")<<td(width,"clr")<<td(width,"play")
			<<td(width,"total");

		int rank=0;
		for(int i=0; i<allusers.userlist.length(); i++)
      	if(allusers.userlist[i].data[_("picurls")][mode]>0)
		      ouf<<tr()
	            <<td(d2a(++rank))
	            <<djlink(allusers.userlist[i])
		      	<<td("<font color=#ffcc44>"+d2a(allusers.userlist[i].data[_("picurls")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("AAA_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("AA_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("A_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("B_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("C_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("D_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("E_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("F_count")][mode]))
		         <<td()
		      	<<td(d2a(allusers.userlist[i].data[_("perfect")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("combo")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("clear")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("play")][mode]))
		         <<td(d2a(allusers.userlist[i].data[_("perfect")][mode]+allusers.userlist[i].data[_("combo")][mode]+allusers.userlist[i].data[_("clear")][mode]+allusers.userlist[i].data[_("play")][mode]));

	   ouf<<tableend();

	   ouf<<footer();

	   ouf.close();
	}
}

///////////////////////////
////////////////////////////
//by percent
////////////////////////////
///////////////////////////

void loudmouthp(usermaster &allusers, const apstring filename, apstring title)
//basically this is exactly the same as dj_point_totals, except it sorts the ranking by
//number of combos rather than djpoints.
{
	allusers.calc_comments_pct();
	for(int mode=0; mode<3; mode++)
   {
		allusers.calc_comments_pct();
   	for(int STEP=65535; STEP>=1; STEP/=2)							//sort users by points for each mode
		   for(int h=0; h<STEP; h++)										//using shell sort
			   for(int i=STEP+h; i<allusers.userlist.length(); i+=STEP)
			   {
			   	int j=i;
			   	while(j>=STEP && (allusers.userlist[j].data[_("comments_pct")][mode]>allusers.userlist[j-STEP].data[_("comments_pct")][mode] ||
                                (allusers.userlist[j].data[_("comments_pct")][mode]==allusers.userlist[j-STEP].data[_("comments_pct")][mode] &&
                                	allusers.userlist[j].data[_("comments")][mode]>allusers.userlist[j-STEP].data[_("comments")][mode])))
			      {
			      	swap(allusers.userlist[j],allusers.userlist[j-STEP]);
			         j-=STEP;
			      }
			   }


   	apstring working_filename=filename;
           if(mode==0) working_filename+=COMBINED;
      else if(mode==1) working_filename+=SINGLE;
      else if(mode==2) working_filename+=DOUBLE;

	   ofstream ouf; ouf.open(working_filename.c_str());

	   ouf<<header(title);

      ouf<<linklist(mode);

		ouf<<bannertitles("LOUDMOUTH AWARDS BY PERCENT",mode);

		ouf<<playstyles(filename);

	   int width=5;
	   ouf<<tablestart("border")
         <<td(6,"Rank")<<td(12,"User")<<td(12,"Comments")
         <<td(width,gif("AAA"))<<td(width,gif("AA"))<<td(width,gif("A"))<<td(width,gif("B"))
         <<td(width,gif("C"))<<td(width,gif("D"))<<td(width,gif("E"))<<td(width,gif("F"))
			<<td(width)<<td(width*2,"percentage")<<td(width*2,"total");

		int rank=0;
		for(int i=0; i<allusers.userlist.length(); i++)
      	if(allusers.userlist[i].data[_("comments")][mode]>0)
		      ouf<<"<tr>"
	            <<"<td>"<<++rank<<"</td>"
	            <<djlink(allusers.userlist[i])
		      	<<"<td>"<<allusers.userlist[i].data[_("comments")][mode]<<"</td>"
		      	<<td(d2a(allusers.userlist[i].data[_("AAA_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("AA_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("A_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("B_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("C_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("D_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("E_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("F_count")][mode]))
		         <<td()
 		      	<<"<td><font color=#ffcc44>"<<int(allusers.userlist[i].data[_("comments_pct")][mode])<<"."<<int(allusers.userlist[i].data[_("comments_pct")][mode]*10)%10<<int(allusers.userlist[i].data[_("comments_pct")][mode]*100)%10<<"%</td>"
		         <<"<td>"<<allusers.userlist[i].data[_("perfect")][mode]+allusers.userlist[i].data[_("combo")][mode]+allusers.userlist[i].data[_("clear")][mode]+allusers.userlist[i].data[_("play")][mode]<<"</td>"
	            <<"</tr>";

	   ouf<<tableend();

	   ouf<<footer();

	   ouf.close();
	}
}

void picurlsp(usermaster &allusers, const apstring filename, apstring title)
//basically this is exactly the same as dj_point_totals, except it sorts the ranking by
//number of combos rather than djpoints.
{
	allusers.calc_picurls_pct();
	for(int mode=0; mode<3; mode++)
   {
   	for(int STEP=65535; STEP>=1; STEP/=2)							//sort users by points for each mode
		   for(int h=0; h<STEP; h++)										//using shell sort
			   for(int i=STEP+h; i<allusers.userlist.length(); i+=STEP)
			   {
			   	int j=i;
			   	while(j>=STEP && (allusers.userlist[j].data[_("picurls_pct")][mode]>allusers.userlist[j-STEP].data[_("picurls_pct")][mode] ||
                                (allusers.userlist[j].data[_("picurls_pct")][mode]==allusers.userlist[j-STEP].data[_("picurls_pct")][mode] &&
                                	allusers.userlist[j].data[_("picurls")][mode]>allusers.userlist[j-STEP].data[_("picurls")][mode])))
			      {
			      	swap(allusers.userlist[j],allusers.userlist[j-STEP]);
			         j-=STEP;
			      }
			   }


   	apstring working_filename=filename;
           if(mode==0) working_filename+=COMBINED;
      else if(mode==1) working_filename+=SINGLE;
      else if(mode==2) working_filename+=DOUBLE;

	   ofstream ouf; ouf.open(working_filename.c_str());

	   ouf<<header(title);

      ouf<<linklist(mode);

		ouf<<bannertitles("CAMERA WHORE AWARDS BY PERCENT",mode);

		ouf<<playstyles(filename);

	   int width=5;
	   ouf<<tablestart("border")
         <<td(6,"Rank")<<td(12,"User")<<td(12,"Images")
         <<td(width,gif("AAA"))<<td(width,gif("AA"))<<td(width,gif("A"))<<td(width,gif("B"))
         <<td(width,gif("C"))<<td(width,gif("D"))<<td(width,gif("E"))<<td(width,gif("F"))
			<<td(width)<<td(width*2,"percentage")<<td(width*2,"total");


		int rank=0;
		for(int i=0; i<allusers.userlist.length(); i++)
      	if(allusers.userlist[i].data[_("picurls")][mode]>0)
		      ouf<<"<tr>"
	            <<"<td>"<<++rank<<"</td>"
	            <<djlink(allusers.userlist[i])
		      	<<"<td>"<<allusers.userlist[i].data[_("picurls")][mode]<<"</td>"
		      	<<"<td>"<<allusers.userlist[i].data[_("AAA_count")][mode]<<"</td>"
		      	<<"<td>"<<allusers.userlist[i].data[_("AA_count")][mode]<<"</td>"
		      	<<"<td>"<<allusers.userlist[i].data[_("A_count")][mode]<<"</td>"
		      	<<"<td>"<<allusers.userlist[i].data[_("B_count")][mode]<<"</td>"
		      	<<"<td>"<<allusers.userlist[i].data[_("C_count")][mode]<<"</td>"
		      	<<"<td>"<<allusers.userlist[i].data[_("D_count")][mode]<<"</td>"
		      	<<"<td>"<<allusers.userlist[i].data[_("E_count")][mode]<<"</td>"
		      	<<"<td>"<<allusers.userlist[i].data[_("F_count")][mode]<<"</td>"
		         <<"<td></td>"
 		      	<<"<td><font color=#ffcc44>"<<int(allusers.userlist[i].data[_("picurls_pct")][mode])<<"."<<int(allusers.userlist[i].data[_("picurls_pct")][mode]*10)%10<<int(allusers.userlist[i].data[_("picurls_pct")][mode]*100)%10<<"%</td>"
		         <<"<td>"<<allusers.userlist[i].data[_("perfect")][mode]+allusers.userlist[i].data[_("combo")][mode]+allusers.userlist[i].data[_("clear")][mode]+allusers.userlist[i].data[_("play")][mode]<<"</td>"
	            <<"</tr>";

	   ouf<<"</table>";

	   ouf<<footer();

	   ouf.close();
	}
}

/////////////////////////
//////////////////////////
//by weighted
//////////////////////////
/////////////////////////

void loudmouthw(usermaster &allusers, const apstring filename, apstring title)
//basically this is exactly the same as dj_point_totals, except it sorts the ranking by
//number of combos rather than djpoints.
{
	allusers.calc_comments_weight();
	for(int mode=0; mode<3; mode++)
   {
   	for(int STEP=65535; STEP>=1; STEP/=2)							//sort users by points for each mode
		   for(int h=0; h<STEP; h++)										//using shell sort
			   for(int i=STEP+h; i<allusers.userlist.length(); i+=STEP)
			   {
			   	int j=i;
			   	while(j>=STEP && (allusers.userlist[j].data[_("comments_weight")][mode]>allusers.userlist[j-STEP].data[_("comments_weight")][mode] ||
                                (allusers.userlist[j].data[_("comments_weight")][mode]==allusers.userlist[j-STEP].data[_("comments_weight")][mode] &&
                                	allusers.userlist[j].data[_("comments")][mode]>allusers.userlist[j-STEP].data[_("comments")][mode])))
			      {
			      	swap(allusers.userlist[j],allusers.userlist[j-STEP]);
			         j-=STEP;
			      }
			   }


   	apstring working_filename=filename;
           if(mode==0) working_filename+=COMBINED;
      else if(mode==1) working_filename+=SINGLE;
      else if(mode==2) working_filename+=DOUBLE;

	   ofstream ouf; ouf.open(working_filename.c_str());

	   ouf<<header(title);

      ouf<<linklist(mode);

		ouf<<bannertitles("LOUDMOUTH AWARDS BY WEIGHTED TOTAL",mode);

		ouf<<playstyles(filename);

	   int width=9;
	   ouf<<tablestart("border")
         <<td(6,"Rank")<<td(10,"User")<<td(12,"Comments")
         <<td(width,gif("AAA"))<<td(width,gif("AA"))<<td(width,gif("A"))
			<<td(width)<<td(width,"percentage")<<td(width*2,"weight")<<td(width,"total");

		int rank=0;
		for(int i=0; i<allusers.userlist.length(); i++)
      	if(allusers.userlist[i].data[_("comments")][mode]>0)
		      ouf<<"<tr>"
	            <<"<td>"<<++rank<<"</td>"
	            <<djlink(allusers.userlist[i])
		      	<<"<td>"<<allusers.userlist[i].data[_("comments")][mode]<<"</td>"
		      	<<"<td>"<<allusers.userlist[i].data[_("AAA_count")][mode]<<"</td>"
		      	<<"<td>"<<allusers.userlist[i].data[_("AA_count")][mode]<<"</td>"
		      	<<"<td>"<<allusers.userlist[i].data[_("A_count")][mode]<<"</td>"
		         <<"<td></td>"
		      	<<"<td>"<<int(allusers.userlist[i].data[_("comments_pct")][mode])<<"."<<int(allusers.userlist[i].data[_("comments_pct")][mode]*10)%10<<int(allusers.userlist[i].data[_("comments_pct")][mode]*100)%10<<"%</td>"
		      	<<"<td><font color=#ffcc44>"<<int(allusers.userlist[i].data[_("comments_weight")][mode])<<"."<<int(allusers.userlist[i].data[_("comments_weight")][mode]*10)%10<<int(allusers.userlist[i].data[_("comments_weight")][mode]*100)%10<<"</td>"
		         <<"<td>"<<allusers.userlist[i].data[_("perfect")][mode]+allusers.userlist[i].data[_("combo")][mode]+allusers.userlist[i].data[_("clear")][mode]+allusers.userlist[i].data[_("play")][mode]<<"</td>"
	            <<"</tr>";

	   ouf<<"</table>";

	   ouf<<footer();

	   ouf.close();
	}
}

void picurlsw(usermaster &allusers, const apstring filename, apstring title)
//basically this is exactly the same as dj_point_totals, except it sorts the ranking by
//number of combos rather than djpoints.
{
	allusers.calc_picurls_weight();
	for(int mode=0; mode<3; mode++)
   {
   	for(int STEP=65535; STEP>=1; STEP/=2)							//sort users by points for each mode
		   for(int h=0; h<STEP; h++)										//using shell sort
			   for(int i=STEP+h; i<allusers.userlist.length(); i+=STEP)
			   {
			   	int j=i;
			   	while(j>=STEP && (allusers.userlist[j].data[_("picurls_weight")][mode]>allusers.userlist[j-STEP].data[_("picurls_weight")][mode] ||
                                (allusers.userlist[j].data[_("picurls_weight")][mode]==allusers.userlist[j-STEP].data[_("picurls_weight")][mode] &&
                                	allusers.userlist[j].data[_("picurls")][mode]>allusers.userlist[j-STEP].data[_("picurls")][mode])))
			      {
			      	swap(allusers.userlist[j],allusers.userlist[j-STEP]);
			         j-=STEP;
			      }
			   }


   	apstring working_filename=filename;
           if(mode==0) working_filename+=COMBINED;
      else if(mode==1) working_filename+=SINGLE;
      else if(mode==2) working_filename+=DOUBLE;

	   ofstream ouf; ouf.open(working_filename.c_str());

	   ouf<<header(title);

      ouf<<linklist(mode);

		ouf<<bannertitles("CAMERA WHORE AWARDS BY WEIGHTED TOTAL",mode);

		ouf<<playstyles(filename);

	   int width=9;
	   ouf<<tablestart("border")
         <<td(6,"Rank")<<td(10,"User")<<td(12,"Images")
         <<td(width,gif("AAA"))<<td(width,gif("AA"))<<td(width,gif("A"))
			<<td(width)<<td(width,"percentage")<<td(width*2,"weight")<<td(width,"total");

		int rank=0;
		for(int i=0; i<allusers.userlist.length(); i++)
      	if(allusers.userlist[i].data[_("picurls")][mode]>0)
		      ouf<<"<tr>"
	            <<"<td>"<<++rank<<"</td>"
	            <<djlink(allusers.userlist[i])
		      	<<"<td><font color=#ffcc44>"<<allusers.userlist[i].data[_("picurls")][mode]<<"</td>"
		      	<<"<td>"<<allusers.userlist[i].data[_("AAA_count")][mode]<<"</td>"
		      	<<"<td>"<<allusers.userlist[i].data[_("AA_count")][mode]<<"</td>"
		      	<<"<td>"<<allusers.userlist[i].data[_("A_count")][mode]<<"</td>"
		         <<"<td></td>"
		      	<<"<td>"<<int(allusers.userlist[i].data[_("picurls_pct")][mode])<<"."<<int(allusers.userlist[i].data[_("picurls_pct")][mode]*10)%10<<int(allusers.userlist[i].data[_("picurls_pct")][mode]*100)%10<<"%</td>"
		      	<<"<td><font color=#ffcc44>"<<int(allusers.userlist[i].data[_("picurls_weight")][mode])<<"."<<int(allusers.userlist[i].data[_("picurls_weight")][mode]*10)%10<<int(allusers.userlist[i].data[_("picurls_weight")][mode]*100)%10<<"</td>"
		         <<"<td>"<<allusers.userlist[i].data[_("perfect")][mode]+allusers.userlist[i].data[_("combo")][mode]+allusers.userlist[i].data[_("clear")][mode]+allusers.userlist[i].data[_("play")][mode]<<"</td>"
	            <<"</tr>";

	   ouf<<"</table>";

	   ouf<<footer();

	   ouf.close();
	}
}

void sauna(usermaster &allusers, const apstring filename, apstring title)
{
	allusers.calc_sauna();

	for(int mode=0; mode<3; mode++)
   {
   	allusers.sortby("towels",mode);

   	apstring working_filename=filename;
           if(mode==0) working_filename+=COMBINED;
      else if(mode==1) working_filename+=SINGLE;
      else if(mode==2) working_filename+=DOUBLE;

	   ofstream ouf; ouf.open(working_filename.c_str());

	   ouf<<header(title);

      ouf<<linklist(mode);

		ouf<<bannertitles("SAUNA MODE",mode);

		ouf<<playstyles(filename);

	   int width=5;
	   ouf<<tablestart("border")
         <<td(6,"Rank")<<td(12,"User")<<td(12,"Towels")
         <<td(width,gif("AAA"))<<td(width,gif("AA"))<<td(width,gif("A"))<<td(width,gif("B"))
         <<td(width,gif("C"))<<td(width,gif("D"))<<td(width,gif("E"))<<td(width,gif("F"))
			<<td(width)<<td(width,"P")<<td(width,"FC")<<td(width,"clr")<<td(width,"play")
			<<td(width,"total");

		int rank=0;
		for(int i=0; i<allusers.userlist.length(); i++)
      	if(allusers.userlist[i].data[_("towels")][mode]>0)
		      ouf<<tr()
	            <<td(d2a(++rank))
	            <<djlink(allusers.userlist[i])
		      	<<td("<font color=#ffcc44>"+d2a(allusers.userlist[i].data[_("towels")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("AAA_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("AA_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("A_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("B_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("C_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("D_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("E_count")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("F_count")][mode]))
		         <<td()
		      	<<td(d2a(allusers.userlist[i].data[_("perfect")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("combo")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("clear")][mode]))
		      	<<td(d2a(allusers.userlist[i].data[_("play")][mode]))
		         <<td(d2a(allusers.userlist[i].data[_("perfect")][mode]+allusers.userlist[i].data[_("combo")][mode]+allusers.userlist[i].data[_("clear")][mode]+allusers.userlist[i].data[_("play")][mode]));

	   ouf<<tableend();

	   ouf<<footer();

	   ouf.close();
	}
}

////////////////////////////////
//BEGIN SONGPAGE FUNCTIONS
////////////////////////////////

void songpage(songmaster &allsongs, const apstring filename, apstring title, apstring sorttype)
{
	allsongs.sortby(sorttype);       //prepare list for table

	for(int mode=0; mode<3; mode++)
   {

   	apstring working_filename=filename;
           if(mode==0) working_filename+=COMBINED;
      else if(mode==1) working_filename+=SINGLE;
      else if(mode==2) working_filename+=DOUBLE;

	   ofstream ouf; ouf.open(working_filename.c_str());

		ouf<<header(title);

	   ouf<<linklist(mode); //get mode-specific linklist

		ouf<<bannertitles(title,mode);

		ouf<<playstyles(filename);

	   ouf<<tablestart("border");

	   int width=0;
	   ouf<<"<td></td>"
      	<<td("Title + Mode")
	      <<td("Plays")
	      <<"<td width="+d2a(width*2,0)+"% colspan=2><center>AAA's</td>"
	      <<"<td width="+d2a(width*3,0)+"% colspan=3><center>EX Tot/Avg/%Avg</td>"
	      <<"<td width="+d2a(width*2,0)+"% colspan=2><center>High EX/%</td>"
	      <<"<td width="+d2a(width*2,0)+"% colspan=2><center>Clears/Rate</td>"
	      <<"<td width="+d2a(width*2,0)+"% colspan=2><center>FC's/Rate</td>"
	      <<"<td width="+d2a(width*2,0)+"% colspan=2><center>PC's/Rate</td>"
	      <<"<td width="+d2a(width*2,0)+"% colspan=2><center>Comments/Rate</td>";

      int rank=0;
	   for(int i=0; i<allsongs.songlist.length(); i++)
	   {
      	if(mode==0 ||
            (mode==1 && (allsongs.songlist[i].mode=="L7" || allsongs.songlist[i].mode=="7" || allsongs.songlist[i].mode=="A")) ||
            (mode==2 && (allsongs.songlist[i].mode=="L14" || allsongs.songlist[i].mode=="14" || allsongs.songlist[i].mode=="A14"))
           )
         {
		   	ouf<<tr();
	         ouf<<td(d2a(++rank,0));
		      ouf<<td(allsongs.songlist[i].head->tr_e2j(allsongs.songlist[i].title)+" <b>"+allsongs.songlist[i].mode);

		      apstring field; //tells which field to highlight in the table
		      double value; //used to replace long variable names
		      int decimals; //tells d2a() how many decimal places to print out
		      apstring append=""; //something to put after the cell data, like a '%' character


		      for(int j=0; j<16; j++)	//iterates through fields and simplifies printing them out
		      {
		      	append=""; //reset it back to null

					switch(j)	//determine which values to load into cell
		         {
		         	case 0: field="playcount";
		            		  value=allsongs.songlist[i].playcount;
		         			  decimals=0;
		                    break;
		         	case 1: field="aaacount";
		            		  value=allsongs.songlist[i].aaacount;
		         			  decimals=0;
		                    break;
		         	case 2: field="aaarate";
		            		  value=double(allsongs.songlist[i].aaacount)/allsongs.songlist[i].playcount*100;
		         			  decimals=2;
		                    append="%";
		                    break;
		         	case 3: field="extotal";
		            		  value=allsongs.songlist[i].extotal;
		         			  decimals=0;
		                    break;
		         	case 4: field="extotalavg";
		            		  value=double(allsongs.songlist[i].extotal)/allsongs.songlist[i].playcount;
		         			  decimals=2;
		                    break;
		         	case 5: field="expctavg";
		            		  value=double(allsongs.songlist[i].extotal)/allsongs.songlist[i].playcount/(allsongs.songlist[i].head->notes)*100/2;
		         			  decimals=2;
		                    append="%"+num2grade(value/100.0);
		                    break;
		         	case 6: field="highscore";
		            		  value=allsongs.songlist[i].highscore;
		         			  decimals=0;
		                    break;
		         	case 7: field="highpct";
		            		  value=allsongs.songlist[i].highpct*100;
		         			  decimals=2;
		                    append="%"+num2grade(value/100.0);
		                    break;
		         	case 8: field="clearcount";
		            		  value=allsongs.songlist[i].clearcount;
		         			  decimals=0;
		                    break;
		         	case 9: field="clearrate";
		            		  value=double(allsongs.songlist[i].clearcount)/allsongs.songlist[i].playcount*100;
		         			  decimals=2;
		                    append="%";
		                    break;
		         	case 10: field="fccount";
		            		  value=allsongs.songlist[i].fccount;
		         			  decimals=0;
		                    break;
		         	case 11: field="fcrate";
		            		  value=double(allsongs.songlist[i].fccount)/allsongs.songlist[i].playcount*100;
		         			  decimals=2;
		                    append="%";
		                    break;
		         	case 12: field="pccount";
		            		  value=allsongs.songlist[i].pccount;
		         			  decimals=0;
		                    break;
		         	case 13: field="pcrate";
		            		  value=double(allsongs.songlist[i].pccount)/allsongs.songlist[i].playcount*100;
		         			  decimals=2;
		                    append="%";
		                    break;
		         	case 14: field="commentcount";
		            		  value=allsongs.songlist[i].commentcount;
		         			  decimals=0;
		                    break;
		         	case 15: field="commentrate";
		            		  value=double(allsongs.songlist[i].commentcount)/allsongs.songlist[i].playcount*100;
		         			  decimals=2;
		                    append="%";
		                    break;
		         }

		         decimals=0; //force to zero to save space

			      if(sorttype==field)
			      	ouf<<td("<font color=#ffcc44>"+d2a(value,decimals)+append);
			      else
			      	ouf<<td(d2a(value,decimals)+append);
		      }
         }
	   }

	   ouf<<tableend();

	   ouf<<footer();

		ouf.close();
	}
}

apstring num2grade(double value)
{
	if(value*9>=8) return get_grade_image("AAA");
	else if(value*9>=7) return get_grade_image("AA");
	else if(value*9>=6) return get_grade_image("A");
 	else if(value*9>=5) return get_grade_image("B");
	else if(value*9>=4) return get_grade_image("C");
	else if(value*9>=3) return get_grade_image("D");
	else if(value*9>=2) return get_grade_image("E");

   return get_grade_image("F");
}

#endif