Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. const Schmervice = require('@hapipal/schmervice')
  2. function engageEveryone(guys) {
  3. let done
  4. do {
  5. done = true
  6. for (let i = 0; i < guys.length; i++) {
  7. const guy = guys[i]
  8. if (!guy.fiance) {
  9. done = false
  10. const gal = guy.nextCandidate()
  11. if (!gal.fiance || gal.prefers(guy)) {
  12. guy.engageTo(gal)
  13. }
  14. }
  15. }
  16. } while (!done)
  17. }
  18. class Person {
  19. constructor(name) {
  20. let candidateIndex = 0
  21. this.name = name
  22. this.fiance = null
  23. this.candidates = []
  24. this.rank = p => {
  25. for (let i = 0; i < this.candidates.length; i++) {
  26. if (this.candidates[i] === p) return i
  27. }
  28. return this.candidates.length + 1
  29. }
  30. this.prefers = p => {
  31. return this.rank(p) < this.rank(this.fiance)
  32. }
  33. this.nextCandidate = () => {
  34. if (candidateIndex >= this.candidates.length) {
  35. return null
  36. }
  37. return this.candidates[candidateIndex++]
  38. }
  39. this.engageTo = p => {
  40. if (p.fiance) {
  41. p.fiance.fiance = null
  42. }
  43. p.fiance = this
  44. if (this.fiance) {
  45. this.fiance.fiance = null
  46. }
  47. this.fiance = p
  48. }
  49. this.swapWith = p => {
  50. console.log('%s & %s swap partners', this.name, p.name)
  51. const thisFiance = this.fiance
  52. const pFiance = p.fiance
  53. this.engageTo(pFiance)
  54. p.engageTo(thisFiance)
  55. }
  56. }
  57. }
  58. module.exports = class MatchService extends Schmervice.Service {
  59. constructor(...args) {
  60. super(...args)
  61. }
  62. async calcMatches(allQueuesByType) {
  63. const seekers = Object.keys(allQueuesByType['seeker']).map(id => ({
  64. profile_id: parseInt(id),
  65. queue: allQueuesByType['seeker'][id],
  66. }))
  67. const posters = Object.keys(allQueuesByType['poster']).map(id => ({
  68. profile_id: parseInt(id),
  69. queue: allQueuesByType['poster'][id],
  70. }))
  71. const diff = Math.abs(posters.length - seekers.length)
  72. const smallerList = posters.length < seekers.length ? posters : seekers
  73. // ADD DUMMY IDS TO THE SMALLER LIST
  74. for (let d = 0; d < diff; d++) {
  75. smallerList.push({ profile_id: `${d}-dummy`, queue: [] })
  76. }
  77. console.log('---')
  78. let allPeople = [...seekers, ...posters]
  79. const queuesById = allPeople.reduce((queuesById, profile) => {
  80. queuesById[profile.profile_id] = profile.queue
  81. return queuesById
  82. }, {})
  83. let allIds = allPeople.map(profile => profile.profile_id)
  84. seekers.forEach(profile => {
  85. profile.queue.forEach(id => allIds.push(id))
  86. })
  87. posters.forEach(profile => {
  88. profile.queue.forEach(id => allIds.push(id))
  89. })
  90. allIds = [...new Set(allIds)]
  91. const peopleById = allIds.reduce((peopleById, id) => {
  92. peopleById[id] = new Person(id)
  93. if (queuesById[id]) {
  94. peopleById[id].candidates = queuesById[id].map(
  95. queueId => new Person(queueId),
  96. )
  97. }
  98. return peopleById
  99. }, {})
  100. const seekerPeople = seekers.map(
  101. profile => peopleById[profile.profile_id],
  102. )
  103. const posterPeople = posters.map(
  104. profile => peopleById[profile.profile_id],
  105. )
  106. // You only need to engage from one side
  107. engageEveryone(seekerPeople)
  108. engageEveryone(posterPeople)
  109. Object.values(peopleById).forEach(person => {
  110. if (person.fiance) {
  111. person.fiance.fiance = null
  112. }
  113. })
  114. return Object.values(peopleById).map(person => ({
  115. id: person.name,
  116. otp: person?.fiance?.name ?? null,
  117. }))
  118. }
  119. }