1

我正在使用 Google App Engine 构建一个 Flash 游戏网站。我将在上面取得成就,并且正在为如何准确存储这些数据而摸不着头脑。我有一个(非谷歌)用户模型。我需要知道如何存储每种成就(名称、描述、图片),以及如何将它们与获得它们的用户联系起来。另外,我需要跟踪他们何时获得它,以及那些还没有获得它的人的当前进度。

如果有人想就检测或其他与成就相关的任务提出建议,请随意。

编辑:

非 Google 用户模型:

class BeardUser(db.Model):
    email = db.StringProperty()
    username = db.StringProperty()
    password = db.StringProperty()
    settings = db.ReferenceProperty(UserSettings)
    is_admin = db.BooleanProperty()
    user_role = db.StringProperty(default="user")
    datetime = db.DateTimeProperty(auto_now_add=True)
4

2 回答 2

3

除非您的用户将动态添加成就(例如在 Kongregate 中,用户可以上传自己的游戏等),否则您的成就列表将是静态的。这意味着您可以将(名称、描述、图片)列表存储在您的主要 python 文件中,或者作为成就模块或其他东西。您可以按此列表中指定的名称或 ID 引用动态数据中的成就。

要指示给定用户是否获得了成就,一种简单的方法是将 ListProperty 添加到您的玩家模型中,该模型将保存玩家获得的成就。默认情况下,这将被索引,因此您可以查询哪些玩家获得了哪些成就等。

如果您还想存储用户获得成就的日期/时间,我们将进入一个内置属性不太理想的区域。您可以添加另一个 ListProperty,其中包含与每个成就相对应的日期时间属性,但这很尴尬:我们真正想要的是一个元组或字典,以便我们可以将成就 ID/名称与实现时间一起存储,并使其变得容易将来添加与每个成就相关的其他属性。

对于这种情况,我通常的方法是将我的理想数据结构转储到 BlobProperty 中,但这有一些缺点,您可能更喜欢不同的方法。

另一种方法是让成就模型与您的用户模型分开,并使用一个 ListProperty,其中包含用户已获得的所有成就的 referenceProperties。这样做的好处是可以很好地索引所有内容,但在运行时会增加 API CPU 成本,特别是如果您要查找大量成就,并且与上述操作相比,删除所有用户的成就等操作将非常昂贵。

于 2009-10-18T02:58:49.110 回答
3

建立在布兰登的回答here。

如果可以的话,在 Python 文件中定义所有成就会快得多,因此它们是在内存中的,不需要获取数据库。这也更容易实现。

class StaticAchievement(object):
    """
    An achievement defined in a Python file.
    """
    by_name = {}
    by_index = []
    def __init__(self, name, description="", picture=None):        
        if picture is None: picture = "static/default_achievement.png"
        StaticAchievement.by_name[name] = self
        StaticAchievement.by_index.append(self)
        self.index = len(StaticAchievement.by_index)

# This automatically adds an entry to the StaticAchievement.by_name dict.
# It also adds an entry to to the StaticAchievement.by_index list.
StaticAchievement(
  name="tied your shoe", 
  description="You successfully tied your shoes!", 
  picture="static/shoes.png"
)

然后您所要做的就是将每个玩家的成就的 id 保存在 db.StringListProperty 中。当你加载了玩家的对象后,渲染成就不需要额外的数据库查找——你已经有了 ID,现在你只需要在 StaticAchievement.all 中查找它们。这很容易实现,并且允许您轻松查询哪些用户具有给定的成就等。不需要其他任何东西。

如果您想要与用户拥有成就相关的其他数据(例如获得成就的日期),那么您可以选择以下方法:

1:将其存储在另一个相同长度的ListProperty中。

这保留了实现的简单性和属性的可索引性。但是,这种解决方案并不符合每个人的口味。如果您需要减少对这些数据的使用混乱,只需在播放器对象上编写一个方法,如下所示:

    def achievement_tuples(self):
        r = []
        for i in range(0, len(self.achievements)):
            r.append( (self.achievements[i], self.achievement_dates[i]) )
        return r

您可以通过维护整数的并行 ListProperty 来处理进度,并在用户取得进展时递增这些整数。

只要您能够理解数据的表示方式,您就可以轻松地将该表示隐藏在您想要的任何方法后面 - 让您拥有所需的界面以及所需的性能和索引特性。但是,如果您真的不需要索引并且不喜欢列表,请参阅选项 #2。

2:将附加数据存储在 BlobProperty 中。

这需要您对数据进行序列化和反序列化,并且您放弃了对列表属性的漂亮查询,但是如果您讨厌并行列表的概念,也许您会更开心。当人们真正想要 Python 的做事方式时,这就是他们倾向于做的事情,这与 App Engine 的方式不同。

3:将附加数据存储在数据库中

(例如,一个包含成就 id 的 StringProperty、一个 DateProperty 和一个 UserProperty 的 PlayersAchievement 对象;在玩家上,一个充满了对 PlayersAchievement 对象的引用的成就列表属性)

由于我们希望玩家有可能获得大量成就,因此开销会很快变差。绕过它很快就会变得非常复杂:memcache,存储中间数据,如预渲染 HTML 的 blob 或序列化的元组列表,设置任务等。如果你想要成就定义,这也是你必须做的事情自己可以修改/存储在数据库中。

于 2010-07-14T18:41:34.583 回答