作者TKyo.bbs@cpu.tfcis.org (暗黑貴公子) 看板: plan
標題[功能]新台鐵火車時刻表查詢
時間動力核心 (2006/06/16 Fri 10:01:06) Updated: 2006/06/16
前言
1.捨棄以往介面, 以 pans() 介面完全取代
2.pans() 介面以新板台鐵火車時刻表查詢介面為思考模式
3.產生兩種查詢結果 (簡易速度較快, 完整速度較慢)
------------------------------------------------------------------------------
:src/lib/f_simg.c
/* 原理同 f_img.c, 唯一不同處為 size + 1 (安全搜尋字串用) */
#include <fcntl.h>
#include <sys/stat.h>
char *
f_simg(fpath, fsize)
char *fpath;
int *fsize;
{
int fd, size, len;
char *fw;
struct stat st;
if ((fd = open(fpath, O_RDONLY)) < 0)
return NULL;
fpath = NULL;
if (!fstat(fd, &st) && S_ISREG(st.st_mode) && (size = st.st_size) > 0
&& (fpath = (char *) malloc(size + 1)))
{
*fsize = size + 1;
fw = fpath;
while (len = read(fd, fw, size))
fw += len;
*fw = '\0';
if (fw - fpath != size)
{
free(fpath);
fpath = NULL;
}
}
close(fd);
return fpath;
}
:src/include/global.h
/* 適當位置插入 (給網路工具用訊息) */
+ #ifdef HAVE_NETTOOL
+ #define MSG_NET_WAIT "連接伺服器中,請稍候..."
+ #define MSG_NET_OK "已連接"
+ #define MSG_NET_SEARCH "查詢資料中,請稍候..."
+ #define MSG_NET_LOST "無法連接上伺服器,查詢失敗"
+ #define MSG_NET_ERROR "資料查詢發生錯誤!"
+ #define MSG_NET_ASK "您要將查詢結果寄回信箱嗎?[N] "
+ #endif
:src/maple/windows.c:pans()
/* 新增 Page Up / Page Down 支援 */
/* 啟用 : 選單結構 Hotkey 再新增一字元即可 */
/* 傳回值為 'U' / 'D' */
- int cur, old_cur, max, ch;
+ int cur, old_cur, max, ch, page;
...
hotkey = desc[0][0];
+ page = desc[0][2];
...
case KEY_END:
cur = max;
break;
+ case KEY_PGUP:
+ if (page)
+ {
+ vs_restore(slt);
+ return 'U';
+ }
+ break;
+ case KEY_PGDN:
+ if (page)
+ {
+ vs_restore(slt);
+ return 'D';
+ }
+ break;
:src/maple/menu.c
/* 自訂選單位置插入 */
"bin/twrailway.so:twrailway_main", 0, - M_XMODE,
"Railway Query 台鐵火車時刻表查詢",
新增 :/src/so/twrailway.c
/*-------------------------------------------------------*/
/* twrailway.c ( NTHU CS MapleBBS Ver 3.10 ) */
/*-------------------------------------------------------*/
/* target : 台鐵火車時刻表查詢 */
/* create : 06/05/26 */
/* update : / / */
/* author : kyo@cszone.twbbs.org */
/*-------------------------------------------------------*/
#include "bbs.h"
#ifdef HAVE_NETTOOL
#define LYNX_PATH _
"/usr/local/bin/lynx -useragent=L_y_n_x --source" /* lynx 的絕對路徑 */
#define AUTOB5_PATH _
"/usr/local/bin/autob5" /* autoconvert 絕對路徑 */
#define STATION_PAGE 10
#define CGI_RailWay "\"SBeginStation=%s&SBeginStationName=&SEndStation=%s" _
"&SEndStationName=&SClass=%c&SDateTime=%s&STime=0000|2359"
"&SearchType=0&SBeginCityCode=&SEndCityCode="
"&BStationIndex=&EStationIndex=\""
static char *station_name[] = {
"基隆", "八堵", "七堵", "五堵", "汐止",
"南港", "松山", "台北", "萬華", "板橋",
"樹林", "山佳", "鶯歌", "桃園", "內壢",
"中壢", "埔心", "楊梅", "富岡", "湖口",
"新豐", "竹北", "新竹", "香山", "崎頂",
"竹南", "三坑", "談文", "大山", "後龍",
"龍港", "白沙屯", "新埔", "通霄", "苑裡",
"日南", "大甲", "台中港", "清水", "沙鹿",
"龍井", "大肚", "追分", "彰化", "花壇",
"員林", "永靖", "社頭", "田中", "二水",
"林內", "石榴", "斗六", "斗南", "石龜",
"大林", "民雄", "嘉義", "水上", "南靖",
"後壁", "新營", "柳營", "林鳳營", "隆田",
"拔林", "善化", "新市", "永康", "台南",
"保安", "中洲", "大湖", "路竹", "岡山",
"橋頭", "楠梓", "左營", "高雄", "大橋",
"大村", "嘉北", "造橋", "豐富", "苗栗",
"南勢", "銅鑼", "三義", "泰安", "后里",
"豐原", "潭子", "台中", "烏日", "成功\",
"大慶", "太原", "鳳山", "後庄", "九曲堂",
"六塊厝", "屏東", "歸來", "麟洛", "西勢",
"竹田", "潮州", "崁頂", "南州", "鎮安",
"林邊", "佳冬", "東海", "枋寮", "加祿",
"內獅", "枋山", "古莊", "大武", "瀧溪",
"多良", "金崙", "太麻里", "知本", "康樂",
"吉安", "志學", "平和", "壽豐", "豐田",
"溪口", "南平", "鳳林", "萬榮", "光復",
"大富", "富源", "瑞穗", "三民", "玉里",
"安通", "東里", "東竹", "富里", "池上",
"海端", "關山", "月美", "瑞和", "瑞源",
"鹿野", "山里", "台東", "永樂", "東澳",
"南澳", "武塔", "漢本", "和平", "和仁",
"崇德", "新城", "景美", "北埔", "花蓮",
"暖暖", "四腳亭", "瑞芳", "侯硐", "三貂嶺",
"牡丹", "雙溪", "貢寮", "福隆", "石城",
"大里", "大溪", "龜山", "外澳", "頭城",
"頂埔", "礁溪", "四城", "宜蘭", "二結",
"中里", "羅東", "冬山", "新馬", "蘇澳新",
"蘇澳", "大華", "十分", "望古", "嶺腳",
"平溪", "菁桐", "竹中", "上員", "竹東",
"橫山", "九讚頭", "合興", "富貴", "內灣",
"榮華", "源泉", "濁水", "龍泉", "集集",
"水里", "車埕", "其他地區", "台北地區", "桃園地區",
"新竹地區", "苗栗地區", "台中地區", "彰化地區", "南投地區",
"雲林地區", "嘉義地區", "台南地區", "高雄地區", "屏東地區",
"台東地區", "花蓮地區", "宜蘭地區", "平溪線", "內灣線",
"集集線"};
static char *station_num[] = {
"1001", "1002", "1003", "1004", "1005",
"1006", "1007", "1008", "1009", "1011",
"1012", "1013", "1014", "1015", "1016",
"1017", "1018", "1019", "1020", "1021",
"1022", "1023", "1025", "1026", "1027",
"1028", "1029", "1102", "1104", "1105",
"1106", "1107", "1108", "1109", "1110",
"1111", "1112", "1113", "1114", "1115",
"1116", "1117", "1118", "1120", "1202",
"1203", "1204", "1205", "1206", "1207",
"1208", "1209", "1210", "1211", "1212",
"1213", "1214", "1215", "1217", "1218",
"1219", "1220", "1221", "1222", "1223",
"1224", "1225", "1226", "1227", "1228",
"1229", "1230", "1231", "1232", "1233",
"1234", "1235", "1236", "1238", "1239",
"1240", "1241", "1302", "1304", "1305",
"1307", "1308", "1310", "1314", "1315",
"1317", "1318", "1319", "1320", "1321",
"1322", "1323", "1402", "1403", "1404",
"1405", "1406", "1407", "1408", "1409",
"1410", "1411", "1412", "1413", "1414",
"1415", "1416", "1417", "1418", "1502",
"1503", "1504", "1507", "1508", "1510",
"1511", "1512", "1514", "1516", "1517",
"1602", "1604", "1605", "1606", "1607",
"1608", "1609", "1610", "1611", "1612",
"1613", "1614", "1616", "1617", "1619",
"1620", "1621", "1622", "1623", "1624",
"1625", "1626", "1627", "1628", "1629",
"1630", "1631", "1632", "1703", "1704",
"1705", "1706", "1708", "1709", "1710",
"1711", "1712", "1713", "1714", "1715",
"1802", "1803", "1804", "1805", "1806",
"1807", "1808", "1809", "1810", "1811",
"1812", "1813", "1814", "1815", "1816",
"1817", "1818", "1819", "1820", "1821",
"1822", "1823", "1824", "1825", "1826",
"1827", "1903", "1904", "1905", "1906",
"1907", "1908", "2203", "2204", "2205",
"2206", "2207", "2208", "2209", "2210",
"2211", "2702", "2703", "2704", "2705",
"2706", "2707", "-1", "-2", "-3",
"-4", "-5", "-6", "-7", "-8",
"-9", "-10", "-11", "-12", "-13",
"-14", "-15", "-16", "-17", "-18",
"-19"};
static int station_from = 0;
static int station_to = 0;
static int
getStation(title)
char *title;
{
int menu_main[17] = {16, 7, 9, 13, 15, 22, 92, 43, 52, 57, 69, 78, 101, 183,
164, 152, 212};
int menu_region[19] = {18, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222,
223, 224, 225, 226, 227, 228, 229, 230};
int menu_region1[24] = {23, 173, 172, 171, 170, 169, 168, 167, 166, 165, 0,
26, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
int menu_region2[7] = {6, 13, 14, 15, 16, 17, 18};
int menu_region3[6] = {5, 19, 20, 21, 22, 23};
int menu_region4[17] = {16, 24, 25, 27, 28, 29, 30, 31, 32, 33, 34, 82, 83,
84, 85, 86, 87};
int menu_region5[18] = {17, 35, 36, 37, 38, 39, 40, 41, 42, 94, 88, 89, 90,
91, 98, 92, 95, 93};
int menu_region6[9] = {8, 43, 44, 80, 45, 46, 47, 48, 49};
int menu_region7[8] = {7, 206, 207, 208, 209, 210, 211, 49};
int menu_region8[6] = {5, 50, 51, 52, 53, 54};
int menu_region9[7] = {6, 55, 56, 81, 57, 58, 59};
int menu_region10[14] = {13, 60, 61, 62, 63, 64, 65, 66, 67, 68, 79, 69, 70,
71};
int menu_region11[11] = {10, 72, 73, 74, 75 ,76, 77, 78, 97, 98, 99};
int menu_region12[18] = {17, 100, 101, 102, 103, 104, 105, 106, 107, 108,
109, 110, 111, 112, 113, 114, 115, 116};
int menu_region13[18] = {17, 117, 118, 119, 120, 121, 122, 123, 124, 152,
151, 150, 149, 148, 147, 146, 145, 144};
int menu_region14[27] = {26, 143, 142, 141, 140, 139, 138, 137, 136, 135,
134, 133, 132, 131, 130, 129, 128, 127, 126, 125,
164, 163, 162, 161, 160, 159, 158};
int menu_region15[23] = {22, 157, 156, 155, 154, 153, 190, 189, 188, 187,
186, 185, 184, 183, 182, 181, 180, 179, 178, 177,
176, 175, 174};
int menu_region16[8] = {7, 169, 196, 195, 194, 193, 192, 191};
int menu_region17[11] = {10, 22, 197, 198, 205, 199, 200, 201, 202, 203,
204};
int menu_region18[8] = {7, 206, 207, 208, 209, 210, 211, 49};
int *event[] = {menu_main, menu_region,
menu_region1, menu_region2, menu_region3, menu_region4,
menu_region5, menu_region6, menu_region7, menu_region8,
menu_region9, menu_region10, menu_region11, menu_region12,
menu_region13, menu_region14, menu_region15, menu_region16,
menu_region17, menu_region18};
int event_num, i, j, top, page;
char buf[100];
char menu_sub[10][25] = {0};
char *menu_station[13];
char menu_main_command[4] = {0}, menu_region_command[4] = {0};
char buf_command[4] = {0};
event_num = top = 0;
strcpy(menu_main_command, "0Q");
strcpy(menu_region_command, "0R");
strcpy(buf_command, "0R");
for(;;)
{
if (event_num == 0)
menu_station[0] = menu_main_command;
else if (event_num == 1)
menu_station[0] = menu_region_command;
else
menu_station[0] = buf_command;
page = (event[event_num][0] - 1) / STATION_PAGE;
if (page)
menu_station[0][2] = '1';
else
{
menu_station[0][2] = '\0';
strcpy(buf, title);
}
for (i = top; i < BMIN(top + STATION_PAGE, event[event_num][0]); i++)
{
j = i % STATION_PAGE;
sprintf(menu_sub[j], "%d %-s", j,
station_name[event[event_num][i + 1]]);
menu_station[j + 1] = menu_sub[j];
}
if ((j = i % STATION_PAGE) == 0)
j = STATION_PAGE;
menu_station[++j] = "Q 取消";
menu_station[++j] = NULL;
if (page)
sprintf(buf, "%s [" MENU_COLOR "PgUp" HEAD_ON "/" MENU_COLOR "PgDn"
HEAD_ON "] 上下頁 ║" FCOLOR "%c" HEAD_ON "║",
title, (top / STATION_PAGE) + '1');
i = pans(-1, -1, buf, menu_station);
if (i >= '0' && i <= '9')
menu_station[0][0] = (char) i;
if (i == 'D')
{
top += STATION_PAGE;
if (top > (event[event_num][0] - 1))
top = 0;
menu_station[0][0] = '0';
continue;
}
else if (i == 'U')
{
top -= STATION_PAGE;
if (top < 0)
top = page * STATION_PAGE;
menu_station[0][0] = '0';
continue;
}
else if (i == 'r')
{
if (event_num >= 2)
{
top = ((event_num - 2) / STATION_PAGE) * STATION_PAGE;
event_num = 1;
}
else
{
event_num = 0;
top = STATION_PAGE;
}
continue;
}
else if (i == 'q')
{
event_num = -1;
break;
}
else
{
i = event[event_num][(top + (i - '0') + 1)];
if ((event_num = atoi(station_num[i])) < 0)
{
event_num = -event_num;
top = 0;
continue;
}
event_num = i;
break;
}
}
return event_num;
}
static void
str_alltrim(buf, str, end)
char *buf;
char *str;
char *end;
{
int i;
char ch;
i = 0;
buf[i] = '\0';
while (str <= end)
{
ch = *str;
if (!(ch == ' ' || ch == 0x0a || ch == 0x09 || ch == 0x0d))
buf[i++] = ch;
str++;
}
buf[i] = '\0';
}
static int
html_parser(src, dst, title, qtype)
char *src, *dst, *title, qtype;
{
FILE *fpw;
int fsize, i, max;
char buf[80];
char *fimage, *start, *str1, *str2, *str3;
char *search[9] = {"EStationIndex=\" >", "EStationIndex=\" >",
"<div align=\"center\">", "<div align=\"center\">",
"</FONT>", "</FONT>", "</FONT>", "</FONT>",
"<span class=\"content_font\">"};
char *search_end[9] = {"</A>", "</A>", "</div>", "</div>",
"</div>", "</div>", "</div>", "</div>", "</font>"};
char *out_fmt[9] = {"│ %4s ", "│%4s", "│%2.2s", "│ %10.10s ",
"│ %5.5s ", "│ %5.5s ", "│%4s", "│%10s│\n",
"│ %-69.69s│\n"};
char *tran_name[4] = {"自強", "莒光", "復興", "電車"};
char tran_color[4] = {'1', '6', '4', '7'};
char *other_info[5] = {"加", "餐\", "專", "跨", "天"};
char *other_desc[5] = {"加班車", "附掛餐\車", "設殘障旅客專用座位車",
"跨日車", "每天行駛"};
char *other_pic[5] = {"addtrain.gif", "food.gif", "people.gif", "mood.gif",
"everyday.gif"};
char *other_search[1] = {"<font color=\"red\">"};
if (!(fimage = f_simg(src, &fsize)))
return 0;
start = fimage;
if (!(fpw = fopen(dst, "w")))
return 0;
fprintf(fpw, "%s\n"
"┌───┬──┬─┬───────┬────┬────┬──┬───"
"──┐\n"
"│ 乘坐 │車次│經│始發站->到達站", title);
if (strlen(station_name[station_from]) == 4)
fprintf(fpw, "│ %4s ", station_name[station_from]);
else
fprintf(fpw, "│ %6s ", station_name[station_from]);
if (strlen(station_name[station_to]) == 4)
fprintf(fpw, "│ %4s ", station_name[station_to]);
else
fprintf(fpw, "│ %6s ", station_name[station_to]);
fputs("│全票│ 行駛時間 │\n"
"│ 車種 │編號│由│ │開車時間│到達時間│價錢│ │\n", fpw);
if (qtype)
{
fputs("├───┼──┼─┼───────┼────┼────┼──┼──"
"───┤\n", fpw);
max = 9;
i = 0;
}
else
max = 8;
while ((str1 = strstr(start, "<A class=sLINK4")))
{
if (qtype && i == max)
fputs("├───┬──┬─┬───────┬────┬────┬──┬─"
"────┤\n", fpw);
for (i = 0; i < max; i++)
{
if ((str2 = strstr(str1, search[i])) &&
(str3 = strstr(str2, search_end[i])))
{
str2 += strlen(search[i]);
*str3 = '\0';
str1 = str3 + 1;
str_alltrim(buf, str2, str3);
if (i == 0)
{
if (qtype == 0)
fputs("├───┼──┼─┼───────┼────┼────┼─"
"─┼─────┤\n", fpw);
for (fsize = 0; fsize < 4; fsize++)
{
if (str_ncmp(buf, tran_name[fsize], 4) == 0)
{
sprintf(buf, "\033[1;3%cm%s\033[m", tran_color[fsize],
tran_name[fsize]);
break;
}
}
}
else if (i == (max - 1))
{
start = str1;
if (qtype)
{
fputs("├───┴──┴─┴───────┴────┴────┴─"
"─┴─────┤\n", fpw);
*buf = '\0';
for (fsize = 0; fsize < 5; fsize++)
{
if (strstr(str2, other_pic[fsize]))
{
if (*buf)
{
strcat(buf, "、");
strcat(buf, other_info[fsize]);
}
else
strcat(buf, other_info[fsize]);
}
}
if ((str2 = strstr(str2, other_search[0])))
{
char info[80];
str2 += strlen(other_search[0]);
str_alltrim(info, str2, str3);
if (strlen(info) > 0)
{
strcat(buf, ",");
strcat(buf, info);
}
}
}
}
fprintf(fpw, out_fmt[i], buf);
}
else
break;
}
if (i != max)
break;
}
if (qtype)
{
fputs("└────────────────────────────────"
"───┘\n\n"
"說明:\n", fpw);
for (i = 0; i < 5; i++)
fprintf(fpw, " %s - %s\n", other_info[i], other_desc[i]);
}
else
fputs("└───┴──┴─┴───────┴────┴────┴──┴──"
"───┘\n", fpw);
fclose(fpw);
free(fimage);
return 1;
}
static int
http_conn(query, title, qtype)
char *query, *title, qtype;
{
char src[64], dst[64];
char cmd[768];
outs(MSG_NET_WAIT);
refresh();
sprintf(src, "tmp/%s.rail", cuser.userid);
sprintf(cmd, LYNX_PATH " -display_charset=utf-8 -nolist -dump "
"http://new.twtraffic.com.tw/twrail/nonscript_search_result.aspx?"
"%s > %s.utf8", query, src);
system(cmd);
sprintf(cmd, AUTOB5_PATH " -i utf8 -o big5 < %s.utf8 > %s", src, src);
system(cmd);
sprintf(cmd, "%s.utf8", src);
unlink(cmd);
outs(MSG_NET_OK "\n");
outs(MSG_NET_SEARCH);
refresh();
sprintf(dst, "tmp/%s.way", cuser.userid);
if (html_parser(src, dst, title, qtype))
{
if (more(dst, (char *) -1) >= 0)
{
if (vans(MSG_NET_ASK) == 'y')
mail_self(dst, cuser.userid, "[備 忘 錄] 台鐵火車時刻表查詢結果",
MAIL_READ);
}
}
else
vmsg(MSG_NET_ERROR);
unlink(dst);
unlink(src);
return 0;
}
int
twrailway_main(void)
{
int pos, ch;
char train_type, num[3], dday[9];
char *menu_train_type[] = {"0Q",
"0 對號列車",
"1 非對號列車",
"2 所有車種",
"Q 取消", 0};
char *menu_dday[] = {"0Q",
"0 今天",
"1 明天",
"2 後天",
"C 自行輸入",
"Q 取消", 0};
char *menu_query_type[] = {"00",
"0 簡易資訊",
"1 完整資訊", 0};
char atrn[512];
char title[128];
struct tm *ptime;
time_t now;
vs_bar("台鐵火車時刻表查詢");
pos = 2;
if ((station_from = getStation("選擇起程站")) > 0)
{
move(pos++, 0);
prints("起程站:%s\n", station_name[station_from]);
if ((station_to = getStation("選擇到達站")) > 0)
{
move(pos++, 0);
prints("到達站:%s\n", station_name[station_to]);
if ((train_type = pans(-1, -1, "選擇車種", menu_train_type)) != 'q')
{
move(pos++, 0);
prints("車種:%s\n", &menu_train_type[((train_type - '0') + 1)][3]);
ch = pans(-1, -1, "選擇時刻表查詢時段", menu_dday);
if (ch != 'q')
{
if (ch == 'c')
{
do
{
if (vget(5, 0, "請輸入時刻表查詢天數(最多 45 天):", num, 3,
DOECHO))
ch = atoi(num);
else
{
ch = -1;
break;
}
} while (ch < 0 || ch > 45);
}
else
{
ch -= '0';
move(pos++, 0);
prints("時刻表查詢時段:%s\n", &menu_dday[(ch + 1)][3]);
}
if (ch >= 0 && ch <= 45)
{
time(&now);
now += 86400 * ch;
ptime = localtime(&now);
sprintf(dday, "%02d/%d/%d", (ptime->tm_year - 11 ) % 100 ,
ptime->tm_mon + 1, ptime->tm_mday);
sprintf(atrn, CGI_RailWay, station_num[station_from],
station_num[station_to], train_type, dday);
ch = pans(-1, -1, "選擇資料顯示模式", menu_query_type);
move(pos++, 0);
prints("資料顯示:%s\n", &menu_query_type[((ch - '0') + 1)][3]);
sprintf(title, "\n 起始站:%s\n 到達站:%s\n查詢車種:%s\n"
"查詢日期:%10.10s\n資料顯示:%s\n",
station_name[station_from], station_name[station_to],
&menu_train_type[((train_type - '0') + 1)][3], BAtime(&now),
&menu_query_type[((ch - '0') + 1)][3]);
http_conn(atrn, title, (ch - '0'));
}
}
}
}
}
return XREDRAW;
}
#endif /* HAVE_NETTOOL */
--
=[﹎:�摃�◣��:﹎ Origin ]|[ ���O���� cpu.tfcis.org ]|[�搟說�﹎:]=
=[﹊:�摃�╱��:﹊ Author ]|[ cszone.twbbs.org ]|[���插�﹊:]=