【发布时间】:2008-10-13 15:47:22
【问题描述】:
所以我为测验做了一些计时器。问题是,当我放
javascript: alert("blah");
在地址中,弹出警告框暂停我的计时器。这在测验中是非常不受欢迎的。
我认为没有任何方法可以阻止这种行为......但我还是会问。
如果没有,介意建议我该怎么做?
【问题讨论】:
标签: javascript timer
所以我为测验做了一些计时器。问题是,当我放
javascript: alert("blah");
在地址中,弹出警告框暂停我的计时器。这在测验中是非常不受欢迎的。
我认为没有任何方法可以阻止这种行为......但我还是会问。
如果没有,介意建议我该怎么做?
【问题讨论】:
标签: javascript timer
永远不要依赖 javascript(或任何其他客户端时间)来计算在回发或不同页面之间完成的操作所经过的时间。
如果你总是比较服务器日期,人们就很难作弊:
【讨论】:
显然预览渲染与发布的渲染不同。这一段是为了确保接下来的两行显示为代码。
// Preserve native alert() if you need it for something special
window.nativeAlert = window.alert;
window.alert = function(msg) {
// Do something with msg here. I always write mine to console.log,
// but then I have rarely found a use for a real modal dialog,
// and most can be handled by the browser (like window.onbeforeunload).
};
【讨论】:
不,没有办法阻止警报停止 JavaScript 中的单线程。也许您可以使用其他一些用户通知方式,例如浮动层。
【讨论】:
它是模态的并停止执行。考虑一种不会像 Lightbox 技术那样暂停执行的替代方案。
【讨论】:
我认为提问者试图防止作弊。由于用户可以键入 javascript: alert("paused");进入地址栏,或者做一个小书签来做,很容易暂停测验和作弊。
我唯一能想到的是使用 Date() 来获取当前时间,并在计时器触发时再次检查它。然后,如果时间差没有合理地接近预期的计时器持续时间,请发出警告并取消该问题的答案或让他们通过测验。没有办法阻止用户暂停您的测验,但应该可以抓住他们。
当然,通过任何防作弊功能,您都会激励人们成为更好的作弊者。一个人可以在他们的 PC 上更改系统时间,并欺骗从操作系统获取时间的 javascript Date() 构造函数。
您可以使用时间间隔与一秒的时间间隔长度进行重复的时钟比较。间隔处理程序还可以更新用户显示器上的剩余时间字段。然后,随着测验时间的流逝,用户可以感受到压力的增加。欢乐时光!
【讨论】:
关于 SyaZ 问题的反馈循环澄清了相关问题。
这里尝试总结一下到目前为止的好答案:
客户端脚本本质上很容易被操纵以欺骗在线测验。见@Filini 's Server-side approach
window.alert = function(msg) {} 将覆盖 alert() 并且可能会击败放入地址栏的低悬果实:javascript:alert('Pausing页面,以便我可以用谷歌搜索答案')或者我现在使用我的电话朋友。Courtesy of @eyelidlessness
如果您必须使用客户端方法,而不是使用 setTimeOut(),您可以使用自定义的基于日期比较的暂停函数,例如(concept by @Mnebuerquo,我的代码示例(@micahwittman )):
例子:
var beginDate = new Date();
function myTimeout(milsecs){
do { curDate = new Date(); }
while((curDate-beginDate) < milsecs);
}
function putDownYourPencils(milsecs){
myTimeout(milsecs);
var seconds = milsecs / 1000;
alert('Your ' + seconds + ' seconds are up. Quiz is over.');
}
putDownYourPencils(3000);
【讨论】:
最终,您无法信任用户输入。如果不跟踪服务器上经过的时间,就不能保证数据没有被操纵。
但是,如果您确信您的测验者不精通 JavaScript,并且只是依靠他们在某处发现的“技巧”,您可以使用以下代码测试作弊(暂停),这不会' t需要修改window.alert:
var timer = {
startDatetime: null,
startSec: 0,
variance: 1,
exitOnPause: true,
count: function (config) {
var that = this;
if (typeof config == "object" && typeof parseInt(config.seconds) == "number" && !isNaN(parseInt(config.seconds)))
{
if (typeof parseFloat(config.variance) == "number" && !isNaN(parseFloat(config.variance))) this.variance = config.variance;
if (typeof config.exitOnPause == "boolean") this.exitOnPause = config.exitOnPause;
if (config.seconds > 0)
{
if (!this.startSec) this.startSec = config.seconds;
if (!this.startDatetime) this.startDatetime = new Date();
var currentDatetime = new Date();
if (currentDatetime.getTime() - this.startDatetime.getTime() > (this.startSec - config.seconds) * this.variance * 1000)
{
if (typeof config.onPause == "function") config.onPause();
if (!this.exitOnPause)
{
this.startDatetime = new Date();
this.startSec = config.seconds--;
window.setTimeout(function () { that.count(config); }, 1000);
}
}
else
{
config.seconds--;
window.setTimeout(function () { that.count(config); }, 1000);
}
}
else
{
if (typeof config.onFinish == "function") config.onFinish();
}
}
}
};
这个计时器对象有一个方法 count(),它接受一个对象作为输入。它期望输入对象中至少有一个 seconds 属性。
由于某种原因,window.setTimeout 并不总是按预期工作。有时,在我的机器上,应该在 1 秒后执行代码的 window.setTimeout(x, 1000) 花费了 2 秒以上。因此,在这种情况下,您应该允许差异,这样没有作弊的人就不会被标记为作弊者。方差默认为 1,但可以在输入对象中覆盖。下面是如何使用此代码的示例,它允许 2.5 秒的“摆动空间”用于慢戳:
timer.count({
seconds: 10,
onPause: function () { alert("You cheated!"); window.location.replace("cheatersAreBad.html"); },
onFinish: function () { alert("Time's up!"); },
variance: 2.5
});
通过这样的解决方案,您可以使用 Ajax 告诉服务器端脚本用户已暂停计时器或将用户重定向到解释他们被发现作弊的页面。如果出于某种原因,您希望允许用户在被发现作弊后继续参加测验,您可以将 exitOnPause 设置为 false:
timer.count({
seconds: 10,
exitOnPause: false,
onPause: function () { recordCheaterViaAjax(); },
onFinish: function () { alert("Time's up!"); },
variance: 2.5
});
【讨论】:
可以将服务器会话设置为在 1 小时后到期。 javascript 只能用作显示工具,让用户知道还剩多少时间。如果他决定通过暂停计时器来作弊,那么在发布他的测试时他可能会惊讶于他的会话已超时。
【讨论】: