Sfoglia il codice sorgente

:sparkles: using cos similarity for quick scoring

tags/0.0.1
j 4 anni fa
parent
commit
e02a9fde1e
3 ha cambiato i file con 120 aggiunte e 17 eliminazioni
  1. 40
    17
      backend/db/survey-generator.js
  2. 79
    0
      backend/package-lock.json
  3. 1
    0
      backend/package.json

+ 40
- 17
backend/db/survey-generator.js Vedi File

1
+const similarity = require('compute-cosine-similarity')
2
+const magic = 1000 // Multiply cosine similary by this
3
+
1
 const not_important = '120'
4
 const not_important = '120'
2
 const somewhat_important = '140'
5
 const somewhat_important = '140'
3
 const important = '160'
6
 const important = '160'
4
 const very_important = '180'
7
 const very_important = '180'
5
 const extremely_important = '200'
8
 const extremely_important = '200'
6
 const mandatory = '400'
9
 const mandatory = '400'
10
+
7
 // -
11
 // -
8
 // 1440 - 2400 total range
12
 // 1440 - 2400 total range
9
 // 1440 - 1900 limited range
13
 // 1440 - 1900 limited range
59
 
63
 
60
 class DummyProfile {
64
 class DummyProfile {
61
     constructor() {
65
     constructor() {
66
+        this.id = null
62
         this.profileResponses = null
67
         this.profileResponses = null
63
         this.langPref = null
68
         this.langPref = null
64
         this.durationPref = null
69
         this.durationPref = null
84
     const profiles = []
89
     const profiles = []
85
     for (let i = 0; i < count; i++) {
90
     for (let i = 0; i < count; i++) {
86
         const dummyProfile = new DummyProfile()
91
         const dummyProfile = new DummyProfile()
92
+        dummyProfile.id = i + 1
87
         profiles.push(dummyProfile)
93
         profiles.push(dummyProfile)
88
     }
94
     }
89
     profiles.forEach(dummy => {
95
     profiles.forEach(dummy => {
90
-        dummy.profileResponses = dummy.profileResponses.map(answer => {
91
-            const answerObj = {}
92
-            const random = rand(12)
93
-            answerObj[random] = answer
94
-            return answerObj
95
-        })
96
+        dummy.profileResponses = dummy.profileResponses.map(
97
+            (answer, response_key_id) => {
98
+                const answerObj = {}
99
+                // aka: id for the question we asked
100
+                answerObj[response_key_id] = answer
101
+                return answerObj
102
+            },
103
+        )
96
     })
104
     })
97
     return profiles
105
     return profiles
98
 }
106
 }
100
 const generatedSeekers = generateDummyProfiles(100)
108
 const generatedSeekers = generateDummyProfiles(100)
101
 const generatedProviders = generateDummyProfiles(10)
109
 const generatedProviders = generateDummyProfiles(10)
102
 
110
 
103
-const compareProfiles = (profile, unorderedPotentialMatches) => {
111
+const scoreMatch = (seeker, potentialMatch) => {
112
+    const seekerResponseValues = seeker.profileResponses.map(res =>
113
+        parseInt(Object.values(res)),
114
+    )
115
+    const potentialMatchResponseValues = potentialMatch.profileResponses.map(
116
+        res => parseInt(Object.values(res)),
117
+    )
118
+    return Math.floor(
119
+        similarity(seekerResponseValues, potentialMatchResponseValues) * magic,
120
+    )
121
+}
122
+const compareProfile = (seeker, unorderedPotentialMatches) => {
104
     const scored = unorderedPotentialMatches.map(potentialMatch => {
123
     const scored = unorderedPotentialMatches.map(potentialMatch => {
105
-        // score the match
106
-        const score = rand(1900)
107
         // add the match to object keyed by score
124
         // add the match to object keyed by score
108
-        return { score, profile: potentialMatch }
125
+        return {
126
+            profileMatchScore: scoreMatch(seeker, potentialMatch),
127
+            profile: potentialMatch,
128
+        }
109
     })
129
     })
110
-    // create array ordered by score
111
-    const orderedPotentialMatches = scored.sort((a, b) => a.score - b.score)
112
-    return orderedPotentialMatches
130
+    // return ordered by score
131
+    return scored.sort((a, b) => a.profileMatchScore - b.profileMatchScore)
113
 }
132
 }
114
 
133
 
115
 generatedSeekers.forEach(seeker => {
134
 generatedSeekers.forEach(seeker => {
116
-    console.log(compareProfiles(seeker, generatedProviders))
135
+    const matchQueue = compareProfile(seeker, generatedProviders).map(
136
+        provider => ({
137
+            score: provider.profileMatchScore,
138
+            profile_id: provider.profile.id,
139
+        }),
140
+    )
141
+    console.log(`\n---|    Results for job_seeker: ${seeker.id}    |---`)
142
+    console.log(matchQueue)
117
 })
143
 })
118
-// console.log(generatedProviders)
119
-// console.log(generatedSeekers[0].profileResponses)
120
-// console.log(generatedProviders[0].profileResponses)

+ 79
- 0
backend/package-lock.json Vedi File

17
         "@hapipal/confidence": "^6.0.1",
17
         "@hapipal/confidence": "^6.0.1",
18
         "@hapipal/schmervice": "^2.0.0",
18
         "@hapipal/schmervice": "^2.0.0",
19
         "@hapipal/schwifty": "^6.0.0",
19
         "@hapipal/schwifty": "^6.0.0",
20
+        "compute-cosine-similarity": "^1.0.0",
20
         "dotenv": "^10.0.0",
21
         "dotenv": "^10.0.0",
21
         "exiting": "^6.0.1",
22
         "exiting": "^6.0.1",
22
         "hapi-swagger": "^14.1.3",
23
         "hapi-swagger": "^14.1.3",
2362
       "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
2363
       "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
2363
       "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
2364
       "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
2364
     },
2365
     },
