Modnar's Zone

SomeCode

字数统计: 586阅读时长: 2 min
2024/12/25

场景记录

累积活跃度奖励

场景概述

给定某 N 个槽位用于领奖(比如累积活跃度奖励),支持按周增量更新配置奖励内容及奖励条件。

配置结构

reward_id from_week_id need_active_num rewards
1 1 2 aaa
2 1 4 bbb
3 1 8 ccc
4 1 16 ddd
5 1 32 eee
6 1 64 fff
2 5 4 bbb’

详细说明

有 6 个奖励项(N = 6),每个奖励项从第一周开始存在奖励配置。例如第一周开始,要求 reward_id(1) 的奖励项达成条件是 need_active_num 达到 2;reward_id(3) 的奖励达成条件是 need_active_num 达到 8。从第 5 周开始,奖励项 reward_id(2) 的奖励条件由 need_active_num 的 4 保持为 4,而奖励发生了变更。如何支持配置的索引结构来高效支持这样的频繁查询?需要支持至少以下两种功能接口:

  • const WeeklyActiveRewardConf *GetWeeklyActiveRewardConf(std::uint32_t reward_id, std::uint32_t week_id) 按照给定周的给定奖励项,获取得到相应的奖励项配置。

  • const std::vector<const WeeklyActiveRewardConf *> &GetWeeklyActiveRewardConf(std::uint32_t week_id) 按照给定周来获取当前周所有的奖励项配置。比如上述从第五周开始,调用此方法得到的配置项的奖励列表应当是 aaabbb'cccdddeeefff

实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
static const std::uint32_t max_reward_num = 6U;
for (const auto &reward_conf : WeeklyActiveRewardConfVector::GetInst().GetConfAll())
{
if (weekly_active_reward_conf_.find(reward_conf.from_week_id) == weekly_active_reward_conf_.end())
{
weekly_active_reward_conf_[reward_conf.from_week_id] =
std::vector<const WeeklyActiveRewardConf *>(max_reward_num, nullptr);
}
CHECK_EXP_ELOG(reward_conf.reward_id <= 0U || reward_conf.reward_id > max_reward_num, continue,
"invalid reward_id|must from 0 to %u|reward_id:%u", max_reward_num, reward_conf.reward_id);
weekly_active_reward_conf_[reward_conf.from_week_id][reward_conf.reward_id - 1UL] = &reward_conf;
}
for (auto iter = weekly_active_reward_conf_.begin(); iter != weekly_active_reward_conf_.end(); ++iter)
{
for (std::size_t i = 0UL; i < iter->second.size(); ++i)
{
CHECK_EXP(iter->second[i] != nullptr, continue);
if (iter == weekly_active_reward_conf_.begin())
{
ERR_LOG(0UL, "no reward config|week_id:%u|reward_id:%zu", iter->first, i + 1UL);
return false;
}
else
{
iter->second[i] = std::prev(iter)->second[i];
}
}
}

利用这样的缓存的 weekly_active_reward_conf_ 数据,可以满足上述需求。对此的两个接口定义为:

1
2
3
4
5
6
7
8
9
const WeeklyActiveRewardConf *GetWeeklyActiveRewardConf(std::uint32_t reward_id, std::uint32_t week_id) const
{
COND_RET(weekly_active_reward_conf_.empty(), nullptr);
auto iter = weekly_active_reward_conf_.upper_bound(week_id);
COND_RET(iter == weekly_active_reward_conf_.begin(), nullptr);
const auto &conf_vec = std::prev(iter)->second;
COND_RET(reward_id <= 0 || reward_id > conf_vec.size(), nullptr);
return conf_vec[reward_id - 1U];
}
1
2
3
4
5
6
7
8
const std::vector<const WeeklyActiveRewardConf *> &GetWeeklyActiveRewardConf(std::uint32_t week_id) const
{
static std::vector<const WeeklyActiveRewardConf *> empty;
COND_RET(weekly_active_reward_conf_.empty(), empty);
auto iter = weekly_active_reward_conf_.upper_bound(week_id);
COND_RET(iter == weekly_active_reward_conf_.end(), empty);
return std::prev(iter)->second;
}
CATALOG
  1. 1. 场景记录
    1. 1.1. 累积活跃度奖励
      1. 1.1.1. 场景概述
      2. 1.1.2. 配置结构
      3. 1.1.3. 详细说明
      4. 1.1.4. 实现代码