5

そこで、クイズ用のタイマーをいくつか作りました。問題は、私が入れたときに気づいたということです

javascript: alert("blah");

アドレスでは、ポップアップ アラート ボックスがタイマーを一時停止します。これはクイズでは非常に望ましくありません。

この動作を止める方法はないと思います...しかし、とにかく尋ねます。

そうでない場合は、どうすればよいか教えてください。

4

8 に答える 8

10

ポストバック間または異なるページ間で実行された操作の経過時間を計算するために、javascript (またはその他のクライアント側の時間) に決して依存しないでください。

サーバーの日付を常に比較すると、人々が不正行為をするのが難しくなります。

  1. 最初のページ要求、サーバー時刻を保存
  2. N秒ごとにjavascript呼び出しでpingを実行し、2つのサーバー時間を比較して、経過時間を返します(表示用)
  3. ユーザーがフォームを送信すると、2 つのサーバー時間を比較し、経過時間を計算し、時間がかかりすぎたものを破棄します (つまり、不正行為の可能性があります)。
于 2008-10-13T16:58:40.970 に答える
6

どうやらプレビューのレンダリングは、投稿されたレンダリングとは異なります。この段落は、次の 2 行がコードとして表示されるようにするためのものです。

// 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).
};
于 2008-10-13T16:21:10.887 に答える
5

いいえ、アラートが JavaScript の単一スレッドを停止するのを防ぐ方法はありません。おそらく、フローティングレイヤーなど、他の方法でユーザー通知を使用できます。

于 2008-10-13T15:49:20.093 に答える
3

モーダルであり、実行を停止します。ライトボックス手法のように実行を一時停止しない代替案を検討してください。

于 2008-10-13T15:51:49.153 に答える
3

質問者は不正行為を防ごうとしていると思います。ユーザーは javascript を入力できるため、alert("paused"); をアドレス バーに入力するか、ブックマークレットを作成して、クイズを一時停止してカンニングするのは簡単です。

私が考えることができる唯一のことは、Date() を使用して現在の時刻を取得し、タイマーが起動したときにもう一度確認することです。次に、時間差が意図したタイマーの持続時間にかなり近くない場合は、警告を表示してその質問への回答を失格にするか、クイズに失敗させます. ユーザーがクイズを一時停止するのを防ぐ方法はありませんが、ユーザーを捕まえることはできるはずです。

もちろん、チート防止を行うことで、人々がより良い詐欺師になるように動機付けます. PC のシステム時刻を変更し、オペレーティング システムから時刻を取得する javascript Date() コンストラクターをだますことができます。

間隔を使用して、1 秒の間隔の長さに対して繰り返しクロック比較を行うことができます。間隔ハンドラーは、ユーザーのディスプレイ上の残り時間フィールドを更新することもできます。その後、クイズの時間がなくなると、ユーザーはプレッシャーが高まるのを感じることができます。楽しい時間!

于 2008-10-13T16:25:02.660 に答える
2

SyaZ の質問に対するフィードバック ループは、問題となっている問題を明確にしました。

これまでの良い答えを要約する試みは次のとおりです。

  • クライアント スクリプトは、本来、簡単に操作してオンライン クイズをだますことができます。@Filiniのサーバー側のアプローチを見る

  • window.alert = function(msg) {} はalert()をオーバーライドし、おそらくアドレスバーに入力する簡単な方法を無効にします: javascript:alert('Pausing page so I can go the answer') or I'll use my Phone -友達になりました。 @まぶたの礼儀

  • setTimeOut() を使用する代わりに、クライアント側のアプローチを使用する必要がある場合は、次のようなカスタムの日付比較ベースの一時停止関数を使用できます( @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);
于 2008-10-13T20:28:25.583 に答える
2

最終的に、ユーザー入力を信頼することはできません。サーバーでの経過時間を追跡しなければ、データが操作されていないという保証はありません。

ただし、クイズの回答者が JavaScript に精通しておらず、どこかで見つけた「トリック」に頼っているだけであると確信している場合は、次のコードを使用してチート (一時停止) をテストできます。変更は必要ありません。 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() メソッドが 1 つあります。少なくとも、入力オブジェクトに秒のプロパティが必要です。

何らかの理由で、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
});
于 2008-10-13T22:57:06.970 に答える
0

サーバー セッションは、たとえば 1 時間で期限切れになるように設定できます。JavaScript は、ユーザーが残り時間を知るための表示ツールとしてのみ使用できます。タイマーを一時停止して不正行為を行うことにした場合、テストを投稿したときにセッションがタイムアウトしたことに驚かれる可能性があります。

于 2012-06-26T18:16:03.907 に答える