2011-10-28 38 views
3

在我的應用程序中,我有多個不是實時的「遊戲」。在每場比賽中,每個球員都有一個得分。在比賽過程中,玩家可以輪流做一些動作。在php中長時間運行全局計時器

然而,如果沒有動作的時間定製量(1小時至1個月不等)內服用,然後雙方球員將失去點的X量。

我認爲有一個全局的「計時器」,由一個cron作業調用。在1小時的時間間隔內,定時器將調用每個遊戲的deductPoints()函數。

deductPoints()功能,我會做這樣的事情:

deductPoints() 
{ 
    timeSinceLastDeduction++; 
    if(timeSinceLastDeduction >= frequencyOfDeduction) 
    { 
     deduct(); 
     timeSinceLastDeduction = 0; 
    } 
} 

有沒有更好的方式來完成這個任務?

+0

您是否將此數據存儲在某種關係數據庫中? –

+0

是的。這還沒有實現,但在我目前的設計中,我正在考慮使用sql數據庫來實現狀態永久性。 –

+0

您可能想要考慮在單個查詢中更新點的方法,而不必爲單個方法調用實例化潛在的大量對象。 –

回答

1

如果你願意存儲更多的數據,我會建議這種設計。

而是扣除每次(在遊戲中的「狀態」強烈依賴),而是存儲在玩家們的每一個動作的要點。當然,讓我們這個表:

id | playerid | action |   stamp 
----+----------+----------+------------------------ 
    1 |  1 | e2 to e4 | 2011-10-27 04:00:00-04 
    2 |  1 |   | 2011-10-27 04:30:00-04 
    3 |  1 |   | 2011-10-27 06:00:00-04 
    4 |  1 |   | 2011-10-27 07:45:00-04 
    5 |  1 |   | 2011-10-27 08:00:00-04 

等等,等等

E2至E4是順便說一下,常見的開局之一的一步棋。你的遊戲,我無法真正設計。然而,「行動」是可選的,你只需要存儲事件發生的行爲來計算懲罰。 (但是,當然,只要你有空間這樣做,就可以存儲額外的信息)。

在這種情況下,「id」是代理鍵。在PostgreSQL中,DDL看起來像:

CREATE TABLE actions(
    id BIGSERIAL PRIMARY KEY, 
    playerid int, 
    action text, 
    stamp timestamptz, 
    UNIQUE(playerid, stamp)); 

元組(playerid,蓋章)將是 「真正」 的主鍵。 「id」是代理鍵。

要查看時間戳的差異,使用窗口函數的代碼相對簡單。 (繼續使用PostgreSQL)

select playerid, time_between, id FROM 
     (SELECT playerid, 
       stamp - lag(stamp) OVER() as time_between, 
       id FROM actions 
       ORDER BY stamp) 
       as ss 
     WHERE playerid = 1 
       AND time_between > '1 hour'; 

樣本輸出,給早期的測試數據:

playerid | time_between | id 
----------+--------------+---- 
     1 | 01:30:00  | 3 
     1 | 01:45:00  | 4 

你不都有cron作業。你存儲了更多的數據(所以它更容易「撤銷」動作)。如果玩家願意,你可以回顧過去的動作。如果計算懲罰變得效率低下,那麼您總是可以將分數緩存在更高的級別。

窗口函數在MySQL btw中不可用。但是可以在PostgreSQL,SQL Server和Oracle中使用。

編輯:如果空間是一個問題,那麼你可以隨時「垃圾收集」這張桌子定期。不過,那會是很多遊戲。每行佔用約48個字節(假設爲空「行動」)。如果你有1000個玩家,每個玩家用40個動作玩200場比賽,你只有384MB的數據。

+0

非常酷,我不敢相信我之前沒有遇到窗口函數。我會研究這個。 –

+0

如果您確實需要使用MySQL或任何其他沒有窗口功能的數據庫來執行此操作,只需從給定的遊戲中返回玩家的所有操作就很容易。然後你在應用程序代碼中計算它。不要爲執行數據分析的應用程序代碼感到羞恥。它是一個巧妙的技巧,你可以在SQL中完成所有這些工作,但如果你不需要,不要專注於這樣做。 – Dragontamer5788

+0

是的,我必須使用mysql,所以我基本上是在應用程序代碼中執行此操作。謝謝! –

1

當轉彎的變化,只是當前時間戳存儲到數據庫中,然後使用cron一定的時間間隔期間執行檢查,如果需要的時間已經過去了,執行您的遊戲功能。

基本上就像你想象的那樣,但你需要在某處存儲時間值。進入數據庫或文件。

+0

酷,我很好奇,如果有一個更有效的方式來解決這個問題。在這個方案中,假設我有1000場比賽,那就意味着我必須每小時「醒來」所有1000場比賽,即使只有其中幾個人每小時都會做事 –

+0

如果您有1000場類似的比賽, cron,它檢查哪些遊戲需要注意並處理它們的功能。 – budwiser