信用过期算法需要帮助

9
所以我卡住了。我正在处理一个有过期时间的积分系统,类似于信用卡里程,但不完全一样。顺便说一句,很抱歉提前写了这么多内容,但我需要添加足够的细节来帮助你获得整个画面。
我需要的是一个系统,用户可以通过完成活动累积积分。但他们也可以在活动上使用这些积分。如果这些积分没有使用,它们应该在30天后过期。我似乎被如何准确计算批处理所困扰,每晚都会运行。任何语言的想法都将不胜感激,因为我似乎被一个无法解决的小细节卡住了。以下是数据示例:
7/1:+5-用户注册 7/2:+5-用户与系统交互 7/2:-3-用户购买活动 7/3:+5-用户与系统交互
所以此时用户已经获得了15个积分,并且已经花费了3个积分。剩下12个积分。(至少我掌握了基本的数学:P)
我应该补充说明,目前我们正在考虑有两个字段:上次处理和下次处理。因此,这些值在此时假设它是一个新注册为:
上次处理日期:7/1 下一个处理日期:8/1
现在到了8/1。批处理开始并查看所有超过30天的积分。此时是5个积分。
这就是它开始变得模糊的地方。
然后系统应该查看最近30天已经使用的所有积分,以查看是否正在使用任何积分。因为它们只有在未被使用时才会过期。所以有3个积分。然后我扣除了用户2个积分,因为那是赚取超过30天的积分和已经花费的积分之间的差异。所以我完成了批处理,并相应地设置了下一天的日期。现在假设他们没有再花费,我重新开始计算赚取超过30天的积分,即5个积分和再次花费的积分,即3个积分。但显然,我不想再次考虑昨天考虑的3个积分。不包括这些3个积分以进行考虑的好方法是什么?
这就是我卡住的地方。
我们正在考虑编写一个关于过期积分的借记记录,以便我们可以跟踪它们,但很难看出我如何在这个计算中使用它。
如果你读到这里,谢谢。如果你甚至做出了一些努力回答,我至少会因为你的努力给你点赞。
编辑: 好的@Greg提到了我忘记解决的问题。在考虑积分时放置标志的想法是一个有效的观点,但由于以下情况而无法工作:
假设在某一天,用户花费了10个积分。但是,该批次考虑的过期积分只累计到5个。那么,他应该仍然有5个积分没有过期,因为他花费的积分不止一个过期时间。所以,标志不起作用,因为我们会跳过这5个额外的积分。希望这样说得清楚吗?
7个回答

4

为了每个系统用户,保留一个数组,存储有关用户在接下来的30天内可用积分数量的信息。

例如,某个用户的数据可能如下所示:

8  | 
7  | | 
6  | | | | 
5  | | | | | | | | | | |
4  | | | | | | | | | | | | | | | | |
3  | | | | | | | | | | | | | | | | | | | | | | | | 
2  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
1  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
  -------------------------------------------------------------
  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
   ^ ^                           ^          
   |  \_                         |
  today tomorrow             in 15 days

每当用户获得一些积分时,您将通过所获得的积分数量增加所有日期的金额。例如,如果用户获得2个积分,则表格将如下所示。就像整个图形上升一样。
10 | 
9  | | 
8  | | | | 
7  | | | | | | | | | | |
6  | | | | | | | | | | | | | | | | |
5  | | | | | | | | | | | | | | | | | | | | | | | | 
4  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
3  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
2  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
1  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
  -------------------------------------------------------------
  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
   ^ ^                           ^          
   |  \_                         |
  today tomorrow             in 15 days

如果用户今天有x个积分并花费了y个积分,您将减少他可用的积分数量至x - y,对于每一天他的积分余额大于x - y。对于他没有超过x - y的日子,积分数量保持不变。就像削去图表的顶部一样。例如,如果用户花费了3个积分,图表会发生变化。

7  | | | | | | | | | | |
6  | | | | | | | | | | | | | | | | |
5  | | | | | | | | | | | | | | | | | | | | | | | | 
4  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
3  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
2  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
1  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
  -------------------------------------------------------------
  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
   ^ ^                           ^          
   |  \_                         |
  today tomorrow             in 15 days

每天您将图表向左移动以模拟过期的信用额度。用户明天将有以下金额:

7  | | | | | | | | | |
6  | | | | | | | | | | | | | | | |
5  | | | | | | | | | | | | | | | | | | | | | | | 
4  | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
3  | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
2  | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
1  | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
  -------------------------------------------------------------
  | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
   ^ ^                           ^          
   |  \_                         |
  today tomorrow             in 15 days

