Firebaseで子ノードの値を監視し、数値ランクを割り当てる

アイドルハンド

スポーツ選手の名前のデータベースでトランザクションを実行し、投票数を正しく操作する賛成票と反対票の関数があります。

投票は1と-1としてキャストされます。次に、計算が行われ、プレーヤーの投票数が合計され、データベースに次のように配置されます。votes

db

投票が行われるたびに、関数またはコードですべての名前を調べてplayers、データベース内の全員のランクを表す番号を各名前に割り当てます(投票の多いものから少ないものへ)(つまり、ジェームズは10票と0票(votes = 10)、ランク1です。ジョンは10票と1票()でランク2です。ジョンに賛成したvotes = 9場合は、ページを更新して、1で結ばれていることを確認する必要があります。以下の現在のコードで学位を取得していますが、入力を介して名前を追加し、賛成票、反対票、撤回を行うと、voteCount変数はすべて奇抜になり、ランクはコースから大きく外れます。これを行うためのより簡単な、またはより良い方法。

OrderedPlayersRankは、プレーヤーをvotes、最初に最高、最後に最悪で並べ替える配列ですしたがって、私の#1ランクの人は、orderedPlayersRank配列の最初に常にある必要があります。

global vars

let prevPlayerVotes = 0
let rankCount = 1

      //RANKING CODE    

      //orderedPlayersRank sorts players from highest votes to lowest

      orderedPlayersRank.map((player) => {
      this.database.child(player.id).transaction(function(player){
      if (player.votes >= prevPlayerVotes) {
          prevPlayerVotes = player.votes
          player.rank = rankCount
      } else if (player.votes < prevPlayerVotes) {
          rankCount++
          player.rank = rankCount
          prevPlayerVotes = player.votes
      } else {
          console.log("Rank calculation error.")
      }
      return player;
   })
})

参考までに、これが私の完全な賛成関数です。私は上記のコードを//ranking functionality下の方にコメントがあるところに置いています。その場所では、有効な投票が行われるたびにランキングコードが実行されます。反対票関数にも同じコードを入れます。

upvotePlayer(playerId) {
const players = this.state.players;

const orderedPlayersRank = _.orderBy(players, ['votes'], ['desc'])
if (this.state.user) {
    let ref = firebase.database().ref('/players/' + playerId + '/voters');
    ref.once('value', snap => {
        var value = snap.val()
        if (value !== null) {
            ref.child(this.uid).once('value', snap => {
                if (snap.val() === 0 || snap.val() == null) {
                    ref.child(this.uid).set(1);
                    this.database.child(playerId).transaction(function(player) {
                        if (player) {
                            player.votes++
                        }
                        return player;
                    })
                } else if (snap.val() === -1) {
                    ref.child(this.uid).set(1);

                    //Added vote balancing 
                    this.database.child(playerId).transaction(function(player) {
                        if (player) {
                            player.votes++
                                player.votes++
                        }
                        return player;
                    })
                } else if (snap.val() === 1) {
                    ref.child(this.uid).set(0);

                    //Added vote balancing
                    this.database.child(playerId).transaction(function(player) {
                        if (player) {
                            player.votes--
                        }
                        return player;
                    })
                } else {
                    console.log("Error in upvoting. snap.val(): " + snap.val())
                }
            })
        } else {
            ref.child(this.uid).set(1);
            this.alertUpVote()
            //Added vote balancing
            this.database.child(playerId).transaction(function(player) {
                if (player) {
                    player.votes++
                        console.log("Player added")
                }
                return player;
            })
        }
    });
//ranking functionality here
} else {
    this.alertNotLoggedIn()
    console.log("Must be logged in to vote.")
}
}

私が言ったように、賛成票機能はうまく機能しています。苦労しているランキング機能についてのアドバイスを探しています。私はどんな助けにも感謝し、他の関連するコードを提供することができます

ブライアン・マソス

したがって、トランザクションが解決される前にデータが変更された場合、トランザクションは完了する前に複数回実行できますこれにより、スコープ外の変数(rankCountおよびprevPlayerVotesが同期しなくなる可能性がありますもう1つの理由は、をループしてorderedPlayersRankPromiseへの呼び出しごとにを返すことである可能性がありますtransactionこれによりprevPlayerRankrankCount期待どおりに順番にではなく、同時に読み取り/変更されます。

1つの解決策はorderByChild('votes')、リストで使用し、前の値をチェックすることと組み合わせてインデックスを使用して、表示時にランクを決定するか、投票に変更が加えられたときにランクを設定することです(Firebase Functionまたはウォッチャーのいずれかによって)。

(Firebase機能)

export var rank = functions.database.ref('players/{playerId}/votes')
.onUpdate((change, context) => {
  // list by 'votes' in ascending order
  var orderedListRef = change.after.ref.root.child('players').orderByChild('votes')
  var oldVotes = change.before.val()
  var newVotes = change.after.val()
  var notChanged = 0
  var changeRank = 0
  // went higher in the list so bump every player passed by 1
  if (newVotes > oldVotes) {
    // Range: [oldVotes, newVotes]
    orderedListRef = orderedListRef.startAt(oldVotes).endAt(newVotes)
    changeRank = 1
    notChanged = newVotes
  } else {// went lower in the list so bump every player passed by -1
    // Range: [newVotes, oldVotes]
    orderedListRef = orderedListRef.startAt(newVotes).endAt(oldVotes)
    changeRank = -1
    notChanged = oldVotes
  }
  return orderedListRef.once('value')
  .then((ss) => {
    var promises = []
    var playersPassed = 0
    // IMPORTANT: must use `forEach` to ensure proper order
    ss.forEach((playerSS) => {
      if (playerSS.key === context.params.playerId) {
        return
      }
      playersPassed += 1
      if (playerSS.child('votes').val() === notChanged) {
        return
      }
      // use transaction to ensure proper number of bumps if multiple changes at once
      promises.push(playerSS.child('rank').ref.transaction((rank) => {
        return rank + changeRank
      }))
    })
    // use transaction to adjust rank by players passed
    promises.push(change.before.ref.parent.child('rank')
    .transaction((rank) => {
      return rank - playersPassed * changeRank
    }))
    return Promise.all(promises)
  })
})

初期化の例

export var initRank = functions.database.ref('players/{playerId}/votes')
.onCreate((snapshot, context) => {
  // list by 'votes' in ascending order
  return Promise.all([
    snapshot.ref.root
      .child('players')
      .orderByChild('votes')
      .startAt(snapshot.val())
      .once('value')
      .then((ss) => {
        return snapshot.ref.parent.child('rank').transaction((rank) => {
          if (rank) {
            return rank + ss.numChildren
          }
          return ss.numChildren
        })
      }),
    snapshot.ref.root
      .child('players')
      .orderByChild('votes')
      .endAt(snapshot.val()-1)
      .once('value')
      .then((ss) => {
        var promises = []
        ss.forEach((playerSS) => {
          promises.push(playerSS.child('rank').ref.transaction((rank) => {
            if (rank) {
              return rank + 1
            }
          })
        })
        return Promise.all(promises)
      })
  ])
})

このアプローチでは、新しく作成されたプレーヤーのランクを最高ランクに設定する必要があります。お役に立てれば!

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

監視可能なHTTPリクエストのサブスクライブから角度コンポーネントの変数に値を割り当てる

分類Dev

Swiftの複数のノードでFirebaseの子の値の変化を監視するにはどうすればよいですか?

分類Dev

コマンドラインでバーを使用して複数の変数に値を割り当てる方法

分類Dev

Firebaseノードのすべての子を読み取り、変更を監視する方法

分類Dev

Angular 8.コンストラクターのサービスプロパティに監視可能な値を割り当てる方法は?

分類Dev

ドロップダウンメニューを使用して、ノックアウトのある変数に値を割り当てます

分類Dev

Firebase Androidで、子ノードの値を取得してブール変数に保存します

分類Dev

ノードreplでの奇妙な(let)変数割り当て動作-値を割り当てられません

分類Dev

Type ScriptAngularでクラスのメンバー変数に値を割り当てる方法

分類Dev

「予期しないトークン:識別子エラー」-phpコードからjavascript関数にphpjson配列型変数値を割り当てます

分類Dev

パンダで複数の値に値を割り当てる方法

分類Dev

AngularJSで変数の値の変更を子コントローラーから親コントローラーに割り当てる方法は?

分類Dev

C#XMLドキュメントクラスを使用して子ノード値を変更する

分類Dev

WPFTreeViewの[イベント]をクリックして選択した子ノードの値を取得する

分類Dev

Firebase(swift)で子ノードの値を取得し、ViewControllerのラベルに表示する方法

分類Dev

ビルドメソッド中にJavaクラスのArrayListメンバー変数に値を割り当てるにはどうすればよいですか?

分類Dev

Linq toXMLを使用してXMLの複数の同一ノードの子ノードの値を取得する方法

分類Dev

RESTAPIを使用してFirebaseで複数の子ノードを取得する

分類Dev

標準コンストラクターを使用したVector3への割り当て時に数値の絶対値のみを取得する

分類Dev

C#を使用してxmlで特定の子ノード値を取得する方法

分類Dev

クラスC ++で変数の値を割り当てます

分類Dev

カンマ区切りの文字列で監視可能な配列のすべてのフィールド値を選択します

分類Dev

変数の初期化なしでmallocを使用してCポインターに値を割り当てる

分類Dev

クラス内の変数に型/値を割り当てる方法

分類Dev

数値で始まる列の値にブール値を割り当てる

分類Dev

コンストラクターを使用してクラス関数に値を割り当てることができません

分類Dev

関数内のクラスメンバーに値を割り当てます

分類Dev

selectメソッドでインスタンス名を使用してクラスインスタンスメンバーに値を割り当てる方法

分類Dev

Angularは、繰り返しなしで複数の値を監視します

Related 関連記事

  1. 1

    監視可能なHTTPリクエストのサブスクライブから角度コンポーネントの変数に値を割り当てる

  2. 2

    Swiftの複数のノードでFirebaseの子の値の変化を監視するにはどうすればよいですか?

  3. 3

    コマンドラインでバーを使用して複数の変数に値を割り当てる方法

  4. 4

    Firebaseノードのすべての子を読み取り、変更を監視する方法

  5. 5

    Angular 8.コンストラクターのサービスプロパティに監視可能な値を割り当てる方法は?

  6. 6

    ドロップダウンメニューを使用して、ノックアウトのある変数に値を割り当てます

  7. 7

    Firebase Androidで、子ノードの値を取得してブール変数に保存します

  8. 8

    ノードreplでの奇妙な(let)変数割り当て動作-値を割り当てられません

  9. 9

    Type ScriptAngularでクラスのメンバー変数に値を割り当てる方法

  10. 10

    「予期しないトークン:識別子エラー」-phpコードからjavascript関数にphpjson配列型変数値を割り当てます

  11. 11

    パンダで複数の値に値を割り当てる方法

  12. 12

    AngularJSで変数の値の変更を子コントローラーから親コントローラーに割り当てる方法は?

  13. 13

    C#XMLドキュメントクラスを使用して子ノード値を変更する

  14. 14

    WPFTreeViewの[イベント]をクリックして選択した子ノードの値を取得する

  15. 15

    Firebase(swift)で子ノードの値を取得し、ViewControllerのラベルに表示する方法

  16. 16

    ビルドメソッド中にJavaクラスのArrayListメンバー変数に値を割り当てるにはどうすればよいですか?

  17. 17

    Linq toXMLを使用してXMLの複数の同一ノードの子ノードの値を取得する方法

  18. 18

    RESTAPIを使用してFirebaseで複数の子ノードを取得する

  19. 19

    標準コンストラクターを使用したVector3への割り当て時に数値の絶対値のみを取得する

  20. 20

    C#を使用してxmlで特定の子ノード値を取得する方法

  21. 21

    クラスC ++で変数の値を割り当てます

  22. 22

    カンマ区切りの文字列で監視可能な配列のすべてのフィールド値を選択します

  23. 23

    変数の初期化なしでmallocを使用してCポインターに値を割り当てる

  24. 24

    クラス内の変数に型/値を割り当てる方法

  25. 25

    数値で始まる列の値にブール値を割り当てる

  26. 26

    コンストラクターを使用してクラス関数に値を割り当てることができません

  27. 27

    関数内のクラスメンバーに値を割り当てます

  28. 28

    selectメソッドでインスタンス名を使用してクラスインスタンスメンバーに値を割り当てる方法

  29. 29

    Angularは、繰り返しなしで複数の値を監視します

ホットタグ

アーカイブ