1stMud4.5.3/
1stMud4.5.3/backup/
1stMud4.5.3/bin/
1stMud4.5.3/bin/extras/
1stMud4.5.3/data/i3/
1stMud4.5.3/doc/1stMud/
1stMud4.5.3/doc/Diku/
1stMud4.5.3/doc/MPDocs/
1stMud4.5.3/doc/Rom/
1stMud4.5.3/notes/
/**************************************************************************
*  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
*  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
*                                                                         *
*  Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael         *
*  Chastain, Michael Quan, and Mitchell Tse.                              *
*                                                                         *
*  In order to use any part of this Merc Diku Mud, you must comply with   *
*  both the original Diku license in 'license.doc' as well the Merc       *
*  license in 'license.txt'.  In particular, you may not remove either of *
*  these copyright notices.                                               *
*                                                                         *
*  Much time and thought has gone into this software and you are          *
*  benefiting.  We hope that you share your changes too.  What goes       *
*  around, comes around.                                                  *
***************************************************************************
*       ROM 2.4 is copyright 1993-1998 Russ Taylor                        *
*       ROM has been brought to you by the ROM consortium                 *
*           Russ Taylor (rtaylor@hypercube.org)                           *
*           Gabrielle Taylor (gtaylor@hypercube.org)                      *
*           Brian Moore (zump@rom.org)                                    *
*       By using this code, you have agreed to follow the terms of the    *
*       ROM license, in the file Rom24/doc/rom.license                    *
***************************************************************************
*          1stMud ROM Derivative (c) 2001-2004 by Markanth                *
*            http://www.firstmud.com/  <markanth@firstmud.com>            *
*         By using this code you have agreed to follow the term of        *
*             the 1stMud license in ../doc/1stMud/LICENSE                 *
***************************************************************************/

#include "merc.h"
#include "interp.h"
#include "recycle.h"
#include "data_table.h"

DataTable stat_data_table[] = {
	{"name", FIELD_STRING, (void *) &stat_zero.name, NULL, NULL},
	{"stats", FIELD_LONG_ARRAY, (void *) &stat_zero.gamestat,
	 (const void *) MAX_GAMESTAT, (const void *) 0},
	{"version", FIELD_INT, (void *) &stat_zero.version, NULL, NULL},
	{NULL, (field_t) - 1, NULL, NULL, NULL}
};

TableSave_Fun(rw_stat_data)
{
	rw_list(type, STAT_FILE, StatData, stat);
}

void update_statlist(CharData * ch, bool pdelete)
{
	StatData *prev;
	StatData *curr;
	int i;

	if (IsNPC(ch) || IsImmortal(ch))
		return;

	prev = NULL;

	for (curr = stat_first; curr != NULL; curr = prev)
	{
		prev = curr->next;

		if (!str_cmp(ch->name, curr->name))
		{
			if (curr->version < mud_info.stats.version)
			{
				memset(curr->gamestat, 0, MAX_GAMESTAT);
				memset(ch->pcdata->gamestat, 0, MAX_GAMESTAT);
			}
			UnLink(curr, stat, next, prev);
			free_stat(curr);
		}
	}
	if (pdelete || IsNPC(ch) || IsImmortal(ch))
	{
		rw_stat_data(act_write);
		return;
	}

	curr = new_stat();
	curr->name = str_dup(ch->name);
	curr->version = mud_info.stats.version;
	for (i = 0; i < MAX_GAMESTAT; i++)
		curr->gamestat[i] = GetStat(ch, i);

	Link(curr, stat, next, prev);
	rw_stat_data(act_write);
	return;
}

const char *print_stat(CharData * ch, const char *head, long value)
{
	return FORMATF("{W%-19.19s {w[{R%10.10ld{w]", head, value);
}