我会给你+1,仅仅是因为你看起来付出了很多努力。让我花几分钟时间来理解你所说的话。但是在快速阅读中,你提到为每个用户都有一个表格。那是打字错误还是你的本意?因为我们有将近10万个用户,为每个用户都建立一个表格可能会有点失控。所以我想要马上理解这一点。 - spinon
@spinon 好的,感谢您的提醒。table 是个糟糕的词汇,这是我的英语不好的表现。我并不是指数据库表,而是一些结构来保存金额,并能将其与日期关联起来。它可以是一个简单的数组,位于数据库之外。我会尝试在编辑中重新表达它。如果使用数据库,只需为30天使用30列,并将一个用户的数据存储在一行中。 - Maciej Hehl
好的,我明白了。让我继续对它进行测试。 - spinon
@spinon 抱歉,在花费积分的描述中我犯了一个错误。我想说的是“更大”,而不是“不超过”。已经修正了。 - Maciej Hehl

3
我不会考虑按照你呈现的方式来处理数据。相反,你应该跟踪用户拥有多少信用点以及何时到期。这样,在购买时就可以跟踪使用了哪些信用点,而不是之后试图解决所有问题。
因此,当用户注册时,他们会拥有:
5 credits expiring on 8/1

与系统互动后的第二天:

5 credits expiring on 8/1
5 credits expiring on 8/2

购买完成后:
2 credits expiring on 8/1
5 credits expiring on 8/2

And so on.


2
这是一个很好的用户界面设计想法,但实际上这种数据存储方式不好;你要有一个审计跟踪来纠正错误。 - Heath Hunnicutt
1
@Heath:确实,这不是一个适当的事务日志替代品。然而,在主要使用类似于这样的东西,并将事务日志视为基本上仅追加,除非出现问题,是我认为前进的最佳方式。 - Anon.
@spinon:交易日志将基本上是只写的——而不是记录过去30天内所有交易的记录,您可以为每个用户维护仅30个整数,并且仍然拥有计算过期时间、余额等所需的所有信息。将日志写出到磁盘上,并将用户数据保留在内存中(信用总额只会达到您预期的用户数量的兆字节级别)。 - Anon.
所以,如果我理解正确的话。你的意思是为每个用户存储一条记录,记录在特定日期到期的所有积分。(我们认为是30天,因此每个用户有30条记录,对吗?)所以,在我的前面情况下,我会有以下记录:8/1 = 5 8/2 = 5 8/3 = 5现在,当他们购买3个积分的活动时,我会从最旧的记录中减去该活动的积分数,对吗?如果是这样的话,如果该活动的成本超过了当天的积分,会发生什么情况?我需要循环遍历每个到期记录,直到达到所需的总数,对吗? - spinon
这似乎是处理事情的最明智方式。 - Nick Johnson
显示剩余3条评论

2
假设您每天运行此批处理,您可以有一张表来跟踪他们赚取的所有积分和使用的积分(负积分)。
在下个月初,您的工作就是找出第一天赚取的积分中哪些没有在这个月使用过。
第一天赚取的积分数减去他们上个月所用的积分数。如果答案为正数,则他们有一些需要过期的积分。因此,在表中添加一条负积分记录。这将抵消未使用的积分。
接下来的一天,重复这个过程,通过计算第二天赚取的积分减去上个月所有赚取的积分之和,考虑到您昨天创建的带有负积分记录的情况。

1
我觉得这是我一直在尝试使用的方法,但似乎并没有起作用。你能否举个例子来演示一下? - spinon

1

是否考虑为支出添加一个标记?如果未设置标记,则可以在必要时将该支出包含在批次中。如果您使用支出抵消到期日,则设置标记。下一次通过时,您将忽略该支出,因为已设置标记。


谢谢您提醒我,我想我在帖子中漏掉了一点细节。现在让我补充一下。 - spinon

1
使用借方记录正常支出。当每月批处理作业运行时,它可以计算小于或等于到期信用的总借方。如果有要到期的信用,只需插入适当的借方记录(适当意味着在您的应用程序中取消多余的部分)。通过这种方式,任何仅检查借方和贷方的“累计总额”代码将达到批处理代码预期的相同余额。

我同意并且我稍微提到了一下。但这仍然不能解决我的问题,至少目前我看不出来如何不考虑在批次中已经花费的3个学分。虽然我认为这方面有些问题。此外,我们正在将借方记录写入表格,并且我们也使用此信息更新聚合列。 - spinon

0
关于朱利安的回复(我还不能评论),我正在处理完全相同的问题,朱利安的方法行不通,因为这将导致账户能够变成负数。
如果用户一个月没有使用服务,在8/4时账户余额将为-3,一项活动价值5将使余额达到2,而不是应该达到的5。

0

解决这个问题的一种方法是仅存储交易记录,而不是余额。然后在需要时始终实时计算余额。以下是数据:

Date : Amount : Expiries
7/1 : +5 : 7/31
7/2 : +5 : 8/1
7/2 : -3 : never
7/3 : +5 : 8/2

任何时候的余额都是尚未过期的所有交易的总和。无需运行任何批处理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接