random-weighted-choice.js 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. /*jshint node:true, laxcomma:true */
  2. "use strict";
  3. var debug = require('debug')('rwc');
  4. var RandomWeightedChoice = function (table, temperature, randomFunction, influence) {
  5. influence = influence || 2; // Seems fine, difficult to tune
  6. if (typeof(temperature)=="undefined") temperature = 50; // in [0,100], 50 is neutral
  7. temperature = temperature | 50;
  8. debug('temperature', temperature);
  9. var T = (temperature - 50) / 50;
  10. if (typeof(randomFunction)=="undefined") randomFunction = Math.random;
  11. var nb = table.length;
  12. if(!nb) return null; // No item given.
  13. var total = 0;
  14. table.forEach(function(element, index) {
  15. total += element.weight;
  16. });
  17. var avg = total / nb;
  18. debug('total', total);
  19. debug('nb', nb);
  20. debug('avg', avg);
  21. // Compute amplified urgencies (depending on temperature)
  22. var ur = {};
  23. var urgencySum = 0;
  24. table.forEach(function(element, index) {
  25. var urgency = element.weight + T * influence * (avg - element.weight);
  26. if (urgency < 0) urgency = 0;
  27. urgencySum += urgency;
  28. ur[element.id] = (ur[element.id] || 0 ) + urgency;
  29. });
  30. var cumulatedUrgencies = {};
  31. var currentUrgency = 0;
  32. Object.keys(ur).forEach(function(id, index) {
  33. currentUrgency += ur[id];
  34. cumulatedUrgencies[id] = currentUrgency;
  35. });
  36. if(urgencySum < 1) return null; // No weight given
  37. // Choose
  38. var choice = randomFunction() * urgencySum;
  39. debug('ur', ur);
  40. debug('cumulatedUrgencies', cumulatedUrgencies);
  41. debug('urgencySum', urgencySum);
  42. debug('choice', choice);
  43. var ids = Object.keys(cumulatedUrgencies);
  44. for(var i=0; i<ids.length; i++) {
  45. var id = ids[i];
  46. var urgency = cumulatedUrgencies[id];
  47. if(choice <= urgency) {
  48. debug('return', id);
  49. return id;
  50. }
  51. }
  52. };
  53. module.exports = RandomWeightedChoice;