成就/徽章的架构

Posted

技术标签:

【中文标题】成就/徽章的架构【英文标题】:Architecture for achievements / badges 【发布时间】:2012-12-05 06:21:32 【问题描述】:

已经有很多关于编写类似于 SO 的徽章系统的问题,我的问题有所不同。假设我有一个网页系统、徽章/成就,在数据库中存储为一行,其中包含成就密钥 (id)、用户 ID 和任何其他数据。

我的简单问题是,我应该将徽章 ID 存储在哪里?每个成就我都有一个课程,其中包含所有数据和方法来测试它是否已经获得。我想我可能有几十个或几百个。我希望这些 ID 只使用一次硬编码,并且在一个简洁的地方,所以我不会意外更改它们或混淆它们。

我可以在课堂上对它们进行硬编码,比如

public int Key  get  return 15;   // I'm calling it Key, not ID

但是,如果我将我的成就拆分到多个文件中,我不想在添加新的时候到处寻找最高的密钥并冒着出错的风险。

我可以把它们放在另一个类的字典里...

public class AchievementSet

    private Dictionary<int, Achievement> _achievements;

    public AchievementSet()
    
        _achievements = new Dictionary<int, Achievement>()
        
             1, new SomethingAchievement() 
        ;
    

但是现在类本身不知道它自己的密钥,它需要(或者是吗?)如果我现在将它传递给构造函数,我冒着数字不匹配的风险。

有什么建议吗?

【问题讨论】:

为什么不将徽章存储在数据库中? 我想,因为每个徽章都有关联的代码,您仍然需要将该代码与徽章 ID 匹配。所以它基本上不会解决任何问题。 【参考方案1】:

在 Stack Overflow 的上下文中,我想每个徽章都具有以下属性: ID、姓名、等级(青铜、白银或黄金)和描述等。

您提到您目前为每个徽章/成就都有一个班级,每个班级都对授予它的条件进行了适当的检查。

我建议您放弃您现在正在查看的模型(每个成就一个课程)的原因是因为当您在 200 种不同的环境中导航时,您将继续面临巨大的问题寻找你记不起的那个 ID 的类。

通过将您的徽章存储在表格中,您的数据都在一个逻辑位置,而不是分散在您的应用程序中。

在回答问题时:您是否不同意接受的回答:***.com/questions/3162446/

不一定,我更喜欢这个想法,而不是我之前提出的一个单一班级的提议,该班级将根据他们的 ID 检查所有徽章。

尽管有它的名字,但我相信 RexM 并没有在该文件中定义 CommenterBadge 本身,应该将其命名为 CommenterBadgeJob。 (您会注意到它没有我在答案中定义的任何特征,并且继承自 BadgeJob)。显而易见的问题是“每个徽章作业如何知道它对应于哪个 BadgeId?”

我会在我的Badge 中添加一个名为BadgeJob 的唯一字段,您可以通过它查找徽章。

enum BadgeClass Bronze, Silver, Gold

//This class would be inherited from the database.
public class Badge

    public int Key get;set;
    public string Name get;set;
    public BadgeClass Class get;set;
    public string BadgeJob get;set;
    public string Description get;set

我会修改他的代码如下:

public class CommenterBadgeJob : BadgeJob

    public Badge commenter_badge get;set;
    public CommenterBadgeJob() : base() 
    
        //Lookup badge
        string badge_job_name = this.GetType().Name;
        commenter_badge  = db.Badges.Where(n=>n.BadgeJob == badge_job_name).Single();
    

    protected override void AwardBadges()
    
        //select all users who have more than x comments 
        //and dont have the commenter badge
        //add badges
    

    //run every 10 minutes
    protected override TimeSpan Interval
    
        get  return new TimeSpan(0,10,0); 
    

【讨论】:

那么您不同意***.com/questions/3162446/… 接受的答案吗? 我已经更新了我的答案。如果我不清楚,请告诉我,我会尝试修改我的答案。 我已经将所有数据放入数据库中,这很有效,因为我的大部分成就都具有简单的条件,例如某些字段 >= 阈值。谢谢!【参考方案2】:

使用枚举怎么样?

  public enum BadgeTypes
  
      GoodAnswer    = 1,
      Commenter     = 2,
      Teacher       = 3,
      //...
  

每个 BadgeJob 都可以有一个 BadgeType 属性,该属性将用于在 AwardBadges() 期间插入成就时填充徽章 ID(枚举值可以保留为整数)。

我认为没有必要为每个成就设置一门课程。 BadgeJob 包含所有徽章归属逻辑,BadgeTypes 足以代表不同的徽章。

【讨论】:

但是每个成就不是有一个Job 类吗?这似乎是一回事……我不想要一个长达数千行的“逻辑”类。 是的,每个成就都有一个工作类别(“BadgeJob 包含...”是复数形式)。抱歉,如果不清楚。 或者,您的意思是,您不希望每个成就有一个工作类别?我看不出这会更短:/ 我确实想要一个,因为我不想要一个庞大的班级。但是,如果逻辑在单独的类中,它们的数据(名称、描述)也可以放在那里。 枚举值不能包含空格或标点符号。但我知道你要去哪里。链接也不错。

以上是关于成就/徽章的架构的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 nosql 构建成就和徽章

Google Play 商店中未显示排行榜和成就徽章

如何在对系统的影响最小的情况下为您的 APP 处理成就/徽章/奖励?

Google Play 商店:我的应用页面不显示排行榜和成就图标/徽章

Rails“徽章”类型插件/教程?

Yii2 Twitter Bootstrap 徽章颜色不变:未找到徽章成功徽章危险等类别