Do_Fun(do_showstats)
{
	int option;
	char arg[MIL];

	argument = one_argument(argument, arg);

	if (NullStr(arg))
	{
		chprintln(ch, "      {ROPTIONS AVAILABLE:{x");
		chprintln(ch, "      {G0{x - Show general {n stats. (gstats)");
		chprintln(ch, "      {G1{x - Ranking of Player Killers (pkills)");
		chprintln(ch, "      {G2{x - Ranking of Player Deaths (pdeaths)");
		chprintln(ch, "      {G3{x - Ranking of Mob Kills (mkills)");
		chprintln(ch, "      {G4{x - Ranking of Mob Deaths (mdeaths)");
		chprintln(ch, "      {G5{x - Personal Rankings (personal)");
		if (IsImmortal(ch))
			chprintln(ch, "      {Gdelete <name>{x - deletes from statlist");
		return;
	}
	option = atoi(arg);

	if (!str_cmp(arg, "delete") && IsImmortal(ch))
	{
		StatData *prev = NULL;
		StatData *curr = NULL;
		bool found = false;

		for (curr = stat_first; curr != NULL; curr = prev)
		{
			prev = curr->next;

			if (!str_cmp(argument, curr->name))
			{
				UnLink(curr, stat, next, prev);
				free_stat(curr);
				rw_stat_data(act_write);
				found = true;
			}
		}
		if (!found)
			chprintlnf(ch, "Error deleting %s.", argument);
	}
	else if (option == 0 || !str_prefix(arg, "gstats"))
	{
		Column *Cd;
		Buffer *b;

		Cd = new_column();
		b = new_buf();
		set_cols(Cd, ch, 2, COLS_BUF, b);

		bprintln(b,
				 stringf(ch, 0, Center, "{R-{r=", "{C[ %s Stats ]",
						 mud_info.name));
		print_cols(Cd, print_stat(ch, "Logins", mud_info.stats.logins));
		print_cols(Cd, print_stat(ch, "Quests", mud_info.stats.quests));
		print_cols(Cd,
				   print_stat(ch, "Quests Complete",
							  mud_info.stats.qcomplete));
		print_cols(Cd, print_stat(ch, "Levels", mud_info.stats.levels));
		print_cols(Cd, print_stat(ch, "Newbies", mud_info.stats.newbies));
		print_cols(Cd, print_stat(ch, "Deletions", mud_info.stats.deletions));
		print_cols(Cd,
				   print_stat(ch, "Mob Deaths", mud_info.stats.mobdeaths));
		print_cols(Cd, print_stat(ch, "Auctions", mud_info.stats.auctions));
		print_cols(Cd,
				   print_stat(ch, "Auctions Sold", mud_info.stats.aucsold));
		print_cols(Cd, print_stat(ch, "Player Deaths", mud_info.stats.pdied));
		print_cols(Cd, print_stat(ch, "Player Kills", mud_info.stats.pkill));
		print_cols(Cd, print_stat(ch, "Notes", mud_info.stats.notes));
		print_cols(Cd, print_stat(ch, "Remorts", mud_info.stats.remorts));
		print_cols(Cd, print_stat(ch, "Wars", mud_info.stats.wars));
		print_cols(Cd,
				   print_stat(ch, "Global Quests", mud_info.stats.gquests));
		print_cols(Cd,
				   print_stat(ch, "Connections", mud_info.stats.connections));
		print_cols(Cd,
				   print_stat(ch, "Connects this Boot",
							  mud_info.stats.boot_connects));
		print_cols(Cd,
				   print_stat(ch, "Online Record", mud_info.stats.online));
		print_cols(Cd,
				   print_stat(ch, "Web Hits", mud_info.stats.web_requests));
		print_cols(Cd,
				   print_stat(ch, "Channel Messages",
							  mud_info.stats.chan_msgs));
		cols_nl(Cd);
		bprintln(b,
				 stringf(ch, 0, Center, "{R-{r=", "{C[ Stats since: %s ]",
						 str_time(mud_info.stats.lastupdate, GetTzone(ch),
								  NULL)));
		sendpage(ch, buf_string(b));
		free_buf(b);
		free_column(Cd);
		return;
	}
	else if (option == 1 || !str_prefix(arg, "pkills"))
		show_game_stats(ch, PK_KILLS);
	else if (option == 3 || !str_prefix(arg, "mkills"))
		show_game_stats(ch, MOB_KILLS);
	else if (option == 2 || !str_prefix(arg, "pdeaths"))
		show_game_stats(ch, PK_DEATHS);
	else if (option == 4 || !str_prefix(arg, "mdeaths"))
		show_game_stats(ch, MOB_DEATHS);
	else if (option == 5 || !str_prefix(arg, "personal"))
	{
		StatData *curr;
		Column Cd;
		Buffer b;
		int i = 0;
		const char *stat_self[MAX_GAMESTAT] = {
			"PLAYER KILLS",
			"MOB KILLS",
			"PK DEATHS",
			"MOB DEATHS",
		};

		update_statlist(ch, false);

		for (curr = stat_first; curr != NULL; curr = curr->next)
			if (!str_cmp(ch->name, curr->name))
				break;

		if (!curr)
		{
			chprintln(ch, "You have no stats yet.");
			return;
		}

		set_cols(&Cd, ch, 2, COLS_BUF, &b);

		bprintln(&b,
				 stringf(ch, 0, Center, "{r-{R=",
						 "{C[ RANKING OF PERSONAL BESTS ]"));
		for (i = 0; i < MAX_GAMESTAT; i++)
		{
			print_cols(&Cd, "{G%2d{w){W %s{x", i + 1,
					   print_stat(ch, stat_self[i], curr->gamestat[i]));
		}
		cols_nl(&Cd);
		bprintln(&b, draw_line(ch, "{r-{R=", 0));
		sendpage(ch, buf_string(&b));
		return;
	}
	else
		do_showstats(n_fun, ch, "");

	return;
}

