Re: [閒聊] 排程系統

作者: laechan (揮淚斬馬雲)   2018-01-13 21:40:36
經思考後,crontab 還是廢棄好了。
目前決定還是回歸 set_times_check 的做法,然後以最近應該優先
完成的自動排程拍賣系統為例,/cmds/std/_blarket.c 裡面要加上
times_check 函數,以華麗與汙痕書店為例,它要透過下指令觸發,
使用者下指令,它才會去 set_times_check,所以我只要透過下指令
的方式設定排程即可,以書店為例,設定的呼叫段如下:
幾秒後
times_check->set_times_check(names,shop_files,({str,sk}),sk/50);
所以假設我希望 2/15 晚上 21:00 開啟拍賣,這時需要一個計算函
數,計算上面時間與現在時間的秒數差,這個有簡單的方式
Sat Jan 13 21:03:10 2018 現在時間
Thr Feb 15 21:00:00 2018 目標時間
年先不用管,上面做 sscanf 取出 mon 及 day:
times=time();
sscanf(ctime(times),"%s %s %s %d:%d:%d %s",week,mon,day,hour,min,sec,year);
tar_mon="Feb";
tar_day="15";
tar_hour=21;
tar_min=0;
t=0;
// 這個迴圈做完只是一瞬間的事而已
while(mon!=tar_mon || day!=tar_day)
{
t+=86400;
sscanf(ctime(times+t),"%s %s %s %d:%d:%d %s",week,mon,day,
hour,min,sec,year);
}
脫離上面 while 的條件就是 mon==tar_mon && day==tar_day,因為
不比年,所以迴圈最多跑三百多次。接著:
t=t+(tar_hour-hour)*3600+(tar_min-min)*60; // 秒不用管
幾秒後
times_check->set_times_check("blarket","/cmds/std/_blarket",({參數}),t);
我剛有用 running 實驗,2849340 秒後就是 2018/2/15 晚上九點:
if(1)
{
string week,mon,day,tar_mon,tar_day,year;
int times,t,hour,min,sec,tar_hour,tar_min;
// 以 2018/02/15 21:00 為例
times=time();
sscanf(ctime(times),"%s %s %s %d:%d:%d %s",week,mon,day,hour,min,sec,year);
tar_mon="Feb";
tar_day="15";
tar_hour=21;
tar_min=0;
t=0;
// 這個迴圈做完只是一瞬間的事而已
while(mon!=tar_mon || day!=tar_day)
{
t+=86400;
sscanf(ctime(times+t),"%s %s %s %d:%d:%d %s",week,mon,day,
hour,min,sec,year);
}
t=t+(tar_hour-hour)*3600+(tar_min-min)*60;
write("t="+t+", ctime(times+t)="+ctime(times+t)+"\n");
}
========== 程式執行區 ==========
t=2849340, ctime(times+t)=Thu Feb 15 21:00:58 2018
========== 程式執行區 ==========
這比 crontab 穩定多了,因為不需要判斷年,就可以很簡單的做好
防止迴圈過大的判斷(例如在 while 迴圈內加上計數器,超過 400
次就代表給的時間有問題就不設定)。
而且,有需要時再設定即可。
就算是 loop 型的 times_check 同樣也可以交給目標物件去做,好
處就是自己的目標物件要跑怎麼樣的 loop 判斷,自己寫最彈性。
這裡還可以導入 boat 的概念:
// 航行計劃
set("plane",({ ({"菲里德軍港","/u/l/laechan/area/felid/room/285-軍港",30,90}),
({"西斯迪克港","/u/l/laechan/area/sisdic/room/001",30,90}),
({"塔塔克高原",TR"015",30,90}),}));
仿照航行計劃,自己編拍賣計劃
// 拍賣計劃
set("blarket",([
"newyear":({ ({......,幾秒後,等待幾秒,..}),
.
.
}),
"santa": ...
]));
先編好拍賣計劃,再透過指令去設定,不同的節慶執行不同的拍賣
計劃即可,根據我 blarket 的寫法
void create()
{
seteuid(getuid(this_object()));
if(file_exists("/open/cmds/blarket.o"))
restore_object("/open/cmds/blarket");
else
data["boards"]=([]);
set("pre_clean",1); // 避免被系統當成真正的 room. 2010/08/28
}
我在這邊多寫一個讀取排程的物件資料即可。
以上應該是比較容易實行的方式,維持 times_check 的泛用性,
wiz 不用習慣新的系統(crontab),只要知道 times_check 的原理
即可,而這東西已經存在很久也有範例了(/std/new_ob/boat.c)。
最近會優先改 blarket,改好後會實驗,接著就會改農場控制室,
將星星日改成可由系統去定時跑,例如六日一定會跑,再來可以一
三五跑一次之類的,這個改好後也會實驗,再有時間,就是月例大
賽的擲筊王比賽的定期每月月底或每月一號開啟,什麼時間開啟不
重要,因為開啟後至少 n 天的時間是線上玩家都可以去擲的。
Laechan

Links booklink

Contact Us: admin [ a t ] ucptt.com