Author Topic: Census Daemon for DS  (Read 2189 times)

Offline Archaegeo

  • Acquaintance
  • *
  • Posts: 33
    • View Profile
Census Daemon for DS
« on: January 03, 2008, 08:56:54 am »
The following code and code changes add the support of a census daemon. This will let your players know when peak usage is each day (in case they want to play when more or less players are on) and it keeps track of new users and the high usage for the mud. It prints the results in a ascii graphical format with different colors based on the total users each hour or each day.

Syntax:
census - Returns the daily usage by hour
census m - Returns the monthly usage by day
census n - Returns the names of everyone who logged on yesterday.

First is the census daemon.  Put it in /daemon/census_d.c
Code: [Select]
// Census tool.
#include <dirs.h>

int totusers();
int pending() {if(event_pending(this_object())) return 1;return 0;}
int nexttot() {add_event(base_name(this_object()), base_name(this_object()), "totusers", ({}), 300, 1);return 1;}
int lastran, lastday, maxday, halfmax;
int *daily;
int *monthly;
string *names,*newbie, *oldnames, *oldnewbie;
int forever;
void login(string name);
void newuser(string name);

int *query_daily() {return daily;}
int *query_monthly() {return monthly;}
int query_forever() {return forever;}
int query_maxday();
string *query_names() {return oldnames;}
string *query_newbie() {return oldnewbie;}

int query_maxday() {
   int *a,b,c,d;
      a=query_daily();
      for(b=0,c=sizeof(a);b<c;b++) {
      if(a[b]==0) continue;
      if(a[b] > d)
         d=a[b];
      }
      return d;
   }

string query_lastran() {return ("lastran "+ctime(lastran)+"lastday "+ctime(lastday));}

void create() {

  if(!event_pending(this_object())) {
     add_event(base_name(this_object()), base_name(this_object()), "totusers", ({}), 300, 1);
  }
  names=({});
  newbie=({});
  oldnames=({});
  oldnewbie=({});
  daily = allocate(48);
  monthly = allocate(31);
  if(file_exists(DIR_SAVE+"/usage.o"))
    restore_object(DIR_SAVE+"/usage");
  return;
}

void fix_monthly(){
    monthly = allocate(31);
    this_object()->update_usage();
    return;
}


void login(string name) {
   if(!name) return;
   if(member_array(name,names) != -1) return;
   if(!names) names = ({});
   names+=({name});
   return;
}

void newbie(string name) {
   if(!name) return;
   if(member_array(name, newbie) != -1) return;
   if(!newbie) newbie = ({});
   newbie += ({name});
   return;
}

string graph(int a) {
   string sym;
   switch(a) {
      case 20: sym = "%^BOLD%^%^RED%^*";break;
      case 16..19: sym = "%^BOLD%^%^WHITE%^*";break;
      case 12..15: sym = "%^BOLD%^%^YELLOW%^*";break;
      case 8..11: sym = "%^GREEN%^*";break;
      case 4..7: sym = "%^CYAN%^*"; break;
      case 0..3: sym = "%^BLUE%^*";break;
      default: sym =  "%^BOLD%^%^WHITE%^^";break;
   }
   return sym;
}


string display_daily() {

   string disp;
   int i,j;
   disp = "";
   i=20;
   while(i>0) {
      for(j=0;j<24;j++) {
         if(daily[j] > 3*i)
         disp += graph(i);
         else disp += " ";
         if(daily[j+24] > 3*i)
         disp += graph(i);
         else disp += " ";
         disp += " ";
      }
      disp += "\n";
      i--;
   }
   disp += "%^RESET%^";
   for(j=0;j<24;j++) {
      if(j < 10) disp += "0"+j+" ";
      else disp += "" + j + " ";
   }
      disp +="\n";
   return disp;
}

string display_monthly() {

   string disp;
   int i,j;
   disp = "";
   i=20;
   while(i>0) {
      for(j=1;j<31;j++) {
         if(monthly[j] > 3*i)
         disp += graph(i);
         else disp += " ";
         disp += " ";
      }
      disp += "\n";
      i--;
   }
   disp += "%^RESET%^";
   return disp;
}
int query_day() {
   int day;
   sscanf(ctime(time()),"%*s %*s %d %*d:%*d:%*s %*s", day);
   return day;
}

