ソースを参照

:construction: new filter service to preprocess a users match pool before scoring

tags/0.0.3^2
juancarbajal98 3年前
コミット
0f3212ab87

+ 24
- 0
backend/lib/services/filter.js ファイルの表示

@@ -0,0 +1,24 @@
1
+const zipcoder = require ('./profile/zipcoder')
2
+
3
+const byProfileType = (profileList, userProfile) => {
4
+    const isUserOpposite = userProfile.is_poster == 1 ? 0 : 1
5
+    return profileList.filter(profile => (profile.user.is_poster == isUserOpposite))
6
+}
7
+const byNullZip = (profileList) => {
8
+    return profileList.filter(profile => {
9
+        return zipcoder.getZipCodeFromProfile(profile) ? true : false
10
+    })
11
+}
12
+const byMaxDistance = (profileList, max) => {
13
+    return profileList.filter(profile => {
14
+        const profileDistance = Math.floor(parseFloat(profile.distance) * 100)
15
+        const adjustedMaxDistance = Math.floor(parseFloat(max) * 100)
16
+        return profileDistance <= adjustedMaxDistance
17
+    })
18
+}
19
+
20
+module.exports = {
21
+    byProfileType,
22
+    byNullZip,
23
+    byMaxDistance,
24
+}

+ 32
- 35
backend/lib/services/profile/index.js ファイルの表示

@@ -4,7 +4,12 @@ const config = require('../../../db/data-generator/config.json')
4 4
 const profiler = require('./profiler')
5 5
 const scoring = require('./scorer')
6 6
 const zipcoder = require('./zipcoder')
7
+<<<<<<< HEAD
7 8
 const { response } = require('@hapi/hapi/lib/validation')
9
+=======
10
+const tagger = require('./tagger')
11
+const filter = require('./filter')
12
+>>>>>>> 154d171 (:construction: new filter service to preprocess a users match pool before scoring)
8 13
 
9 14
 module.exports = class ProfileService extends Schmervice.Service {
10 15
     constructor(...args) {
@@ -253,30 +258,36 @@ module.exports = class ProfileService extends Schmervice.Service {
253 258
             .findOne('profile_id', profileId)
254 259
             .withGraphFetched('responses')
255 260
             .withGraphFetched('user')
256
-
257
-        // Move unneeded responses
261
+        
258 262
         const userZip = zipcoder.getZipCodeFromProfile(userProfile)
259 263
 
260
-        // Find all Profiles that are NOT of our userProfile.type
261
-        // ie. If userProfile.type == seeker, then find: poster
262
-        let profileIdsOfOppositeType = await Profile.query()
264
+        // preprocess potential match pool with filter service methods
265
+        let matchPool = await Profile.query()
263 266
             .withGraphFetched('responses')
264 267
             .withGraphFetched('user')
265
-        // TODO: Let Objection optimize this
266
-        const isPosterOpposite = userProfile.user.is_poster == 1 ? 0 : 1
267
-        profileIdsOfOppositeType = profileIdsOfOppositeType
268
-            .filter(profile => {
269
-                return profile.user.is_poster == isPosterOpposite
270
-            })
271
-            .filter(profile => {
272
-                // Only include profiles that included zipcode response
273
-                return zipcoder.getZipCodeFromProfile(profile) ? true : false
274
-            })
275 268
 
276
-        const profilePlusDistance = await Promise.all(
277
-            profileIdsOfOppositeType.map(async profile => {
278
-                const targetZip = zipcoder.getZipCodeFromProfile(profile)
269
+        matchPool = filter.byProfileType(matchPool, userProfile.user)
270
+        matchPool = filter.byNullZip(matchPool)
271
+        // attach distance to pool profiles for max distance filter 
272
+        matchPool = await this.calcProfileDistances(matchPool, distanceUnit, userZip)
273
+        // filter with matchPool profiles that have distance
274
+        matchPool = filter.byMaxDistance(matchPool, maxDistance)
275
+
276
+        const scoredProfilesWithDistance = scoring.scoreAll(
277
+            matchPool,
278
+            userProfile,
279
+            this.scoreLookup,
280
+        )
281
+        // Order by score
282
+        return scoredProfilesWithDistance.sort(
283
+            (a, b) => b.score.total - a.score.total,
284
+        )
285
+    }
279 286
 
287
+    async calcProfileDistances(matchPool, distanceUnit, userZip){
288
+        await Promise.all(
289
+            matchPool.map(async profile => {
290
+                const targetZip = zipcoder.getZipCodeFromProfile(profile)
280 291
                 if (!userZip || !targetZip)
281 292
                     return { ...profile, distance: [9999, distanceUnit] }
282 293
 
@@ -289,21 +300,7 @@ module.exports = class ProfileService extends Schmervice.Service {
289 300
                     ...profile,
290 301
                     distance: [distance.toFixed(2), distanceUnit],
291 302
                 }
292
-            }),
293
-        )
294
-
295
-        const distanceFilteredProfiles = zipcoder.filterByDistance(
296
-            profilePlusDistance,
297
-            maxDistance,
298
-        )
299
-        const scoredProfilesWithDistance = scoring.scoreAll(
300
-            distanceFilteredProfiles,
301
-            userProfile,
302
-            this.scoreLookup,
303
-        )
304
-        // Order by score
305
-        return scoredProfilesWithDistance.sort(
306
-            (a, b) => b.score.total - a.score.total,
303
+            })
307 304
         )
308 305
     }
309 306
 
@@ -351,8 +348,8 @@ module.exports = class ProfileService extends Schmervice.Service {
351 348
         await this._setTagLookup()
352 349
         let associations = groupingId
353 350
             ? await TagAssociation.query()
354
-                  .where('grouping_id', groupingId)
355
-                  .andWhere('profile_id', profileId)
351
+                .where('grouping_id', groupingId)
352
+                .andWhere('profile_id', profileId)
356 353
             : await TagAssociation.query().andWhere('profile_id', profileId)
357 354
         return associations
358 355
             .map(assoc => ({

+ 0
- 9
backend/lib/services/profile/zipcoder.js ファイルの表示

@@ -11,15 +11,6 @@ const getZipCodeFromProfile = profile => {
11 11
     return zipRes.val
12 12
 }
13 13
 
14
-const filterByDistance = (profileList, max) => {
15
-    return profileList.filter(profile => {
16
-        const profileDistance = Math.floor(parseFloat(profile.distance) * 100)
17
-        const adjustedMaxDistance = Math.floor(parseFloat(max) * 100)
18
-        return profileDistance <= adjustedMaxDistance
19
-    })
20
-}
21
-
22 14
 module.exports = {
23 15
     getZipCodeFromProfile,
24
-    filterByDistance,
25 16
 }

+ 0
- 51
frontend/src/views/OnboardingView.vue ファイルの表示

@@ -2,7 +2,6 @@
2 2
 main.view--onboarding
3 3
     article(
4 4
         style='display: flex; flex-direction: column; align-items: center'
5
-<<<<<<< HEAD
6 5
         v-if='currentStep !== survey.steps.length'
7 6
     )
8 7
         .answers(v-for='(value, key) in answered')
@@ -32,33 +31,15 @@ main.view--onboarding
32 31
 
33 32
     article(v-else)
34 33
         SurveyCompleteView(:answers='answered' :surveySteps='survey.steps')
35
-=======
36
-        v-if='survey'
37
-    )
38
-        .step(v-for='(step, i) in survey.steps')
39
-            component(
40
-                :aspect-questions='step.component == "Aspects" ? survey.aspectQuestions : null'
41
-                :is='step.component'
42
-                :question='step'
43
-                @handle-submit='onSubmit'
44
-                @update-answers='updateAnswers'
45
-                v-if='step && currentStep == i'
46
-            )
47
->>>>>>> b0c2120 (another pre-release (#53))
48 34
 </template>
49 35
 
50 36
 <script>
51 37
 import { Authenticator } from '../services/auth.service.js'
52 38
 import { surveyFactory } from '@/utils'
53
-<<<<<<< HEAD
54 39
 import stepViews from '@/components/onboarding'
55 40
 import SurveyCompleteView from './SurveyCompleteView.vue'
56 41
 let hashedAccessToken = null
57 42
 let currentProfileId = null
58
-=======
59
-import { allSteps } from '@/utils/lang'
60
-import stepViews from '@/components/onboarding'
61
->>>>>>> b0c2120 (another pre-release (#53))
62 43
 
63 44
 // import savesurveybyprfileid - call it on submit
64 45
 // paginate to save every steps answers
@@ -66,7 +47,6 @@ export default {
66 47
     name: 'OnboardingView',
67 48
     components: {
68 49
         ...stepViews,
69
-<<<<<<< HEAD
70 50
         SurveyCompleteView,
71 51
     },
72 52
     data: () => ({
@@ -93,23 +73,10 @@ export default {
93 73
             this.goToStep(0)
94 74
         }
95 75
     },
96
-=======
97
-    },
98
-    data: () => ({
99
-        answered: {},
100
-        aspectQuestions: [],
101
-        currentStep: 0,
102
-        survey: null,
103
-    }),
104
-    async created() {
105
-        this.survey = await surveyFactory.createSurvey(allSteps['usa'])
106
-    },
107
->>>>>>> b0c2120 (another pre-release (#53))
108 76
     methods: {
109 77
         onSubmit() {
110 78
             console.log(JSON.stringify(this.answered))
111 79
         },
112
-<<<<<<< HEAD
113 80
         async goToStep(num) {
114 81
             this.currentStep = num
115 82
         },
@@ -175,21 +142,6 @@ export default {
175 142
             } else {
176 143
                 this.goToStep(this.currentStep + 1)
177 144
             }
178
-=======
179
-        goToStep(num) {
180
-            this.currentStep = num
181
-        },
182
-        updateAnswers(payload) {
183
-            // null payload is passed on splash page
184
-            if (payload) {
185
-                const k = payload.question.response_key_prompt
186
-                this.answered[k] = payload.answer
187
-                console.log(`${k}:`, this.answered[k])
188
-                console.log(`Updated answers: ${JSON.stringify(this.answered)}`)
189
-                if (k === 'aspects') return
190
-            }
191
-            this.goToStep(this.currentStep + 1)
192
->>>>>>> b0c2120 (another pre-release (#53))
193 145
         },
194 146
     },
195 147
 }
@@ -207,12 +159,9 @@ export default {
207 159
     article
208 160
         height: 100vh
209 161
 
210
-<<<<<<< HEAD
211 162
     .answers
212 163
         text-align: center
213 164
 
214
-=======
215
->>>>>>> b0c2120 (another pre-release (#53))
216 165
     .w-button
217 166
             display: flex
218 167
             width: 315px

読み込み中…
キャンセル
保存