浏览代码

Merge branch 'filter-before-scoring' of fyindr/siimee into dev

tags/0.0.3^2
maeda 2 年前
父节点
当前提交
62847c7392

+ 1
- 1
backend/db/seeds/04-responses.js 查看文件

28
     for (let i = 1; i <= len; i += 1) {
28
     for (let i = 1; i <= len; i += 1) {
29
         responsesToPush.push(responses.shift())
29
         responsesToPush.push(responses.shift())
30
         if (i % batchSize === 0 || i > responses.length) {
30
         if (i % batchSize === 0 || i > responses.length) {
31
-            await knex('responses').insert(responsesToPush)
31
+            // await knex('responses').insert(responsesToPush)
32
             responsesToPush = []
32
             responsesToPush = []
33
         }
33
         }
34
     }
34
     }

+ 6
- 0
backend/lib/routes/profile/score.js 查看文件

53
             const distanceUnit = request.query.unit
53
             const distanceUnit = request.query.unit
54
                 ? request.query.unit
54
                 ? request.query.unit
55
                 : 'mile'
55
                 : 'mile'
56
+            const duration = request.query.duration
57
+            const presence = request.query.presence
58
+            const certifications = request.query.certifications
56
 
59
 
57
             const scoredProfiles = await profileService.scoreProfilesFor(
60
             const scoredProfiles = await profileService.scoreProfilesFor(
58
                 profileId,
61
                 profileId,
59
                 maxDistanceMiles,
62
                 maxDistanceMiles,
60
                 distanceUnit,
63
                 distanceUnit,
64
+                duration,
65
+                presence,
66
+                certifications,
61
             )
67
             )
