4

これはかなり複雑な質問ですが、できるだけ簡単かつ簡潔に説明しようとします...

Firebase を使用して、マルチユーザーの Web ベースのゲームを構築しています。ゲームのすべてのラウンドのリストを保持しています。ラウンドの最後に、次のラウンドを開始する準備ができたときにクリックする「開始」ボタンがすべてのユーザーに表示されます。少なくとも 50% のユーザーが「開始」をクリックすると、ラウンドが開始されます。

gameRefゲームの Firebase リファレンスroundListRef、ラウンドのリストを表すリファレンス、およびroundRef現在のラウンドを表すリファレンスがあります。

新しいラウンドが追加されたときに全員の現在のラウンドになるように、child_addedコールバックを添付しました。roundListRef

roundListRef.on('child_added', function(childSnapshot, prevChildName) {
    roundRef = childSnapshot.ref();
});

そこから 50% を簡単に追跡newRoundVotesして計算できます。activePlayers50% に達すると、新しいラウンドが追加され、全員のchild_addedイベントがトリガーされ、そこから新しいラウンドが開始されます...

gameRef.child('newRoundVotes').on('value', function(snapshot) {
    var newRoundVotes = snapshot.val();

    gameRef.child('activePlayers').once('value', function(snapshot) {
        var activePlayers = snapshot.val();

        if (newDriveVotes / activePlayers >= 0.5)
            addNewRound();
    });
});

私の質問は、新しいラウンドが 1 つだけ追加され、全員が同じラウンドに参加していることを確認するにはどうすればよいですか?

たとえば、10 人のプレイヤーがいて、4 人が次のラウンドの開始に投票したとします。5 番目のプレイヤーからイベントがトリガーされる前に 6 番目のプレイヤーが投票した場合、6 番目のプレイヤーchild_addedのラウンドも追加されます。

.set()問題はvsに似て.transaction()いますが、まったく同じではありません (私の理解から)。

誰にも解決策がありますか?

4

2 に答える 2

6

ラウンド名が事前にわかっていれば、トランザクションでこれを解決できる可能性が高いと思います。たとえば、/round/0、/round/1、/round/2 などを使用する場合。

次に、次のようなコードを作成できます。

function addNewRound() {
    var currentRound = Number(roundRef.name());
    var nextRound = currentRound + 1;

    // Use a transaction to try to create the next round.
    roundRefList.child(nextRound).transaction(function(newRoundValue) {
        if (newRoundValue == null) {
            // create new round.
            return { /* whatever should be stored for the round. */ };
        } else {
            // somebody else already created it.  Do nothing.
        }
    });
}

これはあなたのシナリオで機能しますか?

于 2012-08-02T22:35:06.367 に答える
1

考え方を少し変更して、同時実行を追跡する場所としてラウンド カウンターを使用できます。

currentRound = 0;
currentRoundRef.on('value', function(snapshot) {
   currentRound = snapshot.val();
   roundRef = roundListRef.child(currentRound);
});

function addNewRound() {
    currentRoundRef.transaction( function(current_value) {
       if( current_value !== currentRound ) {
          // the round timer has been updated by someone else
          return;
       }
       else {
          return currentRound + 1;
       }
    }, function(success) {
       // called after our transaction succeeds or fails
       if( success ) {
          roundListRef.child(currentRound+1).set(...);
       }
    });
}
于 2012-08-02T22:40:14.110 に答える