Pregunta

Estoy implementando un juego de ajedrez social.Cada usuario puede crear un nuevo juego y esperará hasta que el sistema encuentre un oponente para él.

Cuando el usuario crea un juego, especifica restricciones:el color que les gustaría jugar y el rating mínimo de ajedrez del oponente.

Los oponentes pueden igualar o no igualar. Por ejemplo, se enfrentarán los siguientes dos oponentes:

// User 1 with rating 1700              // User 2 with rating 1800
// creates this game                    // creates this game
game: {                                 game: { 
  color: 'white',                         minRating: 1650
  minRating: 1600                       }
}                                       // User did not specify a preferred color,
                                        // meaning they do not care which color to play

Entonces, si el Usuario 1 es el primer usuario en el sistema y creó su juego, esperará.Una vez que el Usuario 2 crea su juego, debe coincidir inmediatamente con el Usuario 1.

Por otro lado, los siguientes dos oponentes no coincidirán porque ambos quieren jugar con blancas.En este caso, ambos deberían esperar hasta que alguien más cree un juego con color: 'black' (o color no especificado), y minRating que coincidiera con los requisitos.

// User 1 with rating 1700              // User 2 with rating 1800
// creates this game                    // creates this game
game: {                                 game: { 
  color: 'white',                         color: 'white'  
  minRating: 1600                         minRating: 1650
}                                       }

Mis preocupaciones estaban relacionadas con escenarios en los que miles de usuarios crean nuevos juegos al mismo tiempo.¿Cómo me aseguro de emparejar a mis oponentes sin crear puntos muertos?es decir.¿Cómo evito escenarios en los que el Usuario 1, el Usuario 2 y el Usuario 3 intentan encontrar un oponente al mismo tiempo y sus algoritmos de coincidencia devuelven el Usuario 99?¿Cómo me recupero de este escenario, asignando el Usuario 99 solo a uno de ellos?

¿Cómo usarías el poder de Firebase para implementar un sistema de comparación de este tipo?

¿Fue útil?

Solución

Es una tarea desafiante en el entorno NOSQL, especialmente si desea que coincida con varios campos

En su caso, configuraría un índice simple por color y dentro del color, almacenaría la referencia al juego con prioridad establecida para minular. De esa manera, puede consultar los juegos por el color preferido con la prioridad de la minoría.

indexes: {
  color:{
     white:{
        REF_WITH_PRIORITY_TO_RATING: true
     },
     black:{
        REF_WITH_PRIORITY_TO_RATING: true
     }
  }
}

Si desea obtener información cada vez que el partido abre el juego:

ref = new(Firebase)('URL');
query =ref.child('color_index/white/').startAt(minPriority);
query.on('child_added',function(snapshot){
  //here is your new game matching the filter
});

Esto, sin embargo, obtendría más complejo si introduce múltiples campos para filtrar los juegos, por ejemplo, dropRate, timeZone, 'GamesPlayed', etc. En este caso, puede anidar los índices más profundo:

indexes: {
  GMT0: {
    color:{
       white:{
          REF_WITH_PRIORITY_TO_RATING: true
       },
       black:{
          REF_WITH_PRIORITY_TO_RATING: true
       },
  }
  GMT1: {
       // etc
  }
}

Otros consejos

La opción obvia para un punto de partida sería el color, ya que este es un requisito exclusivo. Los demás parecen más como resultados ponderados, por lo que aquellos podrían simplemente incrementar o disminuir el peso.

Utilice prioridades para los rangos MIN / MAX, y mantenga cada uno en un "índice" separado. Luego, tome los partidos para cada uno y cree una unión. Considere esta estructura:

/matches
/matches/colors/white/$user_id
/matches/ranking/$user_id (with a priority equal to ranking)
/matches/timezones/$user_id (with a priority of the GMT relationship)

Ahora para consultar, simplemente agarraría los partidos en cada categoría y los clasificaría por el número de coincidencias. Puedo comenzar con colores, porque presumiblemente no es una calificación opcional o relativa:

var rootRef = new Firebase('.../matches');

var VALUE = {
   "rank": 10, "timezone": 5, "color": 0
}

var matches = []; // a list of ids sorted by weight
var weights = {}; // an index of ids to weights

var colorRef = rootRef.child('colors/black');
colorRef.on('child_added', addMatch);
colorRef.child('colors/black').on('child_removed', removeMatch);

var rankRef = rootRef.child('ranking').startAt(minRank).endAt(maxRank);
rankRef.on('child_added', addWeight.bind(null, VALUE['rank']));
rankRef.on('child_removed', removeWeight.bind(null, VALUE['rank']));

var tzRef = ref.child('timezone').startAt(minTz).endAt(maxTz);
tzRef.on('child_added', addWeight.bind(null, VALUE['timezone']));
tzRef.on('child_removed', removeWeight.bind(null, VALUE['timezone']));

function addMatch(snap) {
   var key = snap.name();
   weights[key] = VALUE['color'];
   matches.push(key);
   matches.sort(sortcmp);
}

function removeMatch(snap) {
   var key = snap.name();
   var i = matches.indexOf(key);
   if( i > -1 ) { matches.splice(i, 1); }
   delete weights[key]; 
}

function addWeight(amt, snap) {
   var key = snap.name();
   if( weights.hasOwnProperty(key) ) {
      weights[key] += amt;
      matches.sort(sortcmp);
   }
}

function removeWeight(amt, snap) {
   var key = snap.name();
   if( weights.hasOwnProperty(key) ) {
      weights[key] -= amt;
      matches.sort(sortcmp);
   }
}

function sortcmp(a,b) {
   var x = weights[a];
   var y = weights[b];
   if( x === y ) { return 0; }
   return x > y? 1 : -1;
}

De acuerdo, ahora he dado lo que todos piden en este caso de uso, cómo crear un rudimentario donde la cláusula. Sin embargo, la respuesta apropiada aquí es que las búsquedas deben ser realizadas por un motor de búsqueda. Esto no es simple donde la condición. Esta es una búsqueda ponderada de las mejores coincidencias, ya que los campos como el color no son opcionales o simplemente el partido de mejor , mientras que otros, posteriormente, son la coincidencia más cercana en cualquier dirección, mientras que algunos simplemente afectan La calidad del partido.

Revisa Linterna para una simple integración de la búsqueda de elastics. Con este enfoque, debe poder aprovechar las excelentes herramientas de ponderación de ES, la clasificación dinámica y todo lo demás que necesita para realizar un algoritmo correspondiente.

con respecto a los puntos muertos. No me enfocaría demasiado hasta que tenga cientos de transacciones por segundo (es decir, cientos de miles de usuarios que compiten por coincidencias). Divida el camino donde escribiremos para aceptar una unión y hacer una transacción para asegurarse de que solo una persona logre obtenerla. Manténgalo separado de los datos de lectura para que el bloqueo en esa ruta no disminuya la velocidad de procesamiento. Mantenga la transacción en un tamaño mínimo (un campo único si es posible).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top