سؤال

أقوم بتنفيذ لعبة شطرنج اجتماعية.يمكن لكل مستخدم إنشاء لعبة جديدة، وسينتظر حتى يجد النظام خصمًا له.

عندما يقوم المستخدم بإنشاء لعبة، فإنه يحدد القيود:اللون الذي يرغبون في لعبه، والحد الأدنى من تصنيف الخصم في الشطرنج.

يمكن للخصوم أن يتطابقوا أو لا يتطابقوا. على سبيل المثال، سوف يتطابق الخصمان التاليان:

// 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

لذلك، إذا كان المستخدم 1 هو المستخدم الأول في النظام، وقام بإنشاء لعبته، فسوف ينتظر.بمجرد قيام المستخدم 2 بإنشاء لعبته، يجب مطابقته على الفور مع المستخدم 1.

على الجانب الآخر، لن يتطابق الخصمان التاليان، لأن كلاهما يريد اللعب باللون الأبيض.في هذه الحالة، يجب على كلاهما الانتظار حتى يقوم شخص آخر بإنشاء لعبة معه color: 'black' (أو اللون غير محدد)، و minRating من شأنها أن تتطابق مع المتطلبات.

// 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
}                                       }

تتعلق مخاوفي بالسيناريوهات التي يقوم فيها آلاف المستخدمين بإنشاء ألعاب جديدة في نفس الوقت.كيف أتأكد من مواجهتي للخصوم دون خلق مآزق؟أي.كيف يمكنني منع السيناريوهات عندما يحاول المستخدم 1 والمستخدم 2 والمستخدم 3 العثور على خصم في نفس الوقت، وترجع خوارزميات المطابقة الخاصة بهم المستخدم 99.كيف يمكنني التعافي من هذا السيناريو، وتخصيص المستخدم 99 لواحد منهم فقط؟

كيف يمكنك استخدام قوة Firebase لتنفيذ نظام المطابقة هذا؟

هل كانت مفيدة؟

المحلول

إنها مهمة صعبة في بيئة NoSQL خاصة إذا كنت تريد مطابقة حقول متعددة

في حالتك، سأقوم بإعداد فهرس بسيط حسب اللون وداخل اللون سأقوم بتخزين المرجع إلى اللعبة مع تعيين الأولوية على minRating.وبهذه الطريقة يمكنك الاستعلام عن الألعاب حسب اللون المفضل مع أولوية minRating.

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

إذا كنت ترغب في الحصول على معلومات عندما تفتح المباراة اللعبة:

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
});

ومع ذلك، قد يصبح الأمر أكثر تعقيدًا إذا قمت بإدخال حقول متعددة لتصفية الألعاب على سبيل المثال dropRate, timeZone, ، "الألعاب التي تم تشغيلها" وما إلى ذلك ...في هذه الحالة، يمكنك تداخل الفهارس بشكل أعمق:

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

نصائح أخرى

سيكون الاختيار الواضح لنقطة البداية هو اللون، لأن هذا مطلب حصري.تبدو النتائج الأخرى أشبه بالنتائج الموزونة، لذا يمكن أن تؤدي هذه النتائج ببساطة إلى زيادة الوزن أو إنقاصه.

استخدم الأولويات للنطاقات الدنيا/القصوى، واحتفظ بكل منها في "فهرس" منفصل.ثم احصل على المباريات لكل منها وقم بإنشاء اتحاد.النظر في هذا الهيكل:

/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)

الآن للاستعلام، أود ببساطة الحصول على المطابقات في كل فئة وترتيبها حسب عدد المطابقات.يمكنني أن أبدأ بالألوان، لأنه من المفترض أن هذا ليس تصنيفًا اختياريًا أو نسبيًا:

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;
}

حسنًا، لقد قدمت الآن ما يطلبه الجميع في حالة الاستخدام هذه - كيفية إنشاء جملة حيث بدائية.ومع ذلك، فإن الإجابة المناسبة هنا هي أن عمليات البحث يجب أن تتم بواسطة محرك بحث.هذا ليس شرطًا بسيطًا.يعد هذا بحثًا مرجحًا عن أفضل التطابقات، لأن الحقول مثل اللون ليست اختيارية أو ببساطة أفضل تطابق، في حين أن الآخرين - ربما الترتيب - هم الأقرب تطابقًا في أي من الاتجاهين، بينما يؤثر البعض ببساطة على جودة من المباراة.

الدفع مصباح يدوي من أجل تكامل ElasticSearch البسيط.باستخدام هذا النهج، يجب أن تكون قادرًا على الاستفادة من أدوات الترجيح الرائعة والفرز الديناميكي وكل شيء آخر تحتاجه لإجراء خوارزمية مطابقة مناسبة.

فيما يتعلق بالجمود.لن أركز كثيرًا هنا حتى يكون لديك مئات المعاملات في الثانية (أي.مئات الآلاف من المستخدمين يتنافسون على المباريات).قم بتقسيم المسار الذي سنكتب فيه لقبول الانضمام وإجراء معاملة لضمان نجاح شخص واحد فقط في الحصول عليها.احتفظ به منفصلاً عن بيانات القراءة حتى لا يؤدي قفل هذا المسار إلى إبطاء عملية المعالجة.احتفظ بالمعاملة في حجمها الأدنى (حقل واحد إن أمكن).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top