/* $Id: vote.c,v 1.2 2002/03/09 17:27:57 in2 Exp $ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "config.h"
#include "pttstruct.h"
#include "modes.h"
#include "common.h"
#include "perm.h"
#include "proto.h"
static int total;
extern int numboards;
extern boardheader_t *bcache; /* Thor: for speed up */
extern char *err_board_update;
extern char *fn_board;
extern char *msg_seperator;
extern int t_lines, t_columns; /* Screen size / width */
extern int b_lines; /* Screen bottom line number: t_lines-1 */
extern int currmode;
extern int usernum;
extern char currboard[]; /* name of currently selected board */
extern userec_t cuser;
static char STR_bv_control[] = "control"; /* 投票日期 選項 */
static char STR_bv_desc[] = "desc"; /* 投票目的 */
static char STR_bv_ballots[] = "ballots";
static char STR_bv_flags[] = "flags";
static char STR_bv_comments[] = "comments"; /* 投票者的建意 */
static char STR_bv_limited[] = "limited"; /* 私人投票 */
static char STR_bv_title[] = "vtitle";
static char STR_bv_results[] = "results";
static char STR_new_control[] = "control0"; /* 投票日期 選項 */
static char STR_new_desc[] = "desc0"; /* 投票目的 */
static char STR_new_ballots[] = "ballots0";
static char STR_new_flags[] = "flags0";
static char STR_new_comments[] = "comments0"; /* 投票者的建意 */
static char STR_new_limited[] = "limited0"; /* 私人投票 */
static char STR_new_title[] = "vtitle0";
int strip_ansi(char *buf, char *str, int mode) {
register int ansi, count = 0;
for(ansi = 0; *str /*&& *str != '\n' */; str++) {
if(*str == 27) {
if(mode) {
if(buf)
*buf++ = *str;
count++;
}
ansi = 1;
} else if(ansi && strchr("[;1234567890mfHABCDnsuJKc=n", *str)) {
if((mode == NO_RELOAD && !strchr("c=n", *str)) ||
(mode == ONLY_COLOR && strchr("[;1234567890m", *str))) {
if(buf)
*buf++ = *str;
count++;
}
if(strchr("mHn ", *str))
ansi = 0;
} else {
ansi =0;
if(buf)
*buf++ = *str;
count++;
}
}
if(buf)
*buf = '\0';
return count;
}
void b_suckinfile(FILE *fp, char *fname) {
FILE *sfp;
if((sfp = fopen(fname, "r"))) {
char inbuf[256];
while(fgets(inbuf, sizeof(inbuf), sfp))
fputs(inbuf, fp);
fclose(sfp);
}
}
static void b_count(char *buf, int counts[]) {
char inchar;
int fd;
memset(counts, 0, 31 * sizeof(counts[0]));
total = 0;
if((fd = open(buf, O_RDONLY)) != -1) {
flock(fd, LOCK_EX); /* Thor: 防止多人同時算 */
while(read(fd, &inchar, 1) == 1) {
counts[(int)(inchar - 'A')]++;
total++;
}
flock(fd, LOCK_UN);
close(fd);
}
}
static int b_nonzeroNum(char *buf) {
int i = 0;
char inchar;
int fd;
if((fd = open(buf, O_RDONLY)) != -1) {
while(read(fd, &inchar, 1) == 1)
if(inchar)
i++;
close(fd);
}
return i;
}
static void vote_report(char *bname, char *fname, char *fpath) {
register char *ip;
time_t dtime;
int fd, bid;
fileheader_t header;
ip = fpath;
while(*(++ip));
*ip++ = '/';
/* get a filename by timestamp */
dtime = time(0);
for(;;) {
sprintf(ip, "M.%ld.A", ++dtime);
fd = open(fpath, O_CREAT | O_EXCL | O_WRONLY, 0644);
if(fd >= 0)
break;
dtime++;
}
close(fd);
log_usies("TESTfn", fname);
log_usies("TESTfp", fpath);
unlink(fpath);
link(fname, fpath);
/* append record to .DIR */
memset(&header, 0, sizeof(fileheader_t));
strcpy(header.owner, "[馬路探子]");
sprintf(header.title, "[%s] 看板 選情報導", bname);
{
register struct tm *ptime = localtime(&dtime);
sprintf(header.date, "%2d/%02d", ptime->tm_mon + 1, ptime->tm_mday);
}
strcpy(header.filename, ip);
strcpy(ip, ".DIR");
if((fd = open(fpath, O_WRONLY | O_CREAT, 0644)) >= 0) {
flock(fd, LOCK_EX);
lseek(fd, 0, SEEK_END);
write(fd, &header, sizeof(fileheader_t));
flock(fd, LOCK_UN);
close(fd);
if((bid = getbnum(bname)) > 0)
setbtotal(bid);
}
}
static void b_result_one(boardheader_t *fh, int ind) {
FILE *cfp, *tfp, *frp, *xfp;
char *bname ;
char buf[STRLEN];
char inbuf[80];
int counts[31];
int num ;
int junk;
char b_control[64];
char b_newresults[64];
char b_report[64];
time_t closetime, now;
fh->bvote--;
if(fh->bvote==0)
fh->bvote=2;
else if(fh->bvote==2)
fh->bvote=1;
if(ind) {
sprintf(STR_new_ballots, "%s%d", STR_bv_ballots, ind);
sprintf(STR_new_control, "%s%d", STR_bv_control, ind);
sprintf(STR_new_desc, "%s%d", STR_bv_desc, ind);
sprintf(STR_new_flags, "%s%d", STR_bv_flags, ind);
sprintf(STR_new_comments, "%s%d", STR_bv_comments, ind);
sprintf(STR_new_limited, "%s%d", STR_bv_limited, ind);
sprintf(STR_new_title, "%s%d", STR_bv_title, ind);
} else {
strcpy(STR_new_ballots, STR_bv_ballots);
strcpy(STR_new_control, STR_bv_control);
strcpy(STR_new_desc, STR_bv_desc);
strcpy(STR_new_flags, STR_bv_flags);
strcpy(STR_new_comments, STR_bv_comments);
strcpy(STR_new_limited, STR_bv_limited);
strcpy(STR_new_title, STR_bv_title);
}
bname = fh->brdname;
setbfile(buf, bname, STR_new_control);
cfp = fopen(buf,"r");
fscanf(cfp, "%d\n%lu\n", &junk, &closetime);
fclose(cfp);
setbfile(b_control, bname, "tmp");
if(rename(buf, b_control) == -1)
return;
setbfile(buf, bname, STR_new_flags);
num = b_nonzeroNum(buf);
unlink(buf);
setbfile(buf, bname, STR_new_ballots);
b_count(buf, counts);
unlink(buf);
setbfile(b_newresults, bname, "newresults");
if((tfp = fopen(b_newresults, "w")) == NULL)
return;
now = time(NULL);
setbfile(buf, bname, STR_new_title);
if((xfp=fopen(buf,"r"))) {
fgets(inbuf, sizeof(inbuf), xfp);
fprintf(tfp, "%s\n◆ 投票名稱: %s\n\n", msg_seperator, inbuf);
}
fprintf(tfp, "%s\n◆ 投票中止於: %s\n\n◆ 票選題目描述:\n\n",
msg_seperator, ctime(&closetime));
fh->vtime = now;
setbfile(buf, bname, STR_new_desc);
b_suckinfile(tfp, buf);
unlink(buf);
if((cfp = fopen(b_control, "r"))) {
fgets(inbuf, sizeof(inbuf), cfp);
fgets(inbuf, sizeof(inbuf), cfp);
fprintf(tfp, "\n◆投票結果:(共有 %d 人投票,每人最多可投 %d 票)\n",
num, junk);
while(fgets(inbuf, sizeof(inbuf), cfp)) {
inbuf[(strlen(inbuf) - 1)] = '\0';
num = counts[inbuf[0] - 'A'];
fprintf(tfp, " %-42s %3d 票 %02.2f%%\n", inbuf + 3, num,
(float)(num*100)/(float)(total));
}
fclose(cfp);
}
unlink(b_control);
fprintf(tfp, "%s\n◆ 使用者建議:\n\n", msg_seperator);
setbfile(buf, bname, STR_new_comments);
b_suckinfile(tfp, buf);
unlink(buf);
fprintf(tfp, "%s\n◆ 總票數 = %d 票\n\n", msg_seperator, total);
fclose(tfp);
setbfile(b_report, bname, "report");
if((frp = fopen(b_report, "w"))) {
b_suckinfile(frp, b_newresults);
fclose(frp);
}
sprintf(inbuf, "boards/%c/%s", bname[0], bname);
vote_report(bname, b_report, inbuf);
if(!(fh->brdattr &BRD_NOCOUNT)) {
sprintf(inbuf, "boards/%c/%s", 'R', "Record");
vote_report(bname, b_report, inbuf);
}
unlink(b_report);
tfp = fopen(b_newresults, "a");
setbfile(buf, bname, STR_bv_results);
b_suckinfile(tfp, buf);
fclose(tfp);
Rename(b_newresults, buf);
}
static void b_result(boardheader_t *fh) {
FILE *cfp;
time_t closetime, now;
int i;
char buf[STRLEN];
char temp[STRLEN];
now = time(NULL);
for(i = 0; i < 9; i++) {
if(i)
sprintf(STR_new_control, "%s%d", STR_bv_control, i);
else
strcpy(STR_new_control, STR_bv_control);
setbfile(buf, fh->brdname, STR_new_control);
cfp = fopen(buf,"r");
if (!cfp)
continue;
fgets(temp,sizeof(temp),cfp);
fscanf(cfp, "%lu\n", &closetime);
fclose(cfp);
if(closetime < now)
b_result_one(fh,i);
}
}
static int b_close(boardheader_t *fh) {
time_t now;
now = time(NULL);
if(fh->bvote == 2) {
if(fh->vtime < now - 3 * 86400) {
fh->bvote = 0;
return 1;
}
else
return 0;
}
b_result(fh);
return 1;
}
int b_closepolls() {
static char *fn_vote_polling = ".polling";
boardheader_t *fhp;
FILE *cfp;
time_t now;
int pos, dirty;
time_t last;
char timebuf[100];
now = time(NULL);
/* Edited by CharlieL for can't auto poll bug */
if((cfp = fopen(fn_vote_polling,"r"))) {
fgets(timebuf,100*sizeof(char),cfp);
sscanf(timebuf, "%lu", &last);
fclose(cfp);
if(last + 3600 >= now)
return 0;
}
if((cfp = fopen(fn_vote_polling, "w")) == NULL)
return 0;
fprintf(cfp, "%lu\n%s\n", now, ctime(&now));
fclose(cfp);
dirty = 0;
for(fhp = bcache, pos = 1; pos <= numboards; fhp++, pos++) {
if(fhp->bvote && b_close(fhp)) {
if(substitute_record(fn_board, fhp, sizeof(*fhp), pos) == -1)
outs(err_board_update);
dirty = 1;
}
}
if(dirty) /* vote flag changed */
reset_board(pos);
return 0;
}
static int vote_view(char *bname, int index) {
boardheader_t *fhp;
FILE* fp;
char buf[STRLEN], genbuf[STRLEN], inbuf[STRLEN];
struct stat stbuf;
int fd, num = 0, i, pos, counts[31];
time_t closetime;
if(index) {
sprintf(STR_new_ballots, "%s%d", STR_bv_ballots, index);
sprintf(STR_new_control, "%s%d", STR_bv_control, index);
sprintf(STR_new_desc, "%s%d", STR_bv_desc, index);
sprintf(STR_new_flags, "%s%d", STR_bv_flags, index);
sprintf(STR_new_comments, "%s%d", STR_bv_comments, index);
sprintf(STR_new_limited, "%s%d", STR_bv_limited, index);
sprintf(STR_new_title, "%s%d", STR_bv_title, index);
} else {
strcpy(STR_new_ballots, STR_bv_ballots);
strcpy(STR_new_control, STR_bv_control);
strcpy(STR_new_desc, STR_bv_desc);
strcpy(STR_new_flags, STR_bv_flags);
strcpy(STR_new_comments, STR_bv_comments);
strcpy(STR_new_limited, STR_bv_limited);
strcpy(STR_new_title, STR_bv_title);
}
setbfile(buf, bname, STR_new_ballots);
if((fd = open(buf, O_RDONLY)) > 0) {
fstat(fd, &stbuf);
close(fd);
} else
stbuf.st_size = 0;
setbfile(buf, bname, STR_new_title);
move(0, 0);
clrtobot();
if((fp = fopen(buf, "r"))) {
fgets(inbuf, sizeof(inbuf), fp);
prints("\n投票名稱: %s", inbuf);
}
setbfile(buf, bname, STR_new_control);
fp = fopen(buf, "r");
fgets(inbuf, sizeof(inbuf), fp);
fscanf(fp, "%lu\n", &closetime);
prints("\n◆ 預知投票紀事: 每人最多可投 %d 票,目前共有 %d 票,\n"
"本次投票將結束於 %s", atoi(inbuf), stbuf.st_size,
ctime(&closetime));
/* Thor: 開放 票數 預知 */
setbfile(buf, bname, STR_new_flags);
num = b_nonzeroNum(buf);
setbfile(buf, bname, STR_new_ballots);
b_count(buf, counts);
prints("共有 %d 人投票\n", num);
total = 0;
while(fgets(inbuf, sizeof(inbuf), fp)) {
inbuf[(strlen(inbuf) - 1)] = '\0';
inbuf[30] = '\0'; /* truncate */
i = inbuf[0] - 'A';
num = counts[i];
move(i % 15 + 6, i / 15 * 40);
prints(" %-32s%3d 票", inbuf, num);
total += num;
}
fclose(fp);
pos = getbnum(bname);
fhp = bcache + pos - 1;
move(t_lines - 3, 0);
prints("◆ 目前總票數 = %d 票", total);
getdata(b_lines - 1, 0, "(A)取消投票 (B)提早開票 (C)繼續?[C] ", genbuf,
4, LCECHO);
if(genbuf[0] == 'a') {
setbfile(buf, bname, STR_new_control);
unlink(buf);
setbfile(buf, bname, STR_new_flags);
unlink(buf);
setbfile(buf, bname, STR_new_ballots);
unlink(buf);
setbfile(buf, bname, STR_new_desc);
unlink(buf);
setbfile(buf, bname, STR_new_limited);
unlink(buf);
setbfile(buf,bname, STR_new_title);
unlink(buf);
if(fhp->bvote)
fhp->bvote--;
if (fhp->bvote == 2)
fhp->bvote = 1;
if(substitute_record(fn_board, fhp, sizeof(*fhp), pos) == -1)
outs(err_board_update);
reset_board(pos);
} else if(genbuf[0] == 'b') {
b_result_one(fhp,index);
if(substitute_record(fn_board, fhp, sizeof(*fhp), pos) == -1)
outs(err_board_update);
reset_board(pos);
}
return FULLUPDATE;
}
static int vote_view_all(char *bname) {
int i;
int x = -1;
FILE *fp, *xfp;
char buf[STRLEN], genbuf[STRLEN];
char inbuf[80];
strcpy(STR_new_control, STR_bv_control);
strcpy(STR_new_title, STR_bv_title);
setbfile(buf, bname, STR_new_control);
move(0, 0);
if((fp=fopen(buf,"r"))) {
prints("(0) ");
x = 0;
fclose(fp);
setbfile(buf, bname, STR_new_title);
if((xfp=fopen(buf,"r")))
fgets(inbuf, sizeof(inbuf), xfp);
else
strcpy(inbuf, "無標題");
prints("%s\n", inbuf);
fclose(xfp);
}
for(i = 1; i < 9; i++) {
sprintf(STR_new_control, "%s%d", STR_bv_control, i);
sprintf(STR_new_title, "%s%d", STR_bv_title, i);
setbfile(buf, bname, STR_new_control);
if((fp=fopen(buf,"r"))) {
prints("(%d) ", i);
x = i;
fclose(fp);
setbfile(buf, bname, STR_new_title);
if((xfp=fopen(buf,"r")))
fgets(inbuf, sizeof(inbuf), xfp);
else
strcpy(inbuf, "無標題");
prints("%s\n", inbuf);
fclose(xfp);
}
}
if(x < 0)
return FULLUPDATE;
sprintf(buf, "要看幾號投票 [%d] ", x);
getdata(b_lines - 1, 0, buf, genbuf, 4, LCECHO);
if(genbuf[0] < '0' || genbuf[0] > '8')
genbuf[0] = '0'+x;
if(genbuf[0] != '0')
sprintf(STR_new_control, "%s%c", STR_bv_control, genbuf[0]);
else
strcpy(STR_new_control, STR_bv_control);
setbfile(buf, bname, STR_new_control);
if((fp=fopen(buf,"r"))) {
fclose(fp);
return vote_view(bname, genbuf[0] - '0');
}
else
return FULLUPDATE;
}
static int vote_maintain(char *bname) {
FILE *fp = NULL;
char inbuf[STRLEN], buf[STRLEN];
int num = 0, aborted, pos, x, i;
time_t closetime;
boardheader_t *fhp;
char genbuf[4];
if(!(currmode & MODE_BOARD))
return 0;
if((pos = getbnum(bname)) <= 0)
return 0;
stand_title("舉辦投票");
fhp = bcache + pos - 1;
/* CharlieL */
if(fhp->bvote != 2 && fhp->bvote !=0) {
getdata(b_lines - 1, 0,
"(V)觀察目前投票 (M)舉辦新投票 (A)取消所有投票 (Q)繼續 [Q]",
genbuf, 4, LCECHO);
if(genbuf[0] == 'v')
return vote_view_all(bname);
else if(genbuf[0] == 'a') {
fhp->bvote=0;
setbfile(buf, bname, STR_bv_control);
unlink(buf);
setbfile(buf, bname, STR_bv_flags);
unlink(buf);
setbfile(buf, bname, STR_bv_ballots);
unlink(buf);
setbfile(buf, bname, STR_bv_desc);
unlink(buf);
setbfile(buf, bname, STR_bv_limited);
unlink(buf);
setbfile(buf, bname, STR_bv_title);
unlink(buf);
for(i = 1; i < 9; i++) {
sprintf(STR_new_ballots, "%s%d", STR_bv_ballots, i);
sprintf(STR_new_control, "%s%d", STR_bv_control, i);
sprintf(STR_new_desc, "%s%d", STR_bv_desc, i);
sprintf(STR_new_flags, "%s%d", STR_bv_flags, i);
sprintf(STR_new_comments, "%s%d", STR_bv_comments, i);
sprintf(STR_new_limited, "%s%d", STR_bv_limited, i);
sprintf(STR_new_title, "%s%d", STR_bv_title, i);
setbfile(buf, bname, STR_new_control);
unlink(buf);
setbfile(buf, bname, STR_new_flags);
unlink(buf);
setbfile(buf, bname, STR_new_ballots);
unlink(buf);
setbfile(buf, bname, STR_new_desc);
unlink(buf);
setbfile(buf, bname, STR_new_limited);
unlink(buf);
setbfile(buf, bname, STR_new_title);
unlink(buf);
}
if(substitute_record(fn_board, fhp, sizeof(*fhp), pos) == -1)
outs(err_board_update);
return FULLUPDATE;
} else if(genbuf[0] != 'm' || fhp->bvote > 10)
return FULLUPDATE;
}
strcpy(STR_new_control, STR_bv_control);
setbfile(buf,bname, STR_new_control);
x = 0;
while(x < 9 && (fp = fopen(buf,"r")) != NULL) {
fclose(fp);
x++;
sprintf(STR_new_control, "%s%d", STR_bv_control, x);
setbfile(buf, bname, STR_new_control);
}
if(fp)
fclose(fp);
if(x >=9)
return FULLUPDATE;
if(x) {
sprintf(STR_new_ballots, "%s%d", STR_bv_ballots,x);
sprintf(STR_new_control, "%s%d", STR_bv_control,x);
sprintf(STR_new_desc, "%s%d", STR_bv_desc,x);
sprintf(STR_new_flags, "%s%d", STR_bv_flags,x);
sprintf(STR_new_comments, "%s%d", STR_bv_comments,x);
sprintf(STR_new_limited, "%s%d", STR_bv_limited,x);
sprintf(STR_new_title, "%s%d", STR_bv_title,x);
} else {
strcpy(STR_new_ballots, STR_bv_ballots);
strcpy(STR_new_control, STR_bv_control);
strcpy(STR_new_desc, STR_bv_desc);
strcpy(STR_new_flags, STR_bv_flags);
strcpy(STR_new_comments, STR_bv_comments);
strcpy(STR_new_limited, STR_bv_limited);
strcpy(STR_new_title, STR_bv_title);
}
clear();
move(0,0);
prints("第 %d 號投票\n", x);
setbfile(buf, bname, STR_new_title);
getdata(4, 0, "請輸入投票名稱", inbuf, 30, LCECHO);
if(inbuf[0]=='\0')
strcpy(inbuf,"不知名的");
fp = fopen(buf, "w");
fprintf(fp, "%s", inbuf);
fclose(fp);
prints("按任何鍵開始編輯此次 [投票宗旨]");
pressanykey();
setbfile(buf, bname, STR_new_desc);
aborted = vedit(buf, NA, NULL);
if(aborted== -1) {
clear();
outs("取消此次投票");
pressanykey();
return FULLUPDATE;
}
aborted = 0;
setbfile(buf, bname, STR_new_flags);
unlink(buf);
getdata(4, 0,
"是否限定投票者名單:(y)編籍可投票人員名單[n]任何人皆可投票:[N]",
inbuf, 2, LCECHO);
setbfile(buf, bname, STR_new_limited);
if(inbuf[0] == 'y') {
fp = fopen(buf, "w");
fprintf(fp,"此次投票設限");
fclose(fp);
friend_edit(FRIEND_CANVOTE);
} else {
if(dashf(buf))
unlink(buf);
}
clear();
getdata(0, 0, "此次投票進行幾天 (一到十天)?", inbuf, 4, DOECHO);
closetime = atoi(inbuf);
if(closetime <= 0)
closetime = 1;
else if(closetime >10)
closetime = 10;
closetime = closetime * 86400 + time(NULL);
setbfile(buf, bname, STR_new_control);
fp = fopen(buf, "w");
fprintf(fp, "00\n%lu\n", closetime);
outs("\n請依序輸入選項, 按 ENTER 完成設定");
num = 0;
while(!aborted) {
sprintf(buf, "%c) ", num + 'A');
getdata((num % 15) + 2, (num / 15) * 40, buf, inbuf, 36, DOECHO);
if(*inbuf) {
fprintf(fp, "%1c) %s\n", (num+'A'), inbuf);
num++;
}
if((*inbuf == '\0' && num >= 1) || num == 30)
aborted = 1;
}
sprintf(buf, "請問每人最多可投幾票?([1]~%d): ", num);
getdata(t_lines-3, 0, buf, inbuf, 3, DOECHO);
if(atoi(inbuf) <= 0 || atoi(inbuf) > num)
strcpy(inbuf,"1");
rewind(fp);
fprintf(fp, "%2d\n", MAX(1, atoi(inbuf)));
fclose(fp);
if(fhp->bvote == 2)
fhp->bvote = 0;
else if(fhp->bvote == 1)
fhp->bvote = 2;
else if(fhp->bvote == 2)
fhp->bvote = 1;
fhp->bvote ++;
if(substitute_record(fn_board, fhp, sizeof(*fhp), pos) == -1)
outs(err_board_update);
reset_board(pos);
outs("開始投票了!");
return FULLUPDATE;
}
static int vote_flag(char *bname, int index, char val) {
char buf[256], flag;
int fd, num, size;
if(index)
sprintf(STR_new_flags, "%s%d", STR_bv_flags, index);
else
strcpy(STR_new_flags, STR_bv_flags);
num = usernum - 1;
setbfile(buf, bname, STR_new_flags);
if((fd = open(buf, O_RDWR | O_CREAT, 0600)) == -1)
return -1;
size = lseek(fd, 0, SEEK_END);
memset(buf, 0, sizeof(buf));
while(size <= num) {
write(fd, buf, sizeof(buf));
size += sizeof(buf);
}
lseek(fd, num, SEEK_SET);
read(fd, &flag, 1);
if(flag == 0 && val != 0) {
lseek(fd, num, SEEK_SET);
write(fd, &val, 1);
}
close(fd);
return flag;
}
static int same(char compare, char list[], int num) {
int n;
int rep = 0;
for(n = 0; n < num; n++) {
if(compare == list[n])
rep = 1;
if(rep == 1)
list[n] = list[n + 1];
}
return rep;
}
static int user_vote_one(char *bname, int ind) {
FILE* cfp,*fcm;
char buf[STRLEN];
boardheader_t *fhp;
int pos = 0, i = 0, count = 0, tickets, fd;
char inbuf[80], choices[31], vote[4], chosen[31];
time_t closetime;
if(ind) {
sprintf(STR_new_ballots, "%s%d", STR_bv_ballots, ind);
sprintf(STR_new_control, "%s%d", STR_bv_control, ind);
sprintf(STR_new_desc, "%s%d", STR_bv_desc, ind);
sprintf(STR_new_flags, "%s%d", STR_bv_flags, ind);
sprintf(STR_new_comments, "%s%d", STR_bv_comments, ind);
sprintf(STR_new_limited, "%s%d", STR_bv_limited, ind);
} else {
strcpy(STR_new_ballots, STR_bv_ballots);
strcpy(STR_new_control, STR_bv_control);
strcpy(STR_new_desc, STR_bv_desc);
strcpy(STR_new_flags, STR_bv_flags);
strcpy(STR_new_comments, STR_bv_comments);
strcpy(STR_new_limited, STR_bv_limited);
}
setbfile(buf, bname, STR_new_control);
cfp = fopen(buf,"r");
if(!cfp)
return FULLUPDATE;
setbfile(buf, bname, STR_new_limited); /* Ptt */
if(dashf(buf)) {
setbfile(buf, bname, FN_CANVOTE);
if(!belong(buf, cuser.userid)) {
fclose(cfp);
outs("\n\n對不起! 這是私人投票..你並沒有受邀唷!");
pressanykey();
return FULLUPDATE;
} else {
outs("\n\n恭喜你受邀此次私人投票....<按任意鍵檢視此次受邀名單>");
pressanykey();
more(buf, YEA);
}
}
if(vote_flag(bname, ind, '\0')) {
outs("\n\n此次投票,你已投過了!");
pressanykey();
return FULLUPDATE;
}
setutmpmode(VOTING);
setbfile(buf, bname, STR_new_desc);
more(buf, YEA);
stand_title("投票箱");
if((pos = getbnum(bname)) <= 0)
return 0;
fhp = bcache + pos - 1;
fgets(inbuf, sizeof(inbuf), cfp);
tickets = atoi(inbuf);
fscanf(cfp,"%lu\n", &closetime);
prints("投票方式:確定好您的選擇後,輸入其代碼(A, B, C...)即可。\n"
"此次投票你可以投 %1d 票。"
"按 0 取消投票 , 1 完成投票\n"
"此次投票將結束於:%s \n",
tickets, ctime(&closetime));
move(5, 0);
memset(choices, 0, sizeof(choices));
memset(chosen , 0, sizeof(chosen));
while(fgets(inbuf, sizeof(inbuf), cfp)) {
move((count % 15) + 5, (count / 15) * 40);
prints( " %s", strtok(inbuf, "\n\0"));
choices[count++] = inbuf[0];
}
fclose(cfp);
while(1) {
vote[0] = vote[1] = '\0';
move(t_lines - 2, 0);
prints("你還可以投 %2d 票", tickets - i);
getdata(t_lines - 4, 0, "輸入您的選擇: ", vote, 3, DOECHO);
*vote = toupper(*vote);
if(vote[0] == '0' || (!vote[0] && !i)) {
outs("記的再來投喔!!");
break;
} else if(vote[0] == '1' && i)
;
else if(!vote[0])
continue;
else if(index(choices, vote[0]) == NULL) /* 無效 */
continue;
else if(same(vote[0], chosen, i)) {
move(((vote[0] - 'A') % 15) + 5, (((vote[0] - 'A')) / 15) * 40);
prints(" ");
i--;
continue;
} else {
if(i == tickets)
continue;
chosen[i] = vote[0];
move(((vote[0]-'A') % 15) + 5, (((vote[0] - 'A')) / 15) * 40);
prints("*");
i++;
continue;
}
if(vote_flag(bname, ind, vote[0]) != 0)
prints("重覆投票! 不予計票。");
else {
setbfile(buf, bname, STR_new_ballots);
if((fd = open(buf, O_WRONLY | O_CREAT | O_APPEND, 0600)) == 0)
outs("無法投入票匭\n");
else {
struct stat statb;
char buf[3], mycomments[3][74], b_comments[80];
for(i = 0; i < 3; i++)
strcpy(mycomments[i], "\n");
flock(fd, LOCK_EX);
for(count = 0; count < 31; count++) {
if(chosen[count])
write(fd, &chosen[count], 1);
}
flock(fd, LOCK_UN);
fstat(fd, &statb);
close(fd);
getdata(b_lines - 2, 0,
"您對這次投票有什麼寶貴的意見嗎?(y/n)[N]",
buf, 3 ,DOECHO);
if(buf[0] == 'Y' || buf[0] == 'y'){
do {
move(5,0);clrtobot();
outs("請問您對這次投票有什麼寶貴的意見?"
"最多三行,按[Enter]結束");
for(i = 0; (i < 3) &&
getdata(7 + i, 0, ":", mycomments[i], 74,
DOECHO); i++);
getdata(b_lines-2,0, "(S)儲存 (E)重新來過 "
"(Q)取消?[S]", buf, 3, LCECHO);
} while(buf[0] == 'E' || buf[0] == 'e');
if(buf[0] == 'Q' || buf[0] == 'q')
break;
setbfile(b_comments, bname, STR_new_comments);
if(mycomments[0])
if((fcm = fopen(b_comments, "a"))){
fprintf(fcm,
"\033[36m○使用者\033[1;36m %s "
"\033[;36m的建議:\033[m\n",
cuser.userid);
for(i = 0; i < 3; i++)
fprintf(fcm, " %s\n", mycomments[i]);
fprintf(fcm, "\n");
fclose(fcm);
}
}
move(b_lines - 1 ,0);
prints("已完成投票!\n");
}
}
break;
}
pressanykey();
return FULLUPDATE;
}
static int user_vote(char *bname) {
int pos;
boardheader_t *fhp;
char buf[STRLEN];
FILE* fp,*xfp;
int i, x = -1;
char genbuf[STRLEN];
char inbuf[80];
if((pos = getbnum(bname)) <= 0)
return 0;
fhp = bcache + pos - 1;
move(0,0);
clrtobot();
if(fhp->bvote == 2 || fhp->bvote == 0) {
outs("\n\n目前並沒有任何投票舉行。");
pressanykey();
return FULLUPDATE;
}
if(!HAS_PERM(PERM_LOGINOK)) {
outs("\n對不起! 您未滿二十歲, 還沒有投票權喔!");
pressanykey();
return FULLUPDATE;
}
strcpy(STR_new_control, STR_bv_control);
strcpy(STR_new_title, STR_bv_title);
setbfile(buf, bname, STR_new_control);
move(0, 0);
if((fp = fopen(buf, "r"))) {
prints("(0) ");
x = 0;
fclose(fp);
setbfile(buf, bname, STR_new_title);
if((xfp = fopen(buf,"r")))
fgets(inbuf, sizeof(inbuf), xfp);
else
strcpy(inbuf, "無標題");
prints("%s\n", inbuf);
fclose(xfp);
}
for(i = 1; i < 9; i++) {
sprintf(STR_new_control, "%s%d", STR_bv_control, i);
sprintf(STR_new_title, "%s%d", STR_bv_title, i);
setbfile(buf, bname, STR_new_control);
if((fp = fopen(buf, "r"))) {
prints("(%d) ", i);
x = i;
fclose(fp);
setbfile(buf, bname, STR_new_title);
if((xfp = fopen(buf, "r")))
fgets(inbuf, sizeof(inbuf), xfp);
else
strcpy(inbuf, "無標題");
prints("%s\n", inbuf);
fclose(xfp);
}
}
if(x < 0)
return FULLUPDATE;
sprintf(buf, "要投幾號投票 [%d] ", x);
getdata(b_lines - 1, 0, buf, genbuf, 4, LCECHO);
if(genbuf[0] < '0' || genbuf[0] > '8')
genbuf[0] = x + '0';
if(genbuf[0] != '0')
sprintf(STR_new_control, "%s%c", STR_bv_control, genbuf[0]);
else
strcpy(STR_new_control, STR_bv_control);
setbfile(buf, bname, STR_new_control);
if((fp = fopen(buf, "r"))){
fclose(fp);
return user_vote_one(bname, genbuf[0] - '0');
} else
return FULLUPDATE;
}
static int vote_results(char *bname) {
char buf[STRLEN];
setbfile(buf, bname, STR_bv_results);
if(more(buf, YEA) == -1)
outs("\n目前沒有任何投票的結果。");
return FULLUPDATE;
}
int b_vote_maintain() {
return vote_maintain(currboard);
}
int b_vote() {
return user_vote(currboard);
}
int b_results() {
return vote_results(currboard);
}