62
             try {
68
             try {
63
                 if (!scoredProfiles) {
69
                 if (!scoredProfiles) {

+ 48
- 0
backend/lib/services/filter.js 查看文件

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
+const byDuration = (profileList, duration) => {
21
+    return profileList.filter(profile => {
22
+        // TODO find duration 
23
+        return profile.duration == duration
24
+    })
25
+}
26
+
27
+const byPresence = (profileList, presence) => {
28
+    return profileList.filter(profile => {
29
+        // TODO find presence 
30
+        return profile.presence == presence
31
+    })
32
+}
33
+
34
+const byCertifications = (profileList, certifications) => {
35
+    return profileList.filter(profile => {
36
+        // TODO find certifications 
37
+        return profile.certifications == certifications
38
+    })
39
+}
40
+
41
+module.exports = {
42
+    byProfileType,
43
+    byNullZip,
44
+    byMaxDistance,
45
+    byDuration,
46
+    byPresence,
47
+    byCertifications,
48
+}

+ 38
- 33
backend/lib/services/profile/index.js 查看文件

4
 const profiler = require('./profiler')
4
 const profiler = require('./profiler')
5
 const scoring = require('./scorer')
5
 const scoring = require('./scorer')
6
 const zipcoder = require('./zipcoder')
6
 const zipcoder = require('./zipcoder')
7
-const { response } = require('@hapi/hapi/lib/validation')
7
+const filter = require('../filter')
8
 
8
 
9
 module.exports = class ProfileService extends Schmervice.Service {
9
 module.exports = class ProfileService extends Schmervice.Service {
10
     constructor(...args) {
10
     constructor(...args) {
243
      * @param {number} profileId
243
      * @param {number} profileId
244
      * @returns {Array} Ordered and scored Profiles
244
      * @returns {Array} Ordered and scored Profiles
245
      */
245
      */
246
-    async scoreProfilesFor(profileId, maxDistance, distanceUnit) {
246
+    async scoreProfilesFor(
247
+        profileId,
248
+        maxDistance,
249
+        distanceUnit,
250
+        duration,
251
+        presence,
252
+        certifications,
253
+    ) {
247
         const { Profile } = this.server.models()
254
         const { Profile } = this.server.models()
248
 
255
 
249
         await this._setScoreLookup()
256
         await this._setScoreLookup()
254
             .withGraphFetched('responses')
261
             .withGraphFetched('responses')
255
             .withGraphFetched('user')
262
             .withGraphFetched('user')
256
 
263
 
257
-        // Move unneeded responses
258
         const userZip = zipcoder.getZipCodeFromProfile(userProfile)
264
         const userZip = zipcoder.getZipCodeFromProfile(userProfile)
259
 
265
 
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()
266
+        // preprocess potential match pool with filter service methods
267
+        let matchPool = await Profile.query()
263
             .withGraphFetched('responses')
268
             .withGraphFetched('responses')
264
             .withGraphFetched('user')
269
             .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
 
270
 
276
-        const profilePlusDistance = await Promise.all(
277
-            profileIdsOfOppositeType.map(async profile => {
278
-                const targetZip = zipcoder.getZipCodeFromProfile(profile)
271
+        matchPool = filter.byProfileType(matchPool, userProfile.user)
272
+        matchPool = filter.byNullZip(matchPool)
273
+        // attach distance to pool profiles for max distance filter
274
+        matchPool = await this.calcProfileDistances(
275
+            matchPool,
276
+            distanceUnit,
277
+            userZip,
278
+        )
279
+        matchPool = filter.byMaxDistance(matchPool, maxDistance)
280
+        matchPool = filter.byDuration(matchPool, duration)
281
+        matchPool = filter.byPresence(matchPool, presence)
282
+        matchPool = filter.byCertifications(matchPool, certifications)
279
 
283
 
284
+        const scoredProfilesWithDistance = scoring.scoreAll(
285
+            matchPool,
286
+            userProfile,
287
+            this.scoreLookup,
288
+        )
289
+        // Order by score
290
+        return scoredProfilesWithDistance.sort(
291
+            (a, b) => b.score.total - a.score.total,
292
+        )
293
+    }
294
+
295
+    async calcProfileDistances(matchPool, distanceUnit, userZip) {
296
+        await Promise.all(
297
+            matchPool.map(async profile => {
298
+                const targetZip = zipcoder.getZipCodeFromProfile(profile)
280
                 if (!userZip || !targetZip)
299
                 if (!userZip || !targetZip)
281
                     return { ...profile, distance: [9999, distanceUnit] }
300
                     return { ...profile, distance: [9999, distanceUnit] }
282
 
301
 
291
                 }
310
                 }
292
             }),
311
             }),
293
         )
312
         )
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,
307
-        )
308
     }
313
     }
309
 
314
 
310
     /**
315
     /**

+ 0
- 9
backend/lib/services/profile/zipcoder.js 查看文件

11
     return zipRes.val
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
 module.exports = {
14
 module.exports = {
23
     getZipCodeFromProfile,
15
     getZipCodeFromProfile,
24
-    filterByDistance,
25
 }
16
 }

+ 218
- 7115
backend/package-lock.json
文件差异内容过多而无法显示
查看文件


+ 2
- 1
frontend/src/main.js 查看文件

8
 import App from './App.vue'
8
 import App from './App.vue'
9
 import MainNav from './components/MainNav.vue'
9
 import MainNav from './components/MainNav.vue'
10
 
10
 
11
-const DEV = import.meta.env.VITE_DEV == 'true'
11
+// const DEV = import.meta.env.VITE_DEV == 'true'
12
+const DEV = false
12
 
13
 
13
 /**
14
 /**
14
  * Check between route changes for login/timeout
15
  * Check between route changes for login/timeout

+ 8
- 2
frontend/src/services/survey.service.js 查看文件

49
     })
49
     })
50
 }
50
 }
51
 
51
 
52
-const scoreSurveyByProfileId = async (profileId, maxDistance = 99) => {
52
+const scoreSurveyByProfileId = async (
53
+    profileId,
54
+    maxDistance = 99,
55
+    duration,
56
+    presence,
57
+    certifications,
58
+) => {
53
     const scoreSurvey = await db.get(
59
     const scoreSurvey = await db.get(
54
-        `/profile/${profileId}/score?max_distance=${maxDistance}`,
60
+        `/profile/${profileId}/score?max_distance=${maxDistance}&duration=${duration}&presence=${presence}&certifications=${certifications}`,
55
     )
61
     )
56
     return scoreSurvey
62
     return scoreSurvey
57
 }
63
 }

+ 1
- 1
frontend/src/utils/lang.js 查看文件

32
 // Easily reorder steps of survey here:
32
 // Easily reorder steps of survey here:
33
 const allSteps = {
33
 const allSteps = {
34
     usa: {
34
     usa: {
35
-        email: 'email',
35
+        splash: 'splash',
36
         name: 'name',
36
         name: 'name',
37
         seeking: 'seeking',
37
         seeking: 'seeking',
38
         password: 'password',
38
         password: 'password',

+ 24
- 1
frontend/src/views/SurveyView.vue 查看文件

207
 
207
 
208
             return userProfileRel
208
             return userProfileRel
209
         },
209
         },
210
-        async _getProfileWithScore(createdProfileId, maxDistance) {
210
+        async _getProfileWithScore(
211
+            createdProfileId,
212
+            maxDistance,
213
+            duration,
214
+            presence,
215
+            certifications,
216
+        ) {
211
             /** A Profile is associated with n:1 user and referenced by profile id */
217
             /** A Profile is associated with n:1 user and referenced by profile id */
212
             const fetchedProfile = await fetchProfileByProfileId(
218
             const fetchedProfile = await fetchProfileByProfileId(
213
                 createdProfileId,
219
                 createdProfileId,
223
             const scored = await scoreSurveyByProfileId(
229
             const scored = await scoreSurveyByProfileId(
224
                 createdProfileId,
230
                 createdProfileId,
225
                 maxDistance,
231
                 maxDistance,
232
+                duration,
233
+                presence,
234
+                certifications,
226
             )
235
             )
227
             if (!scored) {
236
             if (!scored) {
228
                 console.error(`Could not score Profile ${createdProfileId}.`)
237
                 console.error(`Could not score Profile ${createdProfileId}.`)
250
             const maxDistanceRes = survey.find(
259
             const maxDistanceRes = survey.find(
251
                 res => res.response_key_id == distanceKey,
260
                 res => res.response_key_id == distanceKey,
252
             )
261
             )
262
+            const duration = survey.find(
263
+                res => res.response_key_id == prefKeys[1], // == 10
264
+            )
265
+            const presence = survey.find(
266
+                res => (res.response_key_id = prefKeys[2]), // == 11
267
+            )
268
+            // TODO find certifications in responses
269
+            const certifications = survey.find(
270
+                res => (res.response_key_id = certifications),
271
+            )
272
+
253
             /**
273
             /**
254
              * Creating a profile only returns the created
274
              * Creating a profile only returns the created
255
              * user id and profile id
275
              * user id and profile id
264
             const fetchedProfile = await this._getProfileWithScore(
284
             const fetchedProfile = await this._getProfileWithScore(
265
                 createdProfileId,
285
                 createdProfileId,
266
                 maxDistanceRes.val,
286
                 maxDistanceRes.val,
287
+                duration.val,
288
+                presence.val,
289
+                certifications.val,
267
             )
290
             )
268
 
291
 
269
             /**
292
             /**

正在加载...
取消
保存