javascript 为测序数据添加另一层验证

4xrmg8kj  于 2023-03-11  发布在  Java
关注(0)|答案(1)|浏览(107)

bounty将于明天到期。回答此问题可获得+50的声望奖励。Ulquiorra Schiffer希望吸引更多人关注此问题。

我正在创建一个匹配功能,其中2名球员具有相同的重量将配对。
它目前正在基于相同的权重工作。现在,我的目标是,为每个匹配添加一个序列。例如。

  • 如果 * 玩家1* 在第一场比赛,那么玩家1的下一场比赛应该在第四场或第六场比赛。玩家的每一场比赛应该有最少3个和最多6个差距之前,该特定的球员可以再次匹配。

我已经在下面提供了我的当前输出和目标输出。

const source = [
        {
            entryID: 1,
            entryName: "player1",
            weight: 1900,
            class:[],

        }, 
        {
            entryID: 2,
            entryName: "player1",
            weight: 1900,
            class:[],

        },
        {
            entryID: 3,
            entryName: "player2",
            weight: 1900,
            class:[],
        },
        {
            entryID: 4,
            entryName: "player3",
            weight: 1900,
            class:[],
        },
        {
            entryID: 5,
            entryName: "player4",
            weight: 1900,
            class:[],
        },
        {
            entryID: 6,
            entryName: "player5",
            weight: 1900,
            class:[],
        },
        {
            entryID: 7,
            entryName: "player6",
            weight: 1900,
            class:[],
        },
        {
            entryID: 8,
            entryName: "player7",
            weight: 1900,
            class:[],

        },
        {
            entryID: 9,
            entryName: "player8",
            weight: 1900,
            class:[],
        },
        {
            entryID: 10,
            entryName: "player9",
            weight: 1900,
           class:[],
        },
        {
            entryID: 11,
           entryName: "player10",
            weight: 1900,
            class:[],
        },
        {
            entryID: 12,
           entryName: "player11",
            weight: 1900,
              class:[],
        },
        {
            entryID: 13,
           entryName: "player12",
            weight: 1900,
            class:[],
        },
        {
            entryID: 14,
           entryName: "player1",
            weight: 1900,
            class:[],
        },

    ];

console.log(combine(source))

function combine(data = [], different = 0, maxGroupSize = 2) {
    const groups = [], related = [], sortedData = [...data].sort((a, b) => a.weight - b.weight),
        alreadyInRela = (setX, eName) => {
            let list = [...setX, eName]
            return related.some(rela => list.every(l => rela.has(l)))
        };
    
    sortedData.forEach((el, indx) => {
        let place = groups.findIndex( // find a place in a group forEach element, use indx as track
            g => g.names.size < maxGroupSize              // is the group incomplete ?
                && !g.names.has(el.entryName)             // is entryName not in the group list (names Set) ?
                && (el.weight - g.weight) <= different
                && !alreadyInRela(g.names, el.entryName) // is (entryName + group list) does not already used ?
                && el.class.every(c => !g.usedClasses.has(c)) // check class
        )

        if (place < 0) { // not found -> create new group
            let names = new Set().add(el.entryName)                      // create new group
            groups.push({ names, indxs: [indx], weight: el.weight, usedClasses: new Set(el.class) })  // group constitutive info 
            related.push(names)                                      // keep track of group list
        } else { // find a place in a group
            groups[place].names.add(el.entryName)  // related list is also updated
            el.class.forEach(c => groups[place].usedClasses.add(c)) // add classes
            groups[place].indxs.push(indx)        // add indx to retreive element in sortedData 
        }
    });

    return groups.reduce((r, g, i) => { // build result
        if (g.indxs.length > 1) {
            let key = `${i}_` + g.indxs.map(x => sortedData[x].weight).join('_')
            r[key] = []
            g.indxs.forEach(x => r[key].push(sortedData[x]))
        }
        return r
    }, {})
}

当前结果:

{
  0_1900_1900: [{ // 1st match
  class: [],
  entryID: 1,
  entryName: "player1",
  weight: 1900
}, {
  class: [],
  entryID: 3,
  entryName: "player2",
  weight: 1900
}],
  1_1900_1900: [{ // 2nd match (As we can see here, player 1 has been matched again. There should be 3-6 matches before this player can be matched again)
  class: [],
  entryID: 2,
  entryName: "player1",
  weight: 1900
}, {
  class: [],
  entryID: 4,
  entryName: "player3",
  weight: 1900
}],
  2_1900_1900: [{ // 3rd match
  class: [],
  entryID: 5,
  entryName: "player4",
  weight: 1900
}, {
  class: [],
  entryID: 6,
  entryName: "player5",
  weight: 1900
}],
  3_1900_1900: [{ // 4th match
  class: [],
  entryID: 7,
  entryName: "player6",
  weight: 1900
}, {
  class: [],
  entryID: 8,
  entryName: "player7",
  weight: 1900
}],
  4_1900_1900: [{ // 5th match
  class: [],
  entryID: 9,
  entryName: "player8",
  weight: 1900
}, {
  class: [],
  entryID: 10,
  entryName: "player9",
  weight: 1900
}],
  5_1900_1900: [{ // 6th match
  class: [],
  entryID: 11,
  entryName: "player10",
  weight: 1900
}, {
  class: [],
  entryID: 12,
  entryName: "player11",
  weight: 1900
}],
  6_1900_1900: [{ // 7th match
  class: [],
  entryID: 13,
  entryName: "player12",
  weight: 1900
}, {
  class: [],
  entryID: 14,
  entryName: "player1",
  weight: 1900
}]
}

