第5章 今天的瓶子已经用完啦 - nswbmw/N-drifter GitHub Wiki
我们在玩漂流瓶的时候,会遇到瓶子用完的情况,下面我们来实现这个功能。
我们设定:每个用户一天只能扔 10 个瓶子,捡 10 个瓶子。
今天扔瓶子的机会已经用完啦~
首先我们来实现限制扔瓶次数的功能。打开 redis.js ,添加如下代码:
// 检查用户是否超过扔瓶次数限制
function checkPickTimes(owner, callback) {
pool.acquire(function (err, client) {
if (err) {
return callback({code: 0, msg: err});
}
// 到2号数据库检查用户是否超过扔瓶次数限制
client.SELECT(2, function() {
// 获取该用户捡瓶次数
client.GET(owner, function (err, result) {
if (result >= 10) {
return callback({code: 0, msg: "今天扔瓶子的机会已经用完啦~"});
}
// 捡瓶次数加 1
client.INCR(owner, function() {
// 检查是否是当天第一次扔瓶子
// 若是,则设置记录该用户扔瓶次数键的生存期为 1 天
// 若不是,生存期保持不变
client.TTL(owner, function (err, ttl) {
if (ttl === -1) {
client.EXPIRE(owner, 86400, function () {
// 释放连接
pool.release(client);
});
} else {
// 释放连接
pool.release(client);
}
callback({code: 1, msg: ttl});
});
});
});
});
});
}
将:
exports.throw = function(bottle, callback) {
throwOneBottle(bottle, function (result) {
callback(result);
});
}
修改为:
exports.throw = function(bottle, callback) {
checkThrowTimes(bottle.owner, function (result) {
if (result.code === 0) {
return callback(result);
}
throwOneBottle(bottle, function (result) {
callback(result);
});
});
}
我们将记录用户扔瓶次数的键(字符串类型)保存到了 2 号数据库。
以上代码的意思是:在用户扔瓶子前,首先到 2 号数据库中检查该用户对应的值(即扔瓶次数)是否超过 10 。如果超过 10 ,返回错误信息,如果没有超过 10 ,则将该用户对应的扔瓶次数加 1 ,并设置用户键的生存期。
Redis 的 TTL 命令是以秒为单位,返回给定 key 的剩余生存时间,若没有设置生存时间则返回 -1 。若 ttl 为 -1 ,则说明该用户今天第一次扔瓶子,则设置该用户对应 key 的生存期为 1 天,若 ttl 不为 -1 说明该用户不是今天第一次扔瓶子,则生存期不做改变。
今天捡瓶子的机会已经用完啦~
现在我们来实现限制用户捡瓶次数的功能。
同理,打开 redis.js ,添加如下代码:
// 检查用户是否超过捡瓶次数限制
function checkPickTimes(owner, callback) {
pool.acquire(function (err, client) {
if (err) {
return callback({code: 0, msg: err});
}
// 到 3 号数据库检查用户是否超过捡瓶次数限制
client.SELECT(3, function() {
// 获取该用户捡瓶次数
client.GET(owner, function (err, result) {
if (result >= 10) {
return callback({code: 0, msg: "今天捡瓶子的机会已经用完啦~"});
}
// 捡瓶次数加 1
client.INCR(owner, function() {
// 检查是否是当天第一次捡瓶子
// 若是,则设置记录该用户捡瓶次数键的生存期为 1 天
// 若不是,生存期保持不变
client.TTL(owner, function (err, ttl) {
if (ttl === -1) {
client.EXPIRE(owner, 86400, function () {
// 释放连接
pool.release(client);
});
} else {
// 释放连接
pool.release(client);
}
callback({code: 1, msg: ttl});
});
});
});
});
});
}
将:
exports.pick = function(info, callback) {
// 20% 概率捡到海星
if (Math.random() <= 0.2) {
return callback({code: 1, msg: "海星"});
}
pickOneBottle(info, function (result) {
callback(result);
});
}
修改为:
exports.pick = function(info, callback) {
checkPickTimes(info.user, function (result) {
if (result.code === 0) {
return callback(result);
}
// 20% 概率捡到海星
if (Math.random() <= 0.2) {
return callback({code: 1, msg: "海星"});
}
pickOneBottle(info, function (result) {
callback(result);
});
});
}
这里我们使用 3 号数据库存储每个用户捡瓶的次数。
现在,我们完成了限制用户扔瓶子和捡瓶子次数的功能。