int compare_type;

int compare_stats(const void *v1, const void *v2)
{
	StatData *stat1 = *(StatData **) v1;
	StatData *stat2 = *(StatData **) v2;

	if (!stat2)
		return 1;
	if (!stat1)
		return 2;

	return stat2->gamestat[compare_type] - stat1->gamestat[compare_type];
}

void show_game_stats(CharData * ch, int type)
{
	StatData *curr;
	Buffer *output;
	StatData **top;
	Column *Cd, c;
	int count, loop;
	bool found = false;
	const char *stat_name[MAX_GAMESTAT] = {
		"PLAYER KILLERS",
		"MOB KILLERS",
		"PK DEATHS",
		"MOB DEATHS",
	};

	output = new_buf();
	Cd = &c;
	set_cols(Cd, ch, 2, COLS_BUF, output);
	count = 0;
	compare_type = type;

	alloc_mem(top, StatData *, top_stat);

	bprintln(output,
			 stringf(ch, 0, Center, "{R-{r=", "{C[ RANKING OF %s ]",
					 stat_name[type]));
	loop = 0;
	loop = 0;
	for (curr = stat_first; curr != NULL; curr = curr->next)
	{
		top[count] = curr;
		count++;
		found = true;
	}

	if (found)
	{
		qsort(top, count, sizeof(*top), compare_stats);

		for (loop = 0; loop < count; loop++)
		{
			if (loop >= 50)
				break;

			print_cols(Cd, "{G%2d{w){W %-20s {w[{R%8ld{W]{x", loop + 1,
					   top[loop]->name, top[loop]->gamestat[type]);
		}
	}
	if (!found)
		bprintln(output, "No one found yet.");
	else
		cols_nl(Cd);
	bprintln(output, draw_line(ch, "{R-{r=", 0));
	sendpage(ch, buf_string(output));
	free_mem(top);
	free_buf(output);
	free_column(Cd);
	return;
}