varargs void update_usage(int frc) {
    int hour, min, day;

    sscanf(ctime(time()),"%*s %*s %d %d:%d:%*s %*s", day, hour, min);
    if(min > 30 && min < 60 )  hour = hour+24;
    if(sizeof(users()) > halfmax) daily[hour]=(int)sizeof(users());
    else daily[hour]=halfmax;
    maxday = query_maxday();
    if(maxday > forever) forever = maxday;
    lastran = time();
    halfmax = 0;
    if( (time() > (lastday + 86400)) || frc) {
      monthly[day]=(int)maxday;
      maxday = 0;
      oldnames = names;
      oldnewbie = newbie;
      names = ({});
      newbie = ({});
      lastday = time();
    }
    save_object(DIR_SAVE+"/usage");
    return;
}

int totusers() {
  halfmax = sizeof(users());
  call_out("nexttot",300);
  if(time() > (lastran+1600) ) update_usage();
  return 1;
}

Next is the census command, put it in /cmds/players/census.c
Code: [Select]
/*  /cmds/players/census.c
 *  Made for Dead Souls lib
 *  Created by Archaegeo
 *  Do not remove this header
 */


#define USAGE "/daemon/census_d"


mixed cmd(string arg) {
   int *a, b, c, d, e, f, g;
   string *nm, dys;
   if(arg=="m") {
      message("info","\n"+USAGE->display_monthly(), this_player());
      c=USAGE->query_day();
      dys="";
      for(b=0;b<31;b++) {
         if((b+1)==c) {
            if(b<9) dys +="%^YELLOW%^"+(b+1)+" %^RESET%^";
            else if(b>8 && b<19) dys +="%^YELLOW%^"+(1)+" %^RESET%^";
            else if(b<29) dys +="%^YELLOW%^"+(2)+" %^RESET%^";
            else dys +="%^YELLOW%^"+(3)+" %^RESET%^";
         }
         else {
            if(b<9) dys +="%^RESET%^"+(b+1)+" ";
            else if(b>8 && b<19) dys +="%^RESET%^"+(1)+" ";
            else if(b<29) dys +="%^RESET%^"+(2)+" ";
            else dys +="%^RESET%^"+(3)+" ";
         }
      }
      message("info",dys+"\n"
           "                  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1\n",this_player());
      message("info",
      "                            Daily Highs for Past Month\n", this_player());
   }
   else if(arg == "n") {
      message("info","The following people were online yesterday.",this_player());
      nm=USAGE->query_names();
      write(format_page(nm, 5) +"\n");
   }
   else {
   message("info","\n"+USAGE->display_daily(), this_player());
   message("info",
   "                            Daily Census Chart\n", this_player());
   }
   a=USAGE->query_monthly();
   d=0;
   g=0;
   for(b=0,c=sizeof(a);b<c;b++) {
      if(a[b]==0) continue;
      if(a[b] > d) {
         d=a[b];
         g=b;
      }
      if(a[b] > 0) e++;
      f+=a[b];
   }
   b=USAGE->query_forever();
   write("            New Users Yesterday:     "+sizeof((USAGE->query_newbie())));
   write("            Unique Logins Yesterday: "+sizeof((USAGE->query_names())));
   write("            High in last 24 hours:   "+USAGE->query_maxday());
   write("            Daily Average:           "+(f/e)+"\n            High for Month:          "+d+" players, "+(USAGE->query_day()-g)+" days ago.");
   write("            Highest Recorded Usage:  "+b+"\n");
   return 1;
}

int help() {
message("help",
"This command is used to see mud usage over the last 24 hour "
"period.  You can use this to plan your play time depending "
"if you want to be on at the same time as the most or least "
"folks.  Usage: census\n<census m> will display a monthly chart."
"\n<census n> will display all folks who have logged in during past 24 hours.", this_player());
return 1;
}

Finally you will want to make two changes to /secure/lib/connect.c (WARNING, IF YOU BREAK CONNECT.C YOU WILL NOT BE ABLE TO LOGIN, SO BACK IT UP FIRST).

First in static private void eventEnterGame(), add the following line just before the call_out at the end of the function
Code: [Select]
    "/daemon/census_d"->login(Name);

Next in void eventCompleteChar() add the following line just before the call_out at the end of this function
Code: [Select]
    "/daemon/census_d"->newbie(Name);

All done.