如果你愿意存储更多的数据,我会建议这种设计。
而是扣除每次(在游戏中的“状态”强烈依赖),而是存储在玩家们的每一个动作的要点。当然,让我们这个表:
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的数据。
您是否将此数据存储在某种关系数据库中? –
是的。这还没有实现,但在我目前的设计中,我正在考虑使用sql数据库来实现状态永久性。 –
您可能想要考虑在单个查询中更新点的方法,而不必为单个方法调用实例化潜在的大量对象。 –