2011-10-28 34 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