目标结果:

{
  0_1900_1900: [{// 1st match
  class: [],
  entryID: 1,
  entryName: "player1",
  weight: 1900
}, {
  class: [],
  entryID: 3,
  entryName: "player2",
  weight: 1900
}],
  1_1900_1900: [{ //2nd match
  class: [],
  entryID: 4,
  entryName: "player3",
  weight: 1900
}, {
  class: [],
  entryID: 5,
  entryName: "player4",
  weight: 1900
}],
  2_1900_1900: [{ //3rd match
  class: [],
  entryID: 6,
  entryName: "player5",
  weight: 1900
}, {
  class: [],
  entryID: 7,
  entryName: "player6",
  weight: 1900
}],
  3_1900_1900: [{ //4th match (As we can see here, there are 2 matches before player 1 got matched again. This is my target output)
  class: [],
  entryID: 2,
  entryName: "player1",
  weight: 1900
}, {
  class: [],
  entryID: 8,
  entryName: "player7",
  weight: 1900
}],
  4_1900_1900: [{ //5th match
  class: [],
  entryID: 9,
  entryName: "player8",
  weight: 1900
}, {
  class: [],
  entryID: 10,
  entryName: "player9",
  weight: 1900
}],
  5_1900_1900: [{ //6th match
  class: [],
  entryID: 11,
  entryName: "player10",
  weight: 1900
}, {
  class: [],
  entryID: 12,
  entryName: "player11",
  weight: 1900
}],
  6_1900_1900: [{ //7th match
  class: [],
  entryID: 14,
  entryName: "player1",
  weight: 1900
}, {
  class: [],
  entryID: 13,
  entryName: "player12",
  weight: 1900
}]
}

任何帮助都将不胜感激。谢谢

5jdjgkvh

5jdjgkvh1#

为了给matchmaking函数添加所需的序列验证,您需要跟踪每个玩家的最后一场比赛,并确保满足比赛之间的最小和最大间隔。一种方法是给玩家的对象添加一个额外的属性,以跟踪他们最后一场比赛的索引。然后,在将玩家添加到组之前,可以检查它们的最后匹配的索引,并确保最后匹配和当前匹配之间差距在期望的范围内。
以下是合并函数的一个更新实现,其中包括此排序验证:

function combine(data = [], different = 0, maxGroupSize = 2, minGap = 3, maxGap = 6) {
    const groups = [], related = [], sortedData = [...data].sort((a, b) => a.weight - b.weight),
        alreadyInRela = (setX, eName) => {
            let list = [...setX, eName]
            return related.some(rela => list.every(l => rela.has(l)))
        };
    
    sortedData.forEach((el, indx) => {
        let place = groups.findIndex(
            g => g.names.size < maxGroupSize
                && !g.names.has(el.entryName)
                && (el.weight - g.weight) <= different
                && !alreadyInRela(g.names, el.entryName)
                && el.class.every(c => !g.usedClasses.has(c))
                && (el.lastMatchIndex === undefined || indx - el.lastMatchIndex >= minGap)
                && (el.lastMatchIndex === undefined || indx - el.lastMatchIndex <= maxGap)
        )

        if (place < 0) {
            let names = new Set().add(el.entryName)
            groups.push({ names, indxs: [indx], weight: el.weight, usedClasses: new Set(el.class) })
            related.push(names)
        } else {
            groups[place].names.add(el.entryName)
            el.class.forEach(c => groups[place].usedClasses.add(c))
            groups[place].indxs.push(indx)
        }

        el.lastMatchIndex = indx; // update the last match index for the current player
    });

    return groups.reduce((r, g, i) => {
        if (g.indxs.length > 1) {
            let key = `${i}_` + g.indxs.map(x => sortedData[x].weight).join('_')
            r[key] = []
            g.indxs.forEach(x => r[key].push(sortedData[x]))
        }
        return r
    }, {})
}

我在函数中添加了两个新参数minGap和maxGap,它们分别控制匹配之间的最小和最大间隔。我还在每个球员对象中添加了一个新属性lastMatchIndex,它跟踪他们最后一次匹配的索引。该函数在将球员添加到组之前检查最后一次匹配索引,并确保最后一次匹配和当前匹配之间差距在所需的范围内。
通过这些更改,函数应根据最小和最大间隙参数生成所需的匹配序列。

相关问题