summaryrefslogblamecommitdiffstats
path: root/mbbsd/cal.c
blob: 5c2b7cdc81af7f3637d8f68f8d5bb7cf3d28514f (plain) (tree)
1
2
3
4
5
6
7
8
9
          
                

                     
          


                           
                               
 
                                                              
                                 

                                          




                    
   




                                   
                    
                                     
                    

                                                                    
                

                         


                                                     
            




                                                      




                                
   

                



                           



                             
   




                                                                                    
                    

                                                        
                         


                 

                                      

                                                               
                                                            


             
                                                                        



                                                                           
 
          









                                                                            
                                               
 
                                   
 
                             

                                                                            






                                                 
                            








                                   
                                                                 
                        







                                                              
         
          
                                                   
 



                                                                


                         

                                                  

                                                                      

                                                            




                                                              
     

                                                                             


                         
                                                   
 
                               
 
                     

                                        



                         
                                                      


                                                                
 
                                         

                                         
                    
                         
                      

                          
                        


                             
                                               
                      


                                                                        
                                              

                                               
                      
                                                                            
                                              

                                               
                      
                                                                         
                                              

                        



                



                                                                  
                                        



                                                                  
                          
                          
     

                                                                      

                                
                      


                                                     
                                                 



            






                                                       







                     
   

           



                
          

                






                                          

                   
   



                           
                                                                          
                                      
                      
                 
                            









                                                                     
   


                           
 

                                                                            

                   
                         
                 



                                                                      



             
   



                                     
 
                                            
                                                                   


                  

                                                                   


                                                                     
                  
                      
                 

                
                                             

                                             
                               





                           
    




                                                           
                                                              

                                   
               
                            





                                                                
               
                                                         
                                                  

                    
                                
                                                                   


                                               
                
   
                   
 
                               

                                                             





                                                        

 
   





                                              
                                        

                                                         


                         
                                            
                              


                                                      
                        
                                                              
                                                             
                                      

                                                                      
                                                                  



             
   
               
 
                                
                         
                                 
 
                         
                                                                     
 








                                                                  




                                                           
                                             
                               




                                                                       


                                                  
     




                  
           







                                    
           

                
           

                
           

                


     
/* $Id$ */
#include "bbs.h"

/* 防堵 Multi play */
static int
count_multiplay(int unmode)
{
    register int    i, j;
    register userinfo_t *uentp;

    for (i = j = 0; i < USHM_SIZE; i++) { // XXX linear search
    uentp = &(SHM->uinfo[i]);
    if (uentp->uid == usernum)
        if (uentp->lockmode == unmode)
        j++;
    }
    return j;
}

int
lockutmpmode(int unmode, int state)
{
    int             errorno = 0;

    if (currutmp->lockmode)
    errorno = 1;
    else if (count_multiplay(unmode))
    errorno = 2;

    if (errorno && !(state == LOCK_THIS && errorno == LOCK_MULTI)) {
    clear();
    move(10, 20);
    if (errorno == 1)
        prints("請先離開 %s 才能再 %s ",
           ModeTypeTable[currutmp->lockmode],
           ModeTypeTable[unmode]);
    else
        prints("抱歉! 您已有其他線相同的ID正在%s",
           ModeTypeTable[unmode]);
    pressanykey();
    return errorno;
    }
    setutmpmode(unmode);
    currutmp->lockmode = unmode;
    return 0;
}

int
unlockutmpmode()
{
    currutmp->lockmode = 0;
    return 0;
}

/* 使用錢的函數 */
#define VICE_NEW   "vice.new"

/* Heat:發票 */
int
vice(int money, char *item)
{
    char            buf[128];
    unsigned int    viceserial = (currutmp->lastact % 1000000) * 100 + rand() % 100;
    FILE           *fp;
    demoney(-money);
    snprintf(buf, sizeof(buf), BBSHOME "/home/%c/%s/%s",
         cuser.userid[0], cuser.userid, VICE_NEW);
    fp = fopen(buf, "a");
    if (!fp) {
    return 0;
    }
    fprintf(fp, "%08d\n", viceserial);
    fclose(fp);
    snprintf(buf, sizeof(buf),
         "%s 花了%d$ 編號[%08d]", item, money, viceserial);
    mail_id(cuser.userid, buf, "etc/vice.txt", "Ptt經濟部");
    return 0;
}

#define lockreturn(unmode, state) if(lockutmpmode(unmode, state)) return
#define lockreturn0(unmode, state) if(lockutmpmode(unmode, state)) return 0
#define lockbreak(unmode, state) if(lockutmpmode(unmode, state)) break
#define SONGBOOK  "etc/SONGBOOK"
#define OSONGPATH "etc/SONGO"

static int
osong(char *defaultid)
{
    char            destid[IDLEN + 1], buf[200], genbuf[200], filename[256],
                    say[51];
    char            receiver[45], ano[2];
    FILE           *fp, *fp1;
    //*fp2;
    fileheader_t    mail;
    int             nsongs;

    strlcpy(buf, Cdatedate(&now), sizeof(buf));

    lockreturn0(OSONG, LOCK_MULTI);

    /* Jaky 一人一天點一首 */
    if (!strcmp(buf, Cdatedate(&cuser.lastsong)) && !HAS_PERM(PERM_SYSOP)) {
    move(22, 0);
    outs("你今天已經點過囉,明天再點吧....");
    refresh();
    pressanykey();

    unlockutmpmode();
    return 0;
    }
    if (cuser.money < 200) {
    move(22, 0);
    outs("點歌要200銀唷!....");
    refresh();
    pressanykey();
    unlockutmpmode();
    return 0;
    }
    move(12, 0);
    clrtobot();
    prints("親愛的 %s 歡迎來到歐桑自動點歌系統\n", cuser.userid);
    trans_buffer[0] = 0;
    if (!defaultid) {
    getdata(13, 0, "要點給誰呢:[可直接按 Enter 先選歌]",
        destid, sizeof(destid), DOECHO);
    while (!destid[0]) {
        a_menu("點歌歌本", SONGBOOK, 0);
        clear();
        getdata(13, 0, "要點給誰呢:[可按 Enter 重新選歌]",
            destid, sizeof(destid), DOECHO);
    }
    } else
    strlcpy(destid, defaultid, sizeof(destid));

    /* Heat:點歌者匿名功能 */
    getdata(14, 0, "要匿名嗎?[y/n]:", ano, sizeof(ano), DOECHO);

    if (!destid[0]) {
    unlockutmpmode();
    return 0;
    }
    getdata_str(14, 0, "想要要對他(她)說..:", say,
        sizeof(say), DOECHO, "我愛妳..");
    snprintf(save_title, sizeof(save_title),
         "%s:%s", (ano[0] == 'y') ? "匿名者" : cuser.userid, say);
    getdata_str(16, 0, "寄到誰的信箱(可用E-mail)?",
        receiver, sizeof(receiver), LCECHO, destid);

    if (!trans_buffer[0]) {
    outs("\n接著要選歌囉..進入歌本好好的選一首歌吧..^o^");
    pressanykey();
    a_menu("點歌歌本", SONGBOOK, 0);
    }
    if (!trans_buffer[0] || strstr(trans_buffer, "home") ||
    strstr(trans_buffer, "boards") || !(fp = fopen(trans_buffer, "r"))) {
    unlockutmpmode();
    return 0;
    }
    strlcpy(filename, OSONGPATH, sizeof(filename));

    stampfile(filename, &mail);

    unlink(filename);

    if (!(fp1 = fopen(filename, "w"))) {
    fclose(fp);
    unlockutmpmode();
    return 0;
    }
    strlcpy(mail.owner, "點歌機", sizeof(mail.owner));
    snprintf(mail.title, sizeof(mail.title),
         "◇ %s 點給 %s ",
         (ano[0] == 'y') ? "匿名者" : cuser.userid, destid);

    while (fgets(buf, sizeof(buf), fp)) {
    char           *po;
    if (!strncmp(buf, "標題: ", 6)) {
        clear();
        move(10, 10);
        outs(buf);
        pressanykey();
        fclose(fp);
        fclose(fp1);
        unlockutmpmode();
        return 0;
    }
    while ((po = strstr(buf, "<~Src~>"))) {
        po[0] = 0;
        snprintf(genbuf, sizeof(genbuf),
             "%s%s%s", buf,
             (ano[0] == 'y') ? "匿名者" : cuser.userid, po + 7);
        strlcpy(buf, genbuf, sizeof(buf));
    }
    while ((po = strstr(buf, "<~Des~>"))) {
        po[0] = 0;
        snprintf(genbuf, sizeof(genbuf), "%s%s%s", buf, destid, po + 7);
        strlcpy(buf, genbuf, sizeof(buf));
    }
    while ((po = strstr(buf, "<~Say~>"))) {
        po[0] = 0;
        snprintf(genbuf, sizeof(genbuf), "%s%s%s", buf, say, po + 7);
        strlcpy(buf, genbuf, sizeof(buf));
    }
    fputs(buf, fp1);
    }
    fclose(fp1);
    fclose(fp);

    //do_append(OSONGMAIL "/.DIR", &mail2, sizeof(mail2));

    if (do_append(OSONGPATH "/.DIR", &mail, sizeof(mail)) != -1) {
    cuser.lastsong = now;
    /* Jaky 超過 500 首歌就開始砍 */
    nsongs = get_num_records(OSONGPATH "/.DIR", sizeof(mail));
    if (nsongs > 500) {
        delete_range(OSONGPATH "/.DIR", 1, nsongs - 500);
    }
    /* 把第一首拿掉 */
    vice(200, "點歌");
    }
    snprintf(save_title, sizeof(save_title),
         "%s:%s", (ano[0] == 'y') ? "匿名者" : cuser.userid, say);
    hold_mail(filename, destid);

    if (receiver[0]) {
#ifndef USE_BSMTP
    bbs_sendmail(filename, save_title, receiver);
#else
    bsmtp(filename, save_title, receiver, 0);
#endif
    }
    clear();
    outs(
     "\n\n  恭喜您點歌完成囉..\n"
     "  一小時內動態看板會自動重新更新\n"
     "  大家就可以看到您點的歌囉\n\n"
     "  點歌有任何問題可以到Note板的精華區找答案\n"
     "  也可在Note板精華區看到自己的點歌記錄\n"
     "  有任何保貴的意見也歡迎到Note板留話\n"
     "  讓親切的板主為您服務\n");
    pressanykey();
    sortsong();
    topsong();

    unlockutmpmode();
    return 1;
}

int
ordersong()
{
    osong(NULL);
    return 0;
}

static int
inmailbox(int m)
{
    passwd_query(usernum, &xuser);
    cuser.exmailbox = xuser.exmailbox + m;
    passwd_update(usernum, &cuser);
    return cuser.exmailbox;
}


#if !HAVE_FREECLOAK
/* 花錢選單 */
int
p_cloak()
{
    char            buf[4];
    getdata(b_lines - 1, 0,
        currutmp->invisible ? "確定要現身?[y/N]" : "確定要隱身?[y/N]",
        buf, sizeof(buf), LCECHO);
    if (buf[0] != 'y')
    return 0;
    if (cuser.money >= 19) {
    vice(19, "cloak");
    currutmp->invisible %= 2;
    outs((currutmp->invisible ^= 1) ? MSG_CLOAKED : MSG_UNCLOAK);
    refresh();
    safe_sleep(1);
    }
    return 0;
}
#endif

int
p_from()
{
    char            ans[4];

    getdata(b_lines - 2, 0, "確定要改故鄉?[y/N]", ans, sizeof(ans), LCECHO);
    if (ans[0] != 'y')
    return 0;
    reload_money();
    if (cuser.money < 49)
    return 0;
    if (getdata_buf(b_lines - 1, 0, "請輸入新故鄉:",
            currutmp->from, sizeof(currutmp->from), DOECHO)) {
    vice(49, "home");
    currutmp->from_alias = 0;
    }
    return 0;
}

int
p_exmail()
{
    char            ans[4], buf[200];
    int             n;

    if (cuser.exmailbox >= MAX_EXKEEPMAIL) {
    prints("容量最多增加 %d 封,不能再買了。", MAX_EXKEEPMAIL);
    refresh();
    return 0;
    }
    snprintf(buf, sizeof(buf),
         "您曾增購 %d 封容量,還要再買多少?", cuser.exmailbox);

    getdata_str(b_lines - 2, 0, buf, ans, sizeof(ans), LCECHO, "10");

    n = atoi(ans);
    if (!ans[0] || !n)
    return 0;
    if (n < 0)
    n = 100;
    if (n + cuser.exmailbox > MAX_EXKEEPMAIL)
    n = MAX_EXKEEPMAIL - cuser.exmailbox;
    reload_money();
    if (cuser.money < n * 1000)
    return 0;
    vice(n * 1000, "mail");
    inmailbox(n);
    return 0;
}

void
mail_redenvelop(char *from, char *to, int money, char mode)
{
    char            genbuf[200];
    fileheader_t    fhdr;
    FILE           *fp;
    snprintf(genbuf, sizeof(genbuf), "home/%c/%s", to[0], to);
    stampfile(genbuf, &fhdr);
    if (!(fp = fopen(genbuf, "w")))
    return;
    fprintf(fp, "作者: %s\n"
        "標題: 招財進寶\n"
        "時間: %s\n"
        "\033[1;33m親愛的 %s :\n\n\033[m"
        "\033[1;31m    我包給你一個 %d 元的大紅包喔 ^_^\n\n"
        "    禮輕情意重,請笑納...... ^_^\033[m\n"
        ,from, ctime(&now), to, money);
    fclose(fp);
    snprintf(fhdr.title, sizeof(fhdr.title), "招財進寶");
    strlcpy(fhdr.owner, from, sizeof(fhdr.owner));

    if (mode == 'y')
    vedit(genbuf, NA, NULL);
    snprintf(genbuf, sizeof(genbuf), "home/%c/%s/.DIR", to[0], to);
    append_record(genbuf, &fhdr, sizeof(fhdr));
}

/* 計算贈與稅 */
int
give_tax(int money)
{
    int             i, tax = 0;
    int      tax_bound[] = {1000000, 100000, 10000, 1000, 0};
    double   tax_rate[] = {0.4, 0.3, 0.2, 0.1, 0.08};
    for (i = 0; i <= 4; i++)
    if (money > tax_bound[i]) {
        tax += (money - tax_bound[i]) * tax_rate[i];
        money -= (money - tax_bound[i]);
    }
    return (tax <= 0) ? 1 : tax;
}

int
p_give()
{
    int             money, tax;
    char            id[IDLEN + 1], genbuf[90];

    move(1, 0);
    usercomplete("這位幸運兒的id:", id);
    if (!id[0] || !strcmp(cuser.userid, id) ||
    !getdata(2, 0, "要給多少錢:", genbuf, 7, LCECHO))
    return 0;
    money = atoi(genbuf);
    reload_money();
    if (money > 0 && cuser.money >= money) {
    tax = give_tax(money);
    if (money - tax <= 0)
        return 0;       /* 繳完稅就沒錢給了 */
    deumoney(searchuser(id), money - tax);
    demoney(-money);
    snprintf(genbuf, sizeof(genbuf), "%s\t給%s\t%d\t%s\n",
         cuser.userid, id, money - tax, ctime(&now));
    log_file(FN_MONEY, genbuf, 1);
    genbuf[0] = 'n';
    getdata(3, 0, "要自行書寫紅包袋嗎?[y/N]", genbuf, 2, LCECHO);
    mail_redenvelop(cuser.userid, id, money - tax, genbuf[0]);
    }
    return 0;
}

int
p_sysinfo(void)
{
    char            *cpuloadstr;
    int             load;
    extern char    *compile_time;

    load = cpuload(NULL);
    cpuloadstr = (load < 5 ? "良好" : (load < 20 ? "尚可" : "過重"));

    clear();
    showtitle("系統資訊", BBSNAME);
    move(2, 0);
    prints("您現在位於 " TITLE_COLOR BBSNAME "\033[m (" MYIP ")\n"
       "系統負載情況: %s\n"
       "線上服務人數: %d/%d\n"
       "編譯時間:     %s\n"
       "起始時間:     %s\n",
       cpuloadstr, SHM->UTMPnumber,
#ifdef DYMAX_ACTIVE
       GLOBALVAR[9] > 1000 ? GLOBALVAR[9] : MAX_ACTIVE,
#else
       MAX_ACTIVE,
#endif
       compile_time, ctime(&start_time));
    if (HAS_PERM(PERM_SYSOP)) {
    struct rusage ru;
    getrusage(RUSAGE_SELF, &ru);
    prints("記憶體用量: sbrk: %d KB, idrss: %d KB, isrss: %d KB\n",
           ((int)sbrk(0) - 0x8048000) / 1024,
           (int)ru.ru_idrss, (int)ru.ru_isrss);
#ifdef CRITICAL_MEMORY
    prints("目前在 CRITICAL_MEMORY 模式下\n");
#endif
    }
    pressanykey();
    return 0;
}

/* 小計算機 */
static void
ccount(float *a, float b, int cmode)
{
    switch (cmode) {
    case 0:
    case 1:
    case 2:
    *a += b;
    break;
    case 3:
    *a -= b;
    break;
    case 4:
    *a *= b;
    break;
    case 5:
    *a /= b;
    break;
    }
}