我有upvote和downvote函数,它们正在执行事务,并正确地操作我的体育球员名字数据库中的票数。
投票结果为1和-1。然后进行数学运算,将玩家的票数总计,并将其作为投票
放入数据库
每次投票时,我都希望一个函数或一段代码来查看players
中的所有名字,并为每个名字分配一个数字,描述他们在数据库中每个人中的排名(根据他们的投票从多到少)(即。詹姆斯有10张支持票和0张支持票(票=10
),他排名第一。约翰有10张赞成票和1张反对票(票=9
),排名第二。如果我投约翰一票,我应该刷新页面,看到他们是1平。这在一定程度上适用于我下面的当前代码,但是一旦我开始通过输入添加更多的名字,并且做一些向上投票、向下投票和收回我的投票,voteCount变量就会变得异常,排名也会偏离轨道。我相信有一个更容易或更好的方法来做这件事。
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;
})
})
下面是我完整的upvote函数,仅供参考。我把上面的代码放在下面的//ranking functionaly
注释中。在该位置,无论何时投出有效的一票,排名代码都将运行。我也会在downvote函数中放入相同的代码。
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.")
}
}
正如我所说的,upvote功能运行良好。我只是在寻找一些关于排名功能的建议,我正在苦苦挣扎。我很感谢任何帮助,并可以提供任何其他相关代码
因此如果数据在事务解析之前发生更改,则事务可以在完成之前运行多次。这会导致作用域外的任何变量不同步(即rankcount
和prevplayervots
)。另一个原因可能是您在OrderedPlayersRank
上进行循环,并为对Transaction
的每次调用返回一个Promise
。这将导致prevplayerrank
和rankcount
同时被读取/修改,而不是像我想的那样依次读取/修改。
一种解决方案可以是在列表上使用OrderByChild('votes')
,并使用与检查前一个值配对的索引来确定显示时的排名,或者在更改投票时设置排名(通过Firebase函数或观察者)。
例如(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)
})
])
})
使用这种方法,您将需要将新创建的玩家的等级设置为最高等级。希望这有帮助!
我想通过像delete*这样的查询删除整个节点,其中user_id=“-KTruPWrYO9WFj-TF8Ft”如何在firebase上实现?
如果子“contacts”的值为“9aIMkiMa0bSuMLjUk3R5bLpnoQS2”,我想从子“Group”中检索文本“Private Group”。我还想检查父子“问题帖子”的其他子节点是否具有相同的值。我一直在努力,但没有成功。这是我一直在使用的代码,但它只产生了错误。
问题内容: 我正在尝试读取xml文件,例如: 这是我到目前为止的代码: 这是我尝试编写此代码的尝试,怎么说都不成功,这就是我开始赏金的原因。这是http://pastebin.com/huKP4KED。 赏金更新: 我确实真的尝试了好几天,但现在没想到会这么难,我会接受有用的链接/书籍/教程,但更喜欢代码,因为我昨天需要这样做。 这是我需要的: 关于上面的xml: 我需要获取标题ID的值 temp
我想到了这个结构来将数据写入Firebase服务器。然而,我在实际代码中有复杂的情况,以这种方式编写结构。 null 这是我试图更新节点的函数。我在这里的思考过程是--我首先将计划标题和UID设置为要创建的自动ID。然后,我尝试引用auto ID创建的“键”,然后尝试存储all_images和all_dates,并使用对childByAutoID调用创建的相同键的引用来存储,然后更新这些值。 对不
我想在Android Studio中获取isSeen节点的值。M6F2mJjQ8uGPXAynZzV是消息的id,并将消息更改为消息。我想在适配器类中获得这个值。
我想递归地连接一个节点的参数值和它的父节点的相同参数值。 例如,如下: 应该成为 我试过了 有什么问题吗?