ActiveRecord 逻辑挑战 - 使用 AR 时间戳的智能方法

发布于 2024-09-02 08:04:02 字数 1277 浏览 3 评论 0原文

我的问题在某种程度上特定于我的应用程序的问题,但答案在关联逻辑和记录时间戳的用例方面应该具有指导意义。

我有一个 NBA 选择游戏,我想奖励连续正确选择 x 场比赛的徽章 - 10、20、30。

以下是游戏中的模型、属性和关联:

User
id

Pick
id
result # (values can be 'W', 'L', 'T', or nil. nil means hasn't resolved yet.)
resolved # (values can be true, false, or nil.)
game_time
created_at

*注:有选择的结果字段和已解决字段始终为零的情况。也许比赛被取消了。

Badge
id

Award
id
user_id
badge_id
created_at
  • 用户获得多项奖励。
  • 用户有很多选择。
  • 选择属于用户。
  • 徽章有很多奖项。
  • 奖励属于用户。
  • 奖励属于徽章。

这里要在代码中捕获的重要规则之一是,虽然用户可以被授予多个连胜徽章(例如,用户可以赢得多个 10 连胜徽章),但用户不能因为连续获胜而获得另一个徽章之前曾获得过奖章。 考虑这一点的一种方法是,所有获胜选秀权的日期必须在授予连胜徽章的日期之后。例如,假设用户从 5 月 5 日到 5 月 8 日进行了 13 次获胜选择,其中第 10 次获胜选择出现在 5 月 7 日,最后 3 次出现在 5 月 8 日。该用户将在 5 月 7 日获得 10 连胜徽章现在,如果用户在 5 月 9 日再次中奖,代码必须识别出该用户只有 4 次中奖,而不是 14 次,因为该用户已经获得了前 10 次中奖。

现在我们假设该用户又做出 6 个获胜选择。在这种情况下,代码必须认识到自 5 月 5 日以来的所有获奖选择都有资格获得 20 连胜徽章奖励,并颁发该奖励。

另一个重要的规则是,在考虑连胜时,我们不关心比赛时间,而是关心选择的时间(created_at)。例如,假设 A 队在 Sun 上对阵 B 队。 C 队在周六对阵 D 队。如果用户周四选择 C ​​队击败 D 队,周五选择 A 队击败 B 队,周六 C 队获胜,但周日 A 队输球,则用户的连胜次数为 1。C 队是先选的。

那么什么时候必须开始进行连胜呢?一旦选秀就是胜利。如果是输或平局,检查就没有意义。

另请注意:如果选秀未解决(假)并且结果为零,则意味着比赛被推迟并且必须被排除。

综上所述,确定用户是否具有 10 场、20 场或 30 场连胜的最有效、最有效和最精简的方法是什么?

My question is somewhat specific to my app's issue, but the answer should be instructive in terms of use cases for association logic and the record timestamp.

I have an NBA pick 'em game where I want to award badges for picking x number of games in a row correctly -- 10, 20, 30.

Here are the models, attributes, and associations in-play:

User
id

Pick
id
result # (values can be 'W', 'L', 'T', or nil. nil means hasn't resolved yet.)
resolved # (values can be true, false, or nil.)
game_time
created_at

*Note: There are cases where a pick's result field and resolved field will always be nil. Perhaps the game was cancelled.

Badge
id

Award
id
user_id
badge_id
created_at
  • User has many awards.
  • User has many picks.
  • Pick belongs to user.
  • Badge has many awards.
  • Award belongs to user.
  • Award belongs to badge.

One of the important rules here to capture in the code is that while a user can be awarded multiple streak badges (e.g., a user can win multiple 10-streak badges), the user CAN'T be awarded another badge for consecutive winning picks that were previously granted an award badge.
One way to think of this is that all the dates of the winning picks must come after the date that the streak badge was awarded. For example, let's pretend that a user made 13 winning picks from May 5 to May 8, with the 10th winning pick occurring on May 7, and the last 3 on May 8. The user would be awarded a 10-streak badge on May 7. Now if the user makes another winning pick on May 9, the code must recognize that the user only has a streak of 4 winning picks, not 14, because the user already received an award for the first 10.

Now let's assume that the user makes 6 more winning picks. In this case, the code must recognize that all winning picks since May 5 are eligible for a 20-streak badge award, and make the award.

Another important rule is that when looking at a winning streak, we don't care about the game time, but rather when the pick was made (created_at). For example, let's say that Team A plays Team B on Sun. And Team C plays Team D on Sat. If the user picks Team C to beat Team D on Thurs, and Team A to beat Team B on Fri, and Team C wins on Sat, but Team A loses on Sun, then the user has a winning streak of 1. Team C was picked first.

So when must the streak-check kick-in? As soon as a pick is a win. If it's a loss or tie, no point in checking.

One more note: if the pick is not resolved (false) and the result is nil, that means the game was postponed and must be factored out.

With all that said, what is the most efficient, effective and lean way to determine whether a user has a 10-, 20- or 30-win streak?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

情深如许 2024-09-09 08:04:02

我将创建一个 streak 模型,一个用户 has_one streak,包含 3 列:

id
用户 ID
Continuous_wins 整数默认 0

或者

我将 Continuous_wins 列添加到 User。

然后,每次下注解决时,如果不是平局,则更新 Continuous_wins。

  如果输了,则 Continuous_wins 重置为 0。
  如果获胜,则 Continuous_wins 会增加 1。
  如果获胜,请以这种方式授予徽章(ruby'esque psuedo-code):

badge = 10
while badge < max_badge_size do

   if consecutive_wins < badge then
     break
   end

   if (consecutive_wins % badge == 0) then

     # Award the badge here

   end

   badge += 10

end

这个简单的代码似乎涵盖了您的示例。连续 2 场比赛中赢 2 场时,不会获得任何奖励。在连胜 10 场比赛中赢得 10 场时,将授予徽章 10,但不会授予徽章 20。在连胜 40 场比赛中,将授予 10 场比赛徽章、20 场比赛徽章和 40 场比赛徽章,但不会授予 30 场或 50 场比赛徽章。如果连胜 41 场,则不会获得任何奖励。

I'd create a streak model, a user has_one streak, with 3 columns:

id
user_id
consecutive_wins integer default 0

OR

I'd add the consecutive_wins column to User.

Then, each time a bet resolves, if it's not a push, update the consecutive_wins.

  If it's a loss, consecutive_wins is reset to 0.
  If it's a win, consecutive_wins gets incremented by 1.
  If it's a win, award badges in this fashion (ruby'esque psuedo-code):

badge = 10
while badge < max_badge_size do

   if consecutive_wins < badge then
     break
   end

   if (consecutive_wins % badge == 0) then

     # Award the badge here

   end

   badge += 10

end

This simple code seems to cover your example. At win 2 of a 2 game streak, nothing is awarded. At win 10 of a 10 game streak, badge 10 is awarded, but not badge 20. At win 40 of a streak, it would award a 10 badge, a 20 badge, and a 40 badge, but not a 30 or 50 badge. At win 41 of a streak, it would award nothing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文