2366
+    "node_modules/compute-cosine-similarity": {
2367
+      "version": "1.0.0",
2368
+      "resolved": "https://registry.npmjs.org/compute-cosine-similarity/-/compute-cosine-similarity-1.0.0.tgz",
2369
+      "integrity": "sha1-KfK/Lnuu+iMcq6QFkaMcF7GaTpU=",
2370
+      "dependencies": {
2371
+        "compute-dot": "^1.1.0",
2372
+        "compute-l2norm": "^1.1.0",
2373
+        "validate.io-array": "^1.0.5",
2374
+        "validate.io-function": "^1.0.2"
2375
+      }
2376
+    },
2377
+    "node_modules/compute-dot": {
2378
+      "version": "1.1.0",
2379
+      "resolved": "https://registry.npmjs.org/compute-dot/-/compute-dot-1.1.0.tgz",
2380
+      "integrity": "sha1-AaW6LHr3O5kAKsslhFnJV2qCMtw=",
2381
+      "dependencies": {
2382
+        "validate.io-array": "^1.0.3",
2383
+        "validate.io-function": "^1.0.2"
2384
+      }
2385
+    },
2386
+    "node_modules/compute-l2norm": {
2387
+      "version": "1.1.0",
2388
+      "resolved": "https://registry.npmjs.org/compute-l2norm/-/compute-l2norm-1.1.0.tgz",
2389
+      "integrity": "sha1-vQkTHGs2yNcMaDNOF2AJpOCpiaw=",
2390
+      "dependencies": {
2391
+        "validate.io-array": "^1.0.3",
2392
+        "validate.io-function": "^1.0.2"
2393
+      }
2394
+    },
2365
     "node_modules/concat-map": {
2395
     "node_modules/concat-map": {
2366
       "version": "0.0.1",
2396
       "version": "0.0.1",
2367
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
2397
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
7915
         "spdx-expression-parse": "^3.0.0"
7945
         "spdx-expression-parse": "^3.0.0"
7916
       }
7946
       }
7917
     },
7947
     },
7948
+    "node_modules/validate.io-array": {
7949
+      "version": "1.0.6",
7950
+      "resolved": "https://registry.npmjs.org/validate.io-array/-/validate.io-array-1.0.6.tgz",
7951
+      "integrity": "sha1-W1osr9j4uFq7L4hroVPy2Tond00="
7952
+    },
7953
+    "node_modules/validate.io-function": {
7954
+      "version": "1.0.2",
7955
+      "resolved": "https://registry.npmjs.org/validate.io-function/-/validate.io-function-1.0.2.tgz",
7956
+      "integrity": "sha1-NDoZgC7TsZaCaceA5VjpNBHAutc="
7957
+    },
7918
     "node_modules/validator": {
7958
     "node_modules/validator": {
7919
       "version": "10.11.0",
7959
       "version": "10.11.0",
7920
       "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
7960
       "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
9946
       "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
9986
       "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
9947
       "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
9987
       "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
9948
     },
9988
     },
9989
+    "compute-cosine-similarity": {
9990
+      "version": "1.0.0",
9991
+      "resolved": "https://registry.npmjs.org/compute-cosine-similarity/-/compute-cosine-similarity-1.0.0.tgz",
9992
+      "integrity": "sha1-KfK/Lnuu+iMcq6QFkaMcF7GaTpU=",
9993
+      "requires": {
9994
+        "compute-dot": "^1.1.0",
9995
+        "compute-l2norm": "^1.1.0",
9996
+        "validate.io-array": "^1.0.5",
9997
+        "validate.io-function": "^1.0.2"
9998
+      }
9999
+    },
10000
+    "compute-dot": {
10001
+      "version": "1.1.0",
10002
+      "resolved": "https://registry.npmjs.org/compute-dot/-/compute-dot-1.1.0.tgz",
10003
+      "integrity": "sha1-AaW6LHr3O5kAKsslhFnJV2qCMtw=",
10004
+      "requires": {
10005
+        "validate.io-array": "^1.0.3",
10006
+        "validate.io-function": "^1.0.2"
10007
+      }
10008
+    },
10009
+    "compute-l2norm": {
10010
+      "version": "1.1.0",
10011
+      "resolved": "https://registry.npmjs.org/compute-l2norm/-/compute-l2norm-1.1.0.tgz",
10012
+      "integrity": "sha1-vQkTHGs2yNcMaDNOF2AJpOCpiaw=",
10013
+      "requires": {
10014
+        "validate.io-array": "^1.0.3",
10015
+        "validate.io-function": "^1.0.2"
10016
+      }
10017
+    },
9949
     "concat-map": {
10018
     "concat-map": {
9950
       "version": "0.0.1",
10019
       "version": "0.0.1",
9951
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
10020
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
14163
         "spdx-expression-parse": "^3.0.0"
14232
         "spdx-expression-parse": "^3.0.0"
14164
       }
14233
       }
14165
     },
14234
     },
14235
+    "validate.io-array": {
14236
+      "version": "1.0.6",
14237
+      "resolved": "https://registry.npmjs.org/validate.io-array/-/validate.io-array-1.0.6.tgz",
14238
+      "integrity": "sha1-W1osr9j4uFq7L4hroVPy2Tond00="
14239
+    },
14240
+    "validate.io-function": {
14241
+      "version": "1.0.2",
14242
+      "resolved": "https://registry.npmjs.org/validate.io-function/-/validate.io-function-1.0.2.tgz",
14243
+      "integrity": "sha1-NDoZgC7TsZaCaceA5VjpNBHAutc="
14244
+    },
14166
     "validator": {
14245
     "validator": {
14167
       "version": "10.11.0",
14246
       "version": "10.11.0",
14168
       "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",
14247
       "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz",

+ 1
- 0
backend/package.json Vedi File

21
     "@hapipal/confidence": "^6.0.1",
21
     "@hapipal/confidence": "^6.0.1",
22
     "@hapipal/schmervice": "^2.0.0",
22
     "@hapipal/schmervice": "^2.0.0",
23
     "@hapipal/schwifty": "^6.0.0",
23
     "@hapipal/schwifty": "^6.0.0",
24
+    "compute-cosine-similarity": "^1.0.0",
24
     "dotenv": "^10.0.0",
25
     "dotenv": "^10.0.0",
25
     "exiting": "^6.0.1",
26
     "exiting": "^6.0.1",
26
     "hapi-swagger": "^14.1.3",
27
     "hapi-swagger": "^14.1.3",

Loading…
Annulla
Salva