帮助设计自定义集成插件

大家好!我正在研究不同的论坛平台,旨在为巴西的竞技编程(CP)爱好者构建一个社区,但看起来我已经找到了理想的选择!

我希望在这个论坛上实现的一个功能是与 Codeforces 的集成——Codeforces 是一个举办竞技编程比赛和讨论的在线平台。在 Codeforces 中,参赛者拥有一个会根据其在正式比赛中的表现而变化的“评级”(rating)。我希望让我的用户能够在其论坛个人资料中展示他们辛苦获得的评级。

因此,我计划开发的这个插件首先需要允许用户输入他们的 Codeforces 用户名,并以某种方式验证该用户名确实属于该论坛用户。为此,我考虑使用“自定义向导插件”(Custom Wizard Plugin)来询问他们的用户名,然后通过 Codeforces Talks API 发送一个随机字符串,用户需要正确输入该字符串。如果一切顺利,就将他们的用户名存储在一个自定义用户字段中。这样做是否合适?您是否有不同的建议?

现在,我了解我的 [未来] 用户,毕竟我自己也是一名 CP 爱好者!他们会喜欢通过论坛用户名颜色来展示他们的评级。也就是说,如果评级高于 1400,用户名显示为青色;如果高于 1600,则显示为蓝色,以此类推。

我快速研究了如何在 Discourse 上自定义用户名颜色,得到了以下解决方案:我应该为每个评级区间创建一个用户组,然后动态地将用户分配到正确的组中。是否有更好或更简单的方法?

因此,当用户首次将他们的 Codeforces 账户与其个人资料关联时,我可以获取他们的评级,并将他们分配到正确的组(例如:specialist、expert、candidate master,一直到 international grandmaster)。然而,评级可能会很快发生变化,我希望在用户评级更新时能自动更新其所属组别。

目前,我想到了一些实现方法,希望能得到关于选择哪种方案的建议,如果可能的话,也希望能获得一些针对 Discourse 的具体指导:

  • 运行一个定期任务,更新每个用户的个人评级和组别(这会向 Codeforces API 发送大量请求)
  • 运行一个定期任务,在比赛进行时进行处理。由于评级只会在比赛期间发生变化,如果用户的初始评级是一致的,通过实时处理评级变化,我可以仅更新发生变化的评级,并只需一次外部 API 调用即可保持一致性
  • 实现一个自定义的评级和组别解析器。这样我需要存储上次获取的评级,并在下一次 GET rating/groups 请求时,如果评级已过期,则调用 Codeforces API 更新用户的评级和组别。这是我最倾向的方案,因为它看起来简单,并且最终总能保持一致性。不过,我不太确定如何实现它,或者动态地为用户移除和添加组别会带来什么后果。甚至不确定这作为插件是否完全可行

哎呀,抱歉写了这么多!我非常希望能听到关于这一切的任何意见。感谢大家的关注。

一旦你在 user_custom_field 中获取了他们的 Codeforces 用户名,那么在他们登录时更新你需要的任何资料信息(例如分配群组、将 Codeforces 的个人资料数据存入用户自定义字段等)就会变得相当简单。

类似如下:

after_initialize do
  DiscourseEvent.on(:user_logged_in) do |user|
    # 从 Codeforces 获取数据
    if codeforce_rating > 1400
      group = Group.find_by(name: group_1400)
      if group
        gu = GroupUser.find_by(group_id: group.id, user_id: user.id)
        GroupUser.create(group_id: group.id, user_id: user.id) unless gu
      end
    end
  end
end

这种方式非常简单,你只会为社区中实际活跃的用户更新数据。

太棒了!很高兴我在实施任何操作之前先四处打听了一下。

非常感谢!

如果您的所有用户都是 Codeforces 用户,我建议实现单点登录(SSO),将 Codeforces 作为身份验证提供商。这样就不需要额外的验证步骤,用户的注册/登录流程也会更加顺畅。您甚至可以借此同步用户组!

我建议从源头处理:即当 Codeforces 检测到评分变化时,直接调用 Discourse 的 API 来更新评分(或受该评分影响的其他用户属性)。这样就能确保所有数据始终最新。当您需要同步数据时,轮询方式迟早会引发各种问题,因此请尽量避免使用轮询,转而采用基于事件的方法。

我原本以为无法将 Codeforces 用作 SSO 主系统。如果可行的话,你绝对应该采用这种方式!

@pfaffman 认为无法将 Codeforces 用作身份验证提供商的假设是正确的。Codeforces 基本上由一个人维护,我怀疑他是否会为仍处于规划或融资阶段的项目实现任何功能。

我同意轮询并非最优方案!因此,提出的在用户登录时进行查询的方案,似乎在兼顾 [用户的] 一致性与避免过度访问 Codeforces 服务器从而引起注意甚至被封锁之间取得了良好的平衡。

如果我们要为巴西社区实施的这一特定案例取得成功,并且其他社区也尝试效仿,那么也许 Mike(Codeforces 的那位负责人)会实现类似的功能。

尽管如此,非常感谢您的建议!我会将这些建议铭记于心,以便在明年六月与 Mike 会面时,尝试说服他提供帮助,并可能对我们论坛届时采用的任何解决方案进行优化。