Просмотр исходного кода

:recycle: redone stable marriage | half working

tags/0.0.1
j 4 лет назад
Родитель
Сommit
95c0f93244

+ 11
- 2
backend/db/mock.js Просмотреть файл

@@ -1424,8 +1424,8 @@ module.exports = {
1424 1424
         { message_id: 9, user_id: 3, grouping_id: 5, message: 'meow' },
1425 1425
     ],
1426 1426
     match_queues: [
1427
-        { match_queue_id: 1, profile_id: 4, target_id: 1, is_deleted: false },
1428
-        { match_queue_id: 2, profile_id: 4, target_id: 3, is_deleted: false },
1427
+        { match_queue_id: 1, profile_id: 4, target_id: 3, is_deleted: false },
1428
+        { match_queue_id: 2, profile_id: 4, target_id: 1, is_deleted: false },
1429 1429
         { match_queue_id: 3, profile_id: 4, target_id: 2, is_deleted: false },
1430 1430
         { match_queue_id: 4, profile_id: 1, target_id: 4, is_deleted: false },
1431 1431
         { match_queue_id: 5, profile_id: 1, target_id: 6, is_deleted: false },
@@ -1433,5 +1433,14 @@ module.exports = {
1433 1433
         { match_queue_id: 7, profile_id: 2, target_id: 8, is_deleted: false },
1434 1434
         { match_queue_id: 8, profile_id: 2, target_id: 6, is_deleted: false },
1435 1435
         { match_queue_id: 9, profile_id: 2, target_id: 4, is_deleted: false },
1436
+        { match_queue_id: 10, profile_id: 3, target_id: 6, is_deleted: false },
1437
+        { match_queue_id: 11, profile_id: 3, target_id: 8, is_deleted: false },
1438
+        { match_queue_id: 12, profile_id: 3, target_id: 4, is_deleted: false },
1439
+        { match_queue_id: 13, profile_id: 6, target_id: 1, is_deleted: false },
1440
+        { match_queue_id: 14, profile_id: 6, target_id: 3, is_deleted: false },
1441
+        { match_queue_id: 15, profile_id: 6, target_id: 2, is_deleted: false },
1442
+        { match_queue_id: 16, profile_id: 8, target_id: 1, is_deleted: false },
1443
+        { match_queue_id: 17, profile_id: 8, target_id: 3, is_deleted: false },
1444
+        { match_queue_id: 18, profile_id: 8, target_id: 2, is_deleted: false },
1436 1445
     ],
1437 1446
 }

+ 3
- 3
backend/lib/routes/profile/match.js Просмотреть файл

@@ -13,7 +13,7 @@ const pluginConfig = {
13 13
 const validators = {}
14 14
 
15 15
 const responseSchemas = {
16
-    response: Joi.object(),
16
+    response: Joi.array().items(Joi.object()),
17 17
     error: Joi.object({
18 18
         error: Joi.string(),
19 19
     }),
@@ -32,7 +32,7 @@ module.exports = {
32 32
             const { matchService, matchQueueService } =
33 33
                 request.server.services()
34 34
             const allQueues = await matchQueueService.getAllQueues()
35
-            matchService.calcMatches(allQueues)
35
+            const matched = await matchService.calcMatches(allQueues)
36 36
             try {
37 37
                 if (!allQueues) {
38 38
                     throw new RangeError('Unable to match profiles')
@@ -42,7 +42,7 @@ module.exports = {
42 42
                     .response({
43 43
                         ok: true,
44 44
                         handler: pluginConfig.handlerType,
45
-                        data: allQueues,
45
+                        data: matched,
46 46
                     })
47 47
                     .code(200)
48 48
             } catch (err) {

+ 21
- 17
backend/lib/routes/profile/update.js Просмотреть файл

@@ -50,29 +50,33 @@ module.exports = {
50 50
             const { profileService } = request.services()
51 51
             const profileId = request.params.profile_id
52 52
 
53
-            const responseId = request.params.response_id ? request.params.response_id : null
54
-            
55 53
             /** Grab payload info */
56 54
             const res = request.payload
57 55
             try {
58
-                const updatedResponses = await profileService.updateResponsesInProfile(profileId, res)
59
-
60
-                if(!updatedResponses) {
61
-                    throw new RangeError(
62
-                        'Response not updated',
56
+                const updatedResponses =
57
+                    await profileService.updateResponsesInProfile(
58
+                        profileId,
59
+                        res,
63 60
                     )
61
+
62
+                if (!updatedResponses) {
63
+                    throw new RangeError('Response not updated')
64 64
                 }
65
-                return h.response({
66
-                    ok: true,
67
-                    handler: pluginConfig.handlerType,
68
-                    data: updatedResponses,
69
-                }).code(200)
65
+                return h
66
+                    .response({
67
+                        ok: true,
68
+                        handler: pluginConfig.handlerType,
69
+                        data: updatedResponses,
70
+                    })
71
+                    .code(200)
70 72
             } catch (err) {
71
-                return h.response({
72
-                    ok: false,
73
-                    handler: pluginConfig.handlerType,
74
-                    data: { error: `${err}` },
75
-                }).code(409)
73
+                return h
74
+                    .response({
75
+                        ok: false,
76
+                        handler: pluginConfig.handlerType,
77
+                        data: { error: `${err}` },
78
+                    })
79
+                    .code(409)
76 80
             }
77 81
         },
78 82
 

+ 88
- 71
backend/lib/services/match.js Просмотреть файл

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

Загрузка…
Отмена
Сохранить