回精華區
作者verit.bbs@bbs.yzu.edu.tw (BBS 站長大會), 看板: installbbs
標題[WindTop]心理測驗程式
時間元智大學風之塔 (Tue Sep 9 20:00:52 2003) Updated: 2003/09/10
: menu.c 適當的選單加入

  "bin/mind.so:main_mind", 0, - M_XMODE,
  "Mind       ♂ 心理測驗 ♀",

: run/mind

  建立此目錄

: run/mind/help 新增此檔案

心理測驗投稿格式有三種 :

1. 一般題目 , 接下一題

    [Q]題目
    [A-1]說明1
    [A-7]說明2

    上面第二行代表 , 第一個答案接第二題
    上面第三行代表 , 第二個檔案接第八題

2. 題目接結果

    [Q]題目
    [A-R-1]說明一
    [A-0]說明二

    上面第二行代表 , 第一個答案接第一個結果
    上面第二行代表 , 第二個答案接第一題

    ps) 接題目的話 , 題號記得減一
        接結果的話 , 編號不用減一

3. 結果

    [R]結果標題
    結果內容

    ps) 結果內容只能一行 :p


可以參考下面的範例 :)
===
[Q]直接了當的說,妳是?
[A-1]極重視外表
[A-2]較重視內在

[Q]對於喜歡的人態度很積極
[A-3]YES
[A-5]NO

[Q]常常夢見喜歡的人
[A-6]YES
[A-4]NO

[Q]在街上巧遇自己暗戀的人,妳會
[A-5]邀請他一塊去喝茶
[A-14]只打招呼

[Q]上課(上班)時,常盯著喜歡的人看。
[A-7]YES
[A-1]NO

[Q]對於喜歡的人:
[A-8]先從朋友做起
[A=16]毫不猶地向他告白,決心一定要和他成為戀人。

[Q]戀人比朋友還重要。
[A-10]YES
[A-4]NO

[Q]不懂得適時地表白,即使是無聊的玩笑,也會使妳臉紅。
[A-11]YES
[A-5]NO

[Q]曾經去過喜歡的人家裡。
[A-12]YES
[A-9]NO

[Q]暗戀之人曾主動與你說話。
[A-18]YES
[A-16]NO

[Q]有很多異性朋友。
[A-7]YES
[A-11]NO

[Q]暗戀的人如果搬了家:
[A-8]馬上尋找別的戀愛對象
[A-12]即使分隔兩地還是一心一意喜歡他

[Q]討厭整天在一起的戀愛,重視擁有個人的時間及空間。
[A-20]YES
[A-9]NO

[Q]喜歡照顧自己暗戀的人。
[A-R-3]YES
[A-R-1]NO

[Q]情人節時不敢親手送給他巧克力。
[A-13]YES
[A-16]NO

[Q]當面向他告白,會感到十分難為情。
[A-R-1]YES
[A-R-2]NO

[Q]不喜歡講長時間的電話。
[A-13]YES
[A-14]NO

[Q]若受到壓力,便會傾出全力反抗。
[A-R-4]YES
[A-R-3]NO

[Q]有過(暗戀)及被告白的經驗。
[A-13]YES
[A-20]NO

[Q]你覺得那一種較好:
[A-R-2]被告白
[A-R-4]向人告白

[Q]就算有人向妳告白,如果不是自己喜歡的類型,便不會與他交往。
[A-17]YES
[A-19]NO

[R][郭靖]類型的人
對於喜歡照顧別人的好大哥形象,把離家而自己闖江湖的黃蓉當做 (無斷行按下行)
(可信賴的人)並和她彼此依賴相互照顧,是個溫和體貼的對象。很 (無斷行按下行)
容易與人接近這種親力正是妳(你)的魅力所在。

[R][郭芙]類型的人
在喜歡的人面前總是無法表達出自己的本意,事後才自我抱怨不已,(無斷行按下行)
不過很懂得撒嬌、耍賴、也很懂得主動討人喜歡、與人聊天,因此 (無斷行按下行)
異性朋友不少,只要能從失敗中累積經驗,極有可能成為大受歡迎的(無斷行按下行)
人。

[R][小龍女]類型的人
內熱外冷,清純善良型的人:其實是屬於較自閉、內向的性格,但對 (無斷行按下行)
於自己喜歡的事、物會全心去關注,雖不用言語直接說明,但會以  (無斷行按下行)
行動不經意地流露愛意,在內心的澎湃熱情之中還是帶點沉穩,和  (無斷行按下行)
這類型的在一起應該會感到安心自在。

[R][楊過]類型的人
因為個性執著,對自己心儀的人會努力的守候在她(他)身旁,有時  (無斷行按下行)
可能會不敢明明白白作出愛的告白,但專情的她(他),若遇到戀人  (無斷行按下行)
的背叛,他必會使盡全力去挽回,是受壓力愈大反彈愈大,永遠不服 (無斷行按下行)
輸的人。

: src/so/Makeifle

SO =    .... mind.so

: src/so/mind.c 新增此程式

/*-------------------------------------------------------*/
/* mind.c        ( YZU_CSE WindTop BBS )                 */
/*-------------------------------------------------------*/
/* author : verit.bbs@bbs.yzu.edu.tw                     */
/* target : 心理測驗                                     */
/* create : 03/08/05                                     */
/* update :   /  /                                       */
/*-------------------------------------------------------*/


#include "bbs.h"


#define MAX_DESC_LENGTH      256        /* 敘述的長度 */
#define MAX_TEXT_LENGTH      512        /* 內文的長度 */

#define MAX_MIND_QUESTION    50         /* 最多題目個數 */
#define MAX_MIND_ANSWER      5          /* 每題最多答案數 */
#define MAX_MIND_RESULT      10         /* 最多結果數 */

#define LEN                  50         /* 一行最多顯示幾個字 */
#define MIND_XPOS            5          /* 預設輸出 x 座標 */
#define MIND_YPOS            10         /* 預設輸出 y 座標 */

#define DEF_PATH        "run/mind/"

static int x, y;

typedef struct
{
  char question[MAX_DESC_LENGTH];
  char ans_desc[MAX_MIND_ANSWER][MAX_DESC_LENGTH];
  int ans_next[MAX_MIND_ANSWER];
  int ans;
}      QUESTION;

typedef struct
{
  char title[MAX_DESC_LENGTH];
  char desc[MAX_TEXT_LENGTH];
}      RESULT;

typedef struct
{
  QUESTION question[MAX_MIND_QUESTION];
  RESULT result[MAX_MIND_RESULT];
  int qcount;
  int rcount;
}      MIND;


static int
read_file(fpath, m)
  char *fpath;
  MIND *m;
{
  FILE *fp;
  int num;
  int ans;
  int result;
  char buf[MAX_TEXT_LENGTH];
  char *tmp, *tmp2;
  if (!(fp = fopen(fpath, "r")))
    return -1;

  num = -1;
  result = 0;
  while (fgets(buf, sizeof(buf), fp))
  {
    if (buf[1] == 'Q')
    {
      if (num >= 0)
        m->question[num].ans = ans;
      if (++num >= MAX_MIND_QUESTION)
      {
        fclose(fp);
        return -2;
      }
      strcpy(m->question[num].question, buf + 3);
      if (tmp2 = strchr(m->question[num].question, '\n'))
        *tmp2 = 0;
      ans = 0;
    }
    else if (buf[1] == 'A')
    {
      tmp = strchr(buf, ']');
      *tmp = 0;

      if (buf[3] == 'R')
        m->question[num].ans_next[ans] = atoi(buf + 4);
      else
        m->question[num].ans_next[ans] = atoi(buf + 3);

      strcpy(m->question[num].ans_desc[ans], tmp + 1);
      if (tmp2 = strchr(m->question[num].ans_desc[ans], '\n'))
        *tmp2 = 0;
      ++ans;
    }
    else if (buf[1] == 'R')
    {
      m->question[num].ans = ans;

      strcpy(m->result[result].title, buf + 3);
      if (tmp2 = strchr(m->result[result].title, '\n'))
        *tmp2 = 0;

      if (fgets(buf, sizeof(buf), fp))
        strcpy(m->result[result].desc, buf);
      else
        memset(m->result[result].desc, 0, MAX_TEXT_LENGTH);

      if (tmp2 = strchr(m->result[result].desc, '\n'))
        *tmp2 = 0;
      if (++result >= MAX_MIND_RESULT)
        break;
    }
  }

  m->qcount = num + 1;
  m->rcount = result;

  fclose(fp);

  return 1;
}


static int
print_quiz(src)
  char *src;
{
  int wstate = 0;
  int word = 0;
  char *str = src;
  char buf[128], *tmp;
  char form[128];
  int pos = LEN + 1;
  int height = 0;

  sprintf(form, "%%-%ds", pos + 1);

  while (*str)
  {
    height++;
    tmp = str;
    move(x++, y);
    outs(" \033[0;37m▏\033[1;37m");

    wstate = 0;
    word = 0;
    for (; word < pos && *str; str++)
    {
      wstate = (*str < 0) ? ((wstate == 1) ? 0 : 1) : 0;
      word++;
    }

    if (!(*str < 0 && wstate == 0))
      str++;

    memset(buf, 0, sizeof(buf));
    strncpy(buf, tmp, str - tmp);
    prints(form, buf);
    if (strlen(buf) == pos)
      outs("\033[0;47;30m▉\033[40;30;1m▉\033[m ");
    else
      outs("\033[0;47;30m▉\033[40;30;1m▉\033[m ");
  }

  return height;
}


static int
draw_item(src, pos, mode)
  char *src;
  int pos;
  int mode;
{
  char buf[128];

  sprintf(buf, "%%d;37m %s %%-%ds", (mode) ? "◆" : "  ", LEN - 2);
  move(MIND_XPOS + pos + 2, MIND_YPOS);

  outs(" \033[0;37m▏\033[1;");
  prints(buf, (mode) ? 41 : 40, src);
  outs("\033[0;47;30m▉\033[40;30;1m▉\033[m ");
}


static int
draw_menu(question, no)
  QUESTION *question;
  int no;
{
  int i, cur;
  int c;
  int h;

  x = MIND_XPOS;
  y = MIND_YPOS;

  move(x++, y);
  outs(" \033[0;40;37mˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍ\033[m");
  move(x++, y);
  prints(" \033[0;37;44m▏\033[1m第 %02d 題%-43s \033[0;47;34m▉\033[m", no + 1, " ");
  move(x++, y);
  prints(" \033[0;37m▏\033[1m%-51s \033[0;47;30m▉\033[40;30;1m▉\033[m", " ");
  cur = 0;
  h = print_quiz(question[no].question) + 2;

  move(x++, y);
  prints(" \033[0;37m▏\033[1m%-51s \033[0;47;30m▉\033[40;30;1m▉\033[m", " ");

  for (i = 0; i < question[no].ans; ++i, ++x)
    draw_item(question[no].ans_desc[i], i + h, (i == cur) ? 1 : 0);

  move(x++, y);
  prints(" \033[0;37m▏\033[1m%-51s \033[0;47;30m▉\033[40;30;1m▉\033[m", " ");
  move(x++, y);
  outs(" \033[0;47;30m▇\033[30;1m▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇\033[40;30;1m▉\033[m");

  outz("\033[1;37;42m 【操作說明】q)離開 Enter)作答                                                \033[m");

  while (c = vkey())
  {
    draw_item(question[no].ans_desc[cur], cur + h, 0);
    switch (c)
    {
    case KEY_UP:
      cur = (cur == 0) ? question[no].ans - 1 : cur - 1;
      break;
    case KEY_DOWN:
      cur = (cur + 1) % question[no].ans;
      break;
    case '\n':
    case ' ':
      return cur;
    case 'q':
      vmsg(NULL);
      return -892226;
    }
    draw_item(question[no].ans_desc[cur], cur + h, 1);
  }

  return 0;
}


static void
do_test(fpath, title)
  char *fpath;
  char *title;
{
  int no, ans;
  MIND m;

  if (read_file(fpath, &m) <= 0)
    return;

  no = 0;
  while (1)
  {
    vs_bar("心理測驗");
    move(3, MIND_YPOS);
    prints("目前測驗的題目是 : %s", title);
    ans = draw_menu(m.question, no);
    if (ans == -892226)
      return;
    no = m.question[no].ans_next[ans];
    if (no < 0)
    {
      x = MIND_XPOS;
      y = MIND_YPOS;
      no = -no;
      --no;

      vs_bar("心理測驗");
      move(x++, y);
      prints(" \033[0;40;37mˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍˍ\033[m   ");
      move(x++, y);
      prints(" \033[0;37;42m▏\033[1m結果:%-45s \033[0;47;32m▉\033[m   ", m.result[no].title);
      move(x++, y);
      prints(" \033[0;37m▏\033[1m%-51s \033[0;47;30m▉\033[40;30;1m▉\033[m ", " ");

      print_quiz(m.result[no].desc);

      move(x++, y);
      prints(" \033[0;37m▏\033[1m%-51s \033[0;47;30m▉\033[40;30;1m▉\033[m ", " ");
      move(x++, y);
      prints(" \033[0;47;30m▇\033[30;1m▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇\033[40;30;1m▉\033[m ");
      vmsg(NULL);
      break;
    }
  }
}


/*-------------------------------------------------------*/
/* xover 選單                                            */
/*-------------------------------------------------------*/

extern XZ xz[];
extern char xo_pool[];

static int mind_add();

typedef struct
{
  char title[56];
  char fpath[8];
}      XMIND;


static void
mind_item(num, mind)
  int num;
  XMIND *mind;
{
  prints("%6d     %-64s\n", num, mind->title);
}


static int
mind_body(xo)
  XO *xo;
{
  XMIND *mind;
  int num, max, tail;

  move(3, 0);
  clrtobot();
  max = xo->max;
  if (max <= 0)
  {
    if (vans("要新增資料嗎(Y/N)?[N] ") == 'y')
      return mind_add(xo);
    return XO_QUIT;
  }

  mind = (XMIND *) xo_pool;
  num = xo->top;
  tail = num + XO_TALL;
  if (max > tail)
    max = tail;

  do
  {
    mind_item(++num, mind++);
  } while (num < max);

  return XO_FOOT;
}


static int
mind_head(xo)
  XO *xo;
{
  vs_head("心理測驗", str_site);
  outs("[←]離開 [Enter]測驗 [q]瀏覽 [^P]新增 [c]修改 [d]刪除 [h]投稿格式\n"
    "\033[30;47m  編號     測  驗  名  稱                                                     \033[m");
  return mind_body(xo);
}


static int
mind_load(xo)
  XO *xo;
{
  xo_load(xo, sizeof(XMIND));
  return mind_body(xo);
}


static int
mind_init(xo)
  XO *xo;
{
  xo_load(xo, sizeof(XMIND));
  return mind_head(xo);
}


static int      /* 1:新增/修改  0:取消 */
mind_edit(mind, echo)
  XMIND *mind;
  int echo;
{
  char fpath[64];

  if (echo == DOECHO)
  {
    time_t t = time(0);
    memset(mind, 0, sizeof(XMIND));
    archiv32(t, mind->fpath);
  }

  if (vget(b_lines, 0, "名稱:", mind->title, sizeof(mind->title), echo))
  {
    sprintf(fpath, "%s%s", DEF_PATH, mind->fpath);
    if (!vedit(fpath, 0))
      return 1;
    vmsg(echo == DOECHO ? "取消新增" : "取消修改");
  }

  return 0;
}


static int
mind_add(xo)
  XO *xo;
{
  XMIND mind;

  if (!HAS_PERM(PERM_SYSOP))
    return XO_NONE;

  if (mind_edit(&mind, DOECHO))
  {
    rec_add(xo->dir, &mind, sizeof(XMIND));
    xo->pos = XO_TAIL;
    xo_load(xo, sizeof(XMIND));
  }
  return mind_head(xo);
}


static int
mind_delete(xo)
  XO *xo;
{
  if (!HAS_PERM(PERM_SYSOP))
    return XO_NONE;

  if (vans(msg_del_ny) == 'y')
  {
    if (!rec_del(xo->dir, sizeof(XMIND), xo->pos, NULL))
      return mind_load(xo);
  }
  return XO_FOOT;
}


static int
mind_change(xo)
  XO *xo;
{
  XMIND *mind, mate;
  int pos, cur;

  if (!HAS_PERM(PERM_SYSOP))
    return XO_NONE;

  pos = xo->pos;
  cur = pos - xo->top;
  mind = (XMIND *) xo_pool + cur;

  mate = *mind;
  mind_edit(mind, GCARRY);
  if (memcmp(mind, &mate, sizeof(XMIND)))
  {
    rec_put(xo->dir, mind, sizeof(XMIND), pos, NULL);
    move(3 + cur, 0);
    mind_item(++pos, mind);
  }

  return mind_init(xo);
}


static int
mind_browser(xo)
  XO *xo;
{
  XMIND *mind;
  int pos, cur;
  char fpath[64];

  if (!HAS_PERM(PERM_SYSOP))
    return XO_NONE;

  pos = xo->pos;
  cur = pos - xo->top;
  mind = (XMIND *) xo_pool + cur;
  sprintf(fpath, "%s%s", DEF_PATH, mind->fpath);
  more(fpath, NULL);
  return mind_init(xo);
}


static int
mind_do(xo)
  XO *xo;
{
  XMIND *mind;
  int pos, cur;
  char fpath[64];

  pos = xo->pos;
  cur = pos - xo->top;
  mind = (XMIND *) xo_pool + cur;
  sprintf(fpath, "%s%s", DEF_PATH, mind->fpath);
  do_test(fpath, mind->title);

  return mind_init(xo);
}


static int
mind_help(xo)
  XO *xo;
{
  char fpath[64];

  sprintf(fpath, "%shelp", DEF_PATH);
  more(fpath, NULL);
  return mind_head(xo);
}


static KeyFunc mind_cb[] =
{
  XO_INIT, mind_init,
  XO_LOAD, mind_load,
  XO_HEAD, mind_head,
  XO_BODY, mind_body,

  Ctrl('P'), mind_add,
  'r', mind_do,
  'q', mind_browser,
  'c', mind_change,
  'd', mind_delete,
  'h', mind_help
};


int
main_mind()
{
  XO *xo;
  char fpath[64];

  /* 借用 XZ_PAL,所以 feeter 會不對,沒差 :p */
  sprintf(fpath, "%sindex", DEF_PATH);
  xz[XZ_PAL - XO_ZONE].xo = xo = xo_new(fpath);
  xz[XZ_PAL - XO_ZONE].cb = mind_cb;
  xover(XZ_PAL);
  free(xo);

  return 0;
}

--
※ Origin: 元智大學 風之塔 <bbs.yzu.edu.tw> 
※ From  : bbs.yzu.edu.tw
精華選讀←離開[主題上]主題下(k)上篇(j)下篇S/a搜尋 G串列 TAB精華 ↑↓捲 Pg/Space翻