回精華區
作者simple.bbs@bbs.wfc.edu.tw (養兵千日 用在一時) 看板: plan
標題[功能]樂透彩-大樂透(修改版)
時間卡布奇諾 (2004/10/27 Wed 00:39:26) Updated: 2006/01/24
: crontab -e 加入二行

# 每星期樂透開獎一次
50 4 * * 6 bin/lottery-open > /dev/null 2>&1

: src/util/Makefile

EXE =   ... lottery-open

: util/lottery-open.c 新增此程式

/*-------------------------------------------------------*/
/* util/lottery-open.c  ( YZU WindTopBBS Ver 3.00 )      */
/*-------------------------------------------------------*/
/* target : 彩券遊戲 -- 開獎程式                         */
/* create : 02/01/12                                     */
/* update : 03/05/26                                     */
/* author : verit.bbs@bbs.yzu.edu.tw                     */
/* modify : itoc.bbs@bbs.tnfsh.tn.edu.tw                 */
/* modify : simple.bbs@bbs.wfc.edu.tw                    */
/*-------------------------------------------------------*/


#include "bbs.h"


#define OUTFILE_LOTTERY   "run/lottery.result"


/* lottery_num[0~5] 是一般號碼;lottery_num[6] 是特別號 */
static int lottery_num[6];

/* lottery_win[0~6] 依序是中各獎項的注數
   0:普獎 1:陸獎 2:伍獎 3:肆獎 4:參獎 5:貳獎 6:頭獎 */
static int lottery_win[7];

static double totalmoney;     /* 總押金 */

/* eachmoney[0~6] 依序是各獎項的獎金
   0:普獎 1:陸獎 2:伍獎 3:肆獎 4:參獎 5:貳獎 6:頭獎 */
static int eachmoney[7];

static FILE *flog;


/*-------------------------------------------------------*/
/* 發獎金                                                */
/*-------------------------------------------------------*/


static void
add_money(log)
  BUY_LOTTERY *log;
{
  char fpath[64];
  PAYCHECK paycheck;
  static char name[7][3] = {"普", "陸", "伍", "肆", "參", "貳", "頭"};

  memset(&paycheck, 0, sizeof(PAYCHECK));
  time(&paycheck.tissue);
  paycheck.money = eachmoney[log->prize];
  sprintf(paycheck.reason, "大樂透%s獎獎金", name[log->prize]);

  usr_fpath(fpath, log->userid, FN_PAYCHECK);
  rec_add(fpath, &paycheck, sizeof(PAYCHECK));

  fprintf(flog, "  %-13s彩券號碼為 %02d %02d %02d %02d %02d %02d,"
    "中了%s獎 %d 元\n",
    log->userid, log->num[0], log->num[1], log->num[2],
    log->num[3], log->num[4], log->num[5], name[log->prize], paycheck.money);
}


static void
mail_lottery(log)       /* itoc.011115: 寄檔案給 userid */
  BUY_LOTTERY *log;
{
  int i;
  char folder[64];
  HDR hdr;
  static char userid[IDLEN + 1];
  static char fpath[64];
  static FILE *fp;

  /* log[] 要依 log->userid 來排序 */
  /* 同一位使用者可能有多張彩券中獎,在同一封信裡面會把所有明細都寫出來 */

  if (strcmp(userid, log->userid))   /* 新的 userid */
  {
    /* 將前一中獎人的信寄出 */
    if (fp)
    {
      fclose(fp);

      usr_fpath(folder, userid, FN_DIR);
      hdr_stamp(folder, HDR_LINK, &hdr, fpath);
      strcpy(hdr.owner, STR_SYSOP);
      strcpy(hdr.nick, SYSOPNICK);
      strcpy(hdr.title, "彩券發錢");
      rec_add(folder, &hdr, sizeof(HDR));

      unlink(fpath);
    }

    if (!log->userid[0])   /* 已寄出最後一位中獎人通知信 */
      return;

    /* 開始準備新中獎人的信 */
    strcpy(userid, log->userid);

    sprintf(fpath, "tmp/lottery.%d", userid);
    if (fp = fopen(fpath, "w"))
    {
      /* 文章檔頭 */
      fprintf(fp, "%s %s (%s)\n", STR_AUTHOR1, STR_SYSOP, SYSOPNICK);
      fprintf(fp, "標題: 彩券發錢\n時間: %s\n\n", Now());

      /* 文章內容 */
      fprintf(fp, "     本期樂透中獎號碼為:\n\n          ");
      for (i = 0; i < 6; i++)
        fprintf(fp, "%02d  ", lottery_num[i]);
      fprintf(fp, "\n\n     本期樂透特別號碼為:%\n\n          ");
      fprintf(fp, "%02d\n\n", lottery_num[6]);
    }
  }

  fprintf(fp, "     您所購買的號碼為:\n\n          ");
  for (i = 0; i < 6; i++)
    fprintf(fp, "%02d  ", log->num[i]);

  fprintf(fp, "恭喜您贏得 %d 元,詳細中獎記錄請參考 %s 板\n",
    eachmoney[log->prize], BN_RECORD);
}


/*-------------------------------------------------------*/
/* 開獎記錄                                              */
/*-------------------------------------------------------*/


static void
add_post(brdname, fpath, title)           /* 發文到看板 */
  char *brdname;        /* 欲 post 的看板 */
  char *fpath;          /* 檔案路徑 */
  char *title;          /* 文章標題 */
{
  HDR hdr;
  char folder[64];

  brd_fpath(folder, brdname, FN_DIR);
  hdr_stamp(folder, HDR_LINK | 'A', &hdr, fpath);
  strcpy(hdr.owner, STR_SYSOP);
  strcpy(hdr.nick, SYSOPNICK);
  strcpy(hdr.title, title);
  rec_add(folder, &hdr, sizeof(HDR));
}


/*-------------------------------------------------------*/
/* 對獎主程式                                            */
/*-------------------------------------------------------*/


static void
generate_number()    /* 產生中獎結果 */
{
  int i, j, num;

  srand(time(NULL));

  for (i = 0; i < 7; i++)
  {
rand_num:                       /* random 出一個和之前都不同的數字 */
    num = rand() % 49 + 1;
    for (j = 0; j < i; j++)
    {
      if (num == lottery_num[j])/* 這個數字以前 random 過了 */
        goto rand_num;
    }
    lottery_num[i] = num;
  }

  fprintf(flog, "     本期樂透中獎號碼為:\n\n          ");
  for (i = 0; i < 6; i++)
    fprintf(flog, "%02d  ", lottery_num[i]);
  fprintf(flog, "\n\n     本期樂透特別號碼為:%\n\n          ");
  fprintf(flog, "%02d\n\n", lottery_num[6]);

  /* 中獎注數歸零 */
  for (i = 0; i < 7; i++)
    lottery_win[i] = 0;
}


static int  /* -1:摃龜 0:普獎 1:陸獎 2:伍獎 3:肆獎 4:參獎 5:貳獎 6:頭獎 */
check_prize(log)
  BUY_LOTTERY *log;
{
  int i, j;
  int guessed;        /* 中了幾個號碼 */
  int spec;           /* 1: 中了特別號碼 */
  int prize;

  guessed = 0;
  for (i = 0; i < 6; i++)
  {
    for (j = 0; j < 6; j++)
    {
      if (log->num[i] == lottery_num[j])
      {
        guessed++;
        break;
      }
    }
  }

  spec = 0;
  for (i = 0; i < 6; i++)
  {
    if (log->num[i] == lottery_num[6])
    {
      spec = 1;
      break;
    }
  }

  /* 頭獎 與當期六個中獎號碼完全相同者〈順序不限〉
     貳獎 對中當期中獎號碼之其中任五碼+特別號
     參獎 對中當期中獎號碼之其中任五碼
     肆獎 對中當期中獎號碼之其中任四碼+特別號
     伍獎 對中當期中獎號碼之其中任四碼
     陸獎 對中當期中獎號碼之其中任三碼+特別號
     普獎 對中當期中獎號碼之其中任三碼
   */

  if (guessed <= 2)
  {
    prize = -1;
  }
  else if (guessed == 3)
  {
    prize = (!spec) ? 0 : 1;
  }
  else if (guessed == 4)
  {
    prize = (!spec) ? 2 : 3;
  }
  else if (guessed == 5)
  {
    prize = (!spec) ? 4 : 5;
  }
  else if (guessed == 6)
  {
    prize = 6;
  }

  if (prize >= 0)
    lottery_win[prize]++;
  return prize;
}


static void
check_money()         /* 計算各獎項獎金 */
{
  int i;
  double keepmoney;
  int rate[7] = {0, 0, 20, 5, 10, 9, 56};

  /* 頭獎 共 lottery_win[6] 注,佔剩餘獎金56%
     貳獎 共 lottery_win[5] 注,佔剩餘獎金9%
     參獎 共 lottery_win[4] 注,佔剩餘獎金10%
     肆獎 共 lottery_win[3] 注,佔剩餘獎金5%
     伍獎 共 lottery_win[2] 注,佔剩餘獎金20%
     陸獎 共 lottery_win[1] 注,每注獎金為20000銀幣
     普獎 共 lottery_win[0] 注,每注獎金為8000銀幣
   */

  /* 取出上期未發出的獎金 */
  keepmoney = 0;
  rec_get(LAST_KEEP_MONEY, &keepmoney, sizeof(keepmoney), 0);
  totalmoney += keepmoney;

  /* 先扣除普獎、陸獎的獎金 */
  totalmoney -= lottery_win[0] * 8000 + lottery_win[1] * 20000;
  if (totalmoney < 0)
    totalmoney = 0;

  for (i = 2; i < 7; i++)  /* 除普獎、陸獎以外 */
  {
    if (lottery_win[i])
      eachmoney[i] = totalmoney / 100 / lottery_win[i] * rate[i];
    else
      keepmoney += totalmoney / 100 * rate[i];
  }
  eachmoney[1] = 20000;
  eachmoney[0] = 8000;

  /* 將未發出的獎金保留至下期 */
  rec_put(LAST_KEEP_MONEY, &keepmoney, sizeof(keepmoney), 0, NULL);

  fprintf(flog, "各獎項的獎金依序是:");
  for (i = 0; i < 7; i++)
    fprintf(flog, "%d ", eachmoney[i]);
  fprintf(flog, "\n\n");
}


static int
lottery_cmp(a, b)
  BUY_LOTTERY *a, *b;
{
  int ap, bp;

  ap = a->prize;
  bp = b->prize;

  if (ap * bp < 0)   /* 一人有中獎,另一人沒中獎 */
    return ap - bp;  /* 沒中獎的放前面 */

  /* 二人都有中獎或都沒中獎,依 id 排序 */
  return strcmp(a->userid, b->userid);
}


static void
lottery_open()
{
  int fsize;
  BUY_LOTTERY *data, *head, *tail;

  if (data = (BUY_LOTTERY *) f_img(FN_RUN_LOTTERY, &fsize))
  {
    unlink(FN_RUN_LOTTERY);

    fsize /= sizeof(BUY_LOTTERY);
    totalmoney = fsize * 1000;

    /* 第一圈對獎 */
    head = data;
    tail = data + fsize;
    do
    {
      /* 開始對獎,統計中獎注數 */
      head->prize = check_prize(head);
    } while (++head < tail);

    /* 計算各獎項獎金 */
    check_money();

    /* 將 data 依 userid 排序 */
    qsort(data, fsize * sizeof(BUY_LOTTERY), sizeof(BUY_LOTTERY), lottery_cmp);

    /* 第二圈發獎金 */
    head = data;
    do
    {
      if (head->prize >= 0)
      {
        add_money(head);
        mail_lottery(head);
      }
    } while (++head < tail);

    /* 寄出最後一個中獎人通知信 */
    data->userid[0] = '\0';
    mail_lottery(data);

    free(data);
  }
}


int
main()
{
  chdir(BBSHOME);

  if (flog = fopen(OUTFILE_LOTTERY, "w"))
  {
    generate_number();
    lottery_open();
    fclose(flog);
    add_post(BN_RECORD, OUTFILE_LOTTERY, "大樂透開獎記錄");
  }

  exit(0);
}


--
※ Origin: 吳鳳技術學院電算中心 卡布奇諾 <bbs.wfc.edu.tw>
◆ From: bbs.wfc.edu.tw
精華選讀←離開[主題上]主題下(k)上篇(j)下篇S/a搜尋 G串列 TAB精華 ↑↓捲 Pg/Space翻