作者itoc (核心動力), 信區: itoc
標題Re: 請問rpg冒險者的排行榜應該怎麼做呢???
時間2004/10/25 Mon 23:55:04 Updated: 2004/10/26
※ 引述《comfan (難過 傷心)》之銘言:
> wd的rpg角色扮演遊戲裡面有一個子選單 [L]istTop 使用者排行榜
> 進入該選單之後 看到的是下列的畫面 不知道在Maple裡面是否也有辦法做出
> 像站上rpg使用者的排行榜類似的功能
在本例中只排行 maxhp 及 str 欄位
想知道有哪些欄位,請參考 rpg.h
在 (A)nnounce 裡面新增資料,路徑為 -rpgmaxhp 及 -rpgstr
: crontab -e 加入這二行
# 每天作二次 RPG 排行
35 3,15 * * * * bin/toprpg > /dev/null 2>&1
: src/util/Makefile
EXE = ... toprpg
: src/util/toprpg.c 新增此程式
/*-------------------------------------------------------*/
/* util/toprpg.c ( NTHU CS MapleBBS Ver 3.00 ) */
/*-------------------------------------------------------*/
/* target : 使用者 RPG 資料統計及排名 */
/* create : 04/10/25 */
/* update : / / */
/* modify : itoc.bbs@bbs.tnfsh.tn.edu.tw */
/*-------------------------------------------------------*/
#include "bbs.h"
// 還要統計別的欄位的話,這裡加一行檔案路徑
// 並在 (A)nnounce 新增「資料」指向這些檔案
#define OUTFILE_RPGMAXHP BBSHOME"/gem/@/@-rpgmaxhp"
#define OUTFILE_RPGSTR BBSHOME"/gem/@/@-rpgstr"
/*-------------------------------------------------------*/
/* author : mat.bbs@fall.twbbs.org */
/* modify : gslin@abpe.org */
/*-------------------------------------------------------*/
#define TOPNUM (36)
#define TOPNUM_HALF (TOPNUM/2)
typedef struct
{
char userid[IDLEN + 1];
char username[UNLEN + 1];
int num;
} DATA;
// 還要統計別的欄位的話,這裡加一個宣告
static DATA topmaxhp[TOPNUM];
static DATA topstr[TOPNUM];
static int
sort_compare(p1, p2)
const void *p1;
const void *p2;
{
DATA *a1, *a2;
a1 = (DATA *) p1;
a2 = (DATA *) p2;
return (a2->num - a1->num);
}
static DATA *
findmin(src)
DATA *src;
{
int i;
DATA *p;
p = src;
for (i = 0; i < TOPNUM; i++)
{
if (src[i].num < p->num)
p = src + i;
}
return p;
}
static void
merge_id_nick(dst, userid, nick)
char *dst;
char *userid;
char *nick;
{
if (*userid)
{
sprintf(dst, "%s (%s)", userid, nick);
if (strlen(dst) > 25)
dst[25] = 0;
}
else
dst[0] = 0;
}
static void
write_data(fpath, title, data)
char *fpath;
char *title;
DATA *data;
{
FILE *fp;
char buf[256];
int i, num1, num2;
if (!(fp = fopen(fpath, "w")))
return;
i = 12 - (strlen(title) >> 1);
sprintf(buf, " \033[1;33m○ ──────────→ \033[41m%%%ds%%s%%%ds"
"\033[40m ←────────── ○\033[m\n\n", i, i);
fprintf(fp, buf, "", title, "");
fprintf(fp,
"\033[1;37m名次 \033[33m代號(暱稱) \033[36m數量\033[m "
"\033[1;37m名次 \033[33m代號(暱稱) \033[36m數量\033[m\n"
"\033[1;32m%s\033[m\n", MSG_SEPERATOR);
for (i = 0; i < TOPNUM_HALF; i++)
{
char buf1[80], buf2[80];
merge_id_nick(buf1, data[i].userid, data[i].username);
merge_id_nick(buf2, data[i + TOPNUM_HALF].userid,
data[i + TOPNUM_HALF].username);
/* itoc.010408: 解決錢太多,畫面爆掉的問題 */
num1 = data[i].num / 1000000;
num2 = data[i + TOPNUM_HALF].num / 1000000;
if (num2) /* 那麼 data[i].num 也必定 > 10^6 */
{
fprintf(fp, "[%2d] %-25s %5dM [%2d] %-25s %5dM\n", i + 1, buf1, num1,
i + 1 + TOPNUM_HALF, buf2, num2);
}
else if (num1)
{
fprintf(fp, "[%2d] %-25s %5dM [%2d] %-25s %6d\n", i + 1, buf1, num1,
i + 1 + TOPNUM_HALF, buf2, data[i + TOPNUM_HALF].num);
}
else
{
fprintf(fp, "[%2d] %-25s %6d [%2d] %-25s %6d\n",
i + 1, buf1, data[i].num,
i + 1 + TOPNUM_HALF, buf2, data[i + TOPNUM_HALF].num);
}
}
fprintf(fp, "\n");
fclose(fp);
}
static inline void
topusr(acct)
ACCT *acct;
{
DATA *p;
int fd;
char fpath[64];
RPG rpg;
sprintf(fpath, "%s/"FN_RPG, acct->userid);
if ((fd = open(fpath, O_RDONLY)) < 0)
return;
read(fd, &rpg, sizeof(RPG));
close(fd);
// 還要統計別的欄位的話,這裡加一個 if (...) {...} 共六行
if ((p = findmin(&topmaxhp))->num < rpg.maxhp)
{
str_ncpy(p->userid, acct->userid, sizeof(p->userid));
str_ncpy(p->username, acct->username, sizeof(p->username));
p->num = rpg.maxhp;
}
if ((p = findmin(&topstr))->num < rpg.str)
{
str_ncpy(p->userid, acct->userid, sizeof(p->userid));
str_ncpy(p->username, acct->username, sizeof(p->username));
p->num = rpg.str;
}
}
/*-------------------------------------------------------*/
/* 主程式 */
/*-------------------------------------------------------*/
int
main()
{
char c;
int year, month, day;
time_t now;
struct tm *ptime;
// 還要統計別的欄位的話,這裡加一行
memset(&topmaxhp, 0, sizeof(topmaxhp));
memset(&topstr, 0, sizeof(topstr));
now = time(NULL);
ptime = localtime(&now);
year = ptime->tm_year;
month = ptime->tm_mon + 1;
day = ptime->tm_mday;
for (c = 'a'; c <= 'z'; c++)
{
char buf[64];
struct dirent *de;
DIR *dirp;
sprintf(buf, BBSHOME "/usr/%c", c);
chdir(buf);
if (!(dirp = opendir(".")))
continue;
while (de = readdir(dirp))
{
ACCT acct;
int fd;
char *fname;
fname = de->d_name;
if (*fname <= ' ' || *fname == '.')
continue;
sprintf(buf, "%s/.ACCT", fname);
if ((fd = open(buf, O_RDONLY)) < 0)
continue;
read(fd, &acct, sizeof(ACCT));
close(fd);
topusr(&acct);
}
closedir(dirp);
}
// 還要統計別的欄位的話,這裡加二行
qsort(topmaxhp, TOPNUM, sizeof(DATA), sort_compare);
write_data(OUTFILE_RPGMAXHP, "RPG血牛排行榜", &topmaxhp);
qsort(topstr, TOPNUM, sizeof(DATA), sort_compare);
write_data(OUTFILE_RPGSTR, "RPG力士排行榜", &topstr);
return 0;
}
--
╭┼ Origin: Maple-itoc˙動力核心 processor.tfcis.org
┼┘ Author: itoc 從 itoc.Dorm11.NCTU.edu.tw 發表