tmi2_fluffos_v2/
tmi2_fluffos_v2/bin/
tmi2_fluffos_v2/etc/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/ChangeLog.old/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/Win32/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/compat/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/compat/simuls/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/include/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/clone/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/command/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/data/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/etc/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/include/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/inherit/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/inherit/master/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/log/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/compiler/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/efuns/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/operators/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/u/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/tmp/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/windows/
tmi2_fluffos_v2/lib/
tmi2_fluffos_v2/lib/adm/
tmi2_fluffos_v2/lib/adm/daemons/languages/
tmi2_fluffos_v2/lib/adm/daemons/network/I3/
tmi2_fluffos_v2/lib/adm/daemons/virtual/
tmi2_fluffos_v2/lib/adm/daemons/virtual/template/
tmi2_fluffos_v2/lib/adm/news/
tmi2_fluffos_v2/lib/adm/obj/
tmi2_fluffos_v2/lib/adm/obj/master/
tmi2_fluffos_v2/lib/adm/priv/
tmi2_fluffos_v2/lib/adm/shell/
tmi2_fluffos_v2/lib/adm/tmp/
tmi2_fluffos_v2/lib/cmds/
tmi2_fluffos_v2/lib/d/
tmi2_fluffos_v2/lib/d/Conf/
tmi2_fluffos_v2/lib/d/Conf/adm/
tmi2_fluffos_v2/lib/d/Conf/boards/
tmi2_fluffos_v2/lib/d/Conf/cmds/
tmi2_fluffos_v2/lib/d/Conf/data/
tmi2_fluffos_v2/lib/d/Conf/logs/
tmi2_fluffos_v2/lib/d/Conf/obj/
tmi2_fluffos_v2/lib/d/Conf/text/help/
tmi2_fluffos_v2/lib/d/Fooland/adm/
tmi2_fluffos_v2/lib/d/Fooland/data/
tmi2_fluffos_v2/lib/d/Fooland/data/attic/
tmi2_fluffos_v2/lib/d/Fooland/items/
tmi2_fluffos_v2/lib/d/TMI/
tmi2_fluffos_v2/lib/d/TMI/adm/
tmi2_fluffos_v2/lib/d/TMI/boards/
tmi2_fluffos_v2/lib/d/TMI/data/
tmi2_fluffos_v2/lib/d/TMI/rooms/
tmi2_fluffos_v2/lib/d/grid/
tmi2_fluffos_v2/lib/d/grid/adm/
tmi2_fluffos_v2/lib/d/grid/data/
tmi2_fluffos_v2/lib/d/std/
tmi2_fluffos_v2/lib/d/std/adm/
tmi2_fluffos_v2/lib/data/adm/
tmi2_fluffos_v2/lib/data/adm/daemons/
tmi2_fluffos_v2/lib/data/adm/daemons/doc_d/
tmi2_fluffos_v2/lib/data/adm/daemons/emoted/
tmi2_fluffos_v2/lib/data/adm/daemons/network/http/
tmi2_fluffos_v2/lib/data/adm/daemons/network/services/mail_q/
tmi2_fluffos_v2/lib/data/adm/daemons/network/smtp/
tmi2_fluffos_v2/lib/data/adm/daemons/news/archives/
tmi2_fluffos_v2/lib/data/attic/connection/
tmi2_fluffos_v2/lib/data/attic/user/
tmi2_fluffos_v2/lib/data/std/connection/b/
tmi2_fluffos_v2/lib/data/std/connection/l/
tmi2_fluffos_v2/lib/data/std/user/a/
tmi2_fluffos_v2/lib/data/std/user/b/
tmi2_fluffos_v2/lib/data/std/user/d/
tmi2_fluffos_v2/lib/data/std/user/f/
tmi2_fluffos_v2/lib/data/std/user/l/
tmi2_fluffos_v2/lib/data/std/user/x/
tmi2_fluffos_v2/lib/data/u/d/dm/working/doc_d/
tmi2_fluffos_v2/lib/data/u/l/leto/doc_d/
tmi2_fluffos_v2/lib/data/u/l/leto/smtp/
tmi2_fluffos_v2/lib/doc/
tmi2_fluffos_v2/lib/doc/driverdoc/applies/
tmi2_fluffos_v2/lib/doc/driverdoc/applies/interactive/
tmi2_fluffos_v2/lib/doc/driverdoc/concepts/
tmi2_fluffos_v2/lib/doc/driverdoc/driver/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/arrays/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/buffers/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/compile/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/ed/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/filesystem/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/floats/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/functions/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/general/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/mappings/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/numbers/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/parsing/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/constructs/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/preprocessor/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/types/
tmi2_fluffos_v2/lib/doc/driverdoc/platforms/
tmi2_fluffos_v2/lib/doc/mudlib/
tmi2_fluffos_v2/lib/ftp/
tmi2_fluffos_v2/lib/include/driver/
tmi2_fluffos_v2/lib/log/
tmi2_fluffos_v2/lib/log/driver/
tmi2_fluffos_v2/lib/obj/net/
tmi2_fluffos_v2/lib/obj/shells/
tmi2_fluffos_v2/lib/obj/tools/
tmi2_fluffos_v2/lib/std/adt/
tmi2_fluffos_v2/lib/std/board/
tmi2_fluffos_v2/lib/std/body/
tmi2_fluffos_v2/lib/std/fun/
tmi2_fluffos_v2/lib/std/living/
tmi2_fluffos_v2/lib/std/object/
tmi2_fluffos_v2/lib/std/shop/
tmi2_fluffos_v2/lib/std/socket/
tmi2_fluffos_v2/lib/std/user/
tmi2_fluffos_v2/lib/std/virtual/
tmi2_fluffos_v2/lib/student/
tmi2_fluffos_v2/lib/student/kalypso/
tmi2_fluffos_v2/lib/student/kalypso/armor/
tmi2_fluffos_v2/lib/student/kalypso/rooms/
tmi2_fluffos_v2/lib/student/kalypso/weapons/
tmi2_fluffos_v2/lib/u/l/leto/
tmi2_fluffos_v2/lib/u/l/leto/cmds/
tmi2_fluffos_v2/lib/www/errors/
tmi2_fluffos_v2/lib/www/gateways/
tmi2_fluffos_v2/lib/www/images/
tmi2_fluffos_v2/old/
tmi2_fluffos_v2/win32/
 
//	File	:  /adm/daemons/topuserd.c
//	Creator	:  Watcher@TMI-2  (7/1/93)
//
//	This daemon produces an output of the top ranking users
//	according to their saved skill statistics.
 
//	PLEASE NOTE: Depending on the size of your user database,
//	running this system can cause a large lag for about 10
//	minutes, thus it may be adviseable to schedule the daemon
//	to produce it early in the morning with the event daemon.
 
#include <daemons.h>
#include <mudlib.h>
#include <config.h>
#include <uid.h>

inherit DAEMON;
 
#define RANK_NUM	25	//  Number of ranking positions displayed
#define INCLUDE_WIZS	1	//  Include wizards in the ranking list ?
#define MIN_SCORE	5	//  Any score below this are not ranked
 
#define OUTPUT_FILE	"/log/top_user_list"
 
static int create_shell();
static int create_list();
static int scan_dir(string dir);
static int process_user(string who);

mixed	*list;
 
object	shell;
int	active;

 
void create() {  
	seteuid(getuid(this_object()));
}
 
 
//  This function creates the user shell from which the user's 
//  skill stat system. If it cannot create a shell, it will
//  terminate the top user list production cycle.
 
static int create_shell() {
   string err;
 
   err = catch( shell = new(USER_OB) );

   if(err) {
   write("Error: Could not generate shell for top user list.\n       " + err );
   return 0; }
 
return 1; }
 
 
//  This function begins the production of the top user list.
//  It will block the call if it is not a ROOT or Admin request.
 
int produce_list() {
   object who;
   string *main;
   int loop;

   //	Check permissions of caller ... block if not ROOT or admin
 
   if(geteuid(previous_object()) != ROOT_UID &&
      !adminp(geteuid(previous_object())))  return 0;

   //	Is there already a list being produced? If so return -1
   //	to inform the caller that one is already being produced.
 
   if(active) return -1;
 
   //	Create the user data shell for processing.
 
   if(!create_shell())  return 0;
 
   active = 1;
 
   //	Wipe clean and setup list data array
 
   list = ({ });
 
   //	Note the calling user's object pointer.
 
   if(this_player())  who = this_player();
 
   //	Get an array of all the character data subdirectories
   //	to process the individual user.o files.
 
   main = get_dir( CDATA_DIR + "/" );

   if(!main || !sizeof(main))  return 0;
 
   //	Loop through and check each user subdirectory.

   for(loop=0; loop<sizeof(main); loop++)
	scan_dir(CDATA_DIR + "/" + main[loop] + "/");
 
   //	Okay, done with the shell ... destruct it.

   if(shell)  destruct(shell);
 
   //	Sort the user list into descending ranking order
 
   list = sort_array(list, "rank_list", this_object());
 
   //	Now that the rank array is done ... produce the ranking list.
 
   create_list();
 
   //	Ranking sweep is no longer active ... so remove the flag.
 
   active = 0;
 
   //	Now if the command initiator exists, inform them that the
   //	list creation is done. You may wish to make this into a
   //	shout-like announcement, to inform all mudders of the 
   //	updated user rankings. 
 
   if(who)  tell_object(who, "Top user list creation complete.\n");
 
return 1; }
 
 
//  This function does the actual scanning of the individual 
//  user subdirectories, and processes each of the user.o files
//  for its skill stat value rankings.
 
static int scan_dir(string dir) {
   string *files;
   int loop;
 
   //	Get an array of the individual user.o files.  If none exist
   //	in this subdirectory, go to the next one.
 
   files = get_dir(dir);

   if(!files || !sizeof(files))  return 0;

   //	Loop through each file and pass it to the processing function
   //   The compartmentalization allows admins to easily change the
   //	the specific requirements for ranking which is generally
   //	mudlib dependent and varies. :)
 
   for(loop=0; loop<sizeof(files); loop++)
	process_user(dir + files[loop]);

return 1; }
 
 
//  This function does the actual character processing and stores 
//  the user's skill statistic score (or whatever mudlib dependent
//  statistic system) for ranking.
 
static int process_user(string who) {
   mapping skills;
   string *askills, *junk, name;
   int loop, count;
 
   //	Double check to see if the user file actually exists, and
   //	parse out the user's name from the file name.
 
   if(!who || !file_exists(who) ||
      sscanf(who, "%s" + __SAVE_EXTENSION__, name) != 1)  return 0;
 
   junk = explode(name, "/");
   name = junk[sizeof(junk)-1];
 
   //	Prepare and setup the user shell for data request.
 
   reload_object(shell);

   seteuid(name);
   export_uid(shell);
 
   if(!shell->restore_body())  return 0;
 
   //	Set the daemon's euid back to ROOT
 
   seteuid(ROOT_UID);
 
   //	Get the skill statistics from selected user
 
   skills = (mapping)shell->query_skill_stats();
   
   if(!skills || !mapp(skills))  return 0;
 
   askills = keys(skills);
 
   // 	Loop through the skills and add em up

   for(loop=0; loop<sizeof(askills); loop++)
	count += skills[askills[loop]];
 
   //	If the score is less than the defined MIN_SCORE, don't 
   //	include it in the ranking mapping.
 
   if(count < MIN_SCORE)  return 0;
 
   //	Check to see if wizards are included and if user is a wizard.
 
   if(!INCLUDE_WIZS && shell->query("wizard"))  return 0;
 
   //	Okay, the score qualifies, so add it to the ranking array.
 
   list += ({ ({ name, count }) });
 
return 1; }
 
 
//  This function returns a copy of the ranked list of user scores.
 
mixed *query_list() {  return list;  }
 
 
//  This function is used to sort the ranking array.
 
static int rank_list(mixed *part1, mixed *part2) {
	return (part2[1] - part1[1]);  }
 
 
//  This function produces the top user list output file. You may 
//  wish to customize it to your own mudlib's needs and format.
 
static int create_list() {
   string dump;
   int loop;
 
   //  	Create the list output header information
 
   dump = "\t\t\tTOP RANKING USER LIST\n\t\t\t=====================\n\n" +
	  "   Created: " + ctime(time()) + "\tActive users: " + sizeof(list) +
	  "\n\n";

   //	Loop through the ranking array and tack on top set to list.
 
   for(loop=0; (loop<25 && loop<sizeof(list)); loop++) {
	dump += sprintf("  %-5s%-11s%-10s",
		(loop<9 ? " [" + (loop+1) + "]" : "[" + (loop+1) + "]"),
		capitalize(list[loop][0]), 
		list[loop][1] + " skill points");
	if(loop % 2)  dump += "\n";  else  dump += "\t";
   }
 
   dump += "\n";
 
   //	Okay ... create the actual ranking output file.
 
   if(file_exists(OUTPUT_FILE))  rm(OUTPUT_FILE);
   write_file(OUTPUT_FILE, dump);
 
return 1; }