const similarity = require('compute-cosine-similarity') const magic = 1000 // Multiply cosine similary by this const not_important = '120' const somewhat_important = '140' const important = '160' const very_important = '180' const extremely_important = '200' const mandatory = '400' // - // 1440 - 2400 total range // 1440 - 1900 limited range // - // Reserved for REALLY important answers // like full-time vs part-time // and remote vs onsite only // 400 mandatory const importance = [ not_important, somewhat_important, important, very_important, extremely_important, ] const langs = [ 'javascript', 'python', 'ruby', 'erlang', 'haskall', 'php', 'swift', 'rust', 'objective-c', 'common lisp', 'java', 'perl', 'cobol', 'fortran', 'julia', 'c#', 'go', 'c++', ] const duration = ['full', 'part'] const location = ['onsite', 'remote', 'flexible'] const otherWeightLookup = { full: mandatory, part: mandatory, onsite: mandatory, remote: mandatory, flexible: mandatory, } const rand = max => { return Math.floor(Math.random() * max) < 1 ? 1 : Math.floor(Math.random() * max) } class DummyProfile { constructor() { this.id = null this.profileResponses = null this.langPref = null this.durationPref = null this.locationPref = null // profile is constructed of 12 answers, 2 for each dimension this.profileResponses = this.getRandomAnswers(12, importance) this.langPref = this.getRandomAnswers(rand(4), langs) this.durationPref = this.getRandomAnswers(1, duration) this.locationPref = this.getRandomAnswers(1, location) } getRandomAnswers(count, options) { const answers = [] for (let i = 0; i < count; i++) { const random = rand(options.length) answers.push(options[random]) } return answers } } const generateDummyProfiles = count => { const profiles = [] for (let i = 0; i < count; i++) { const dummyProfile = new DummyProfile() dummyProfile.id = i + 1 profiles.push(dummyProfile) } profiles.forEach(dummy => { dummy.profileResponses = dummy.profileResponses.map( (answer, response_key_id) => { const answerObj = {} // aka: id for the question we asked answerObj[response_key_id] = answer return answerObj }, ) }) return profiles } const generatedSeekers = generateDummyProfiles(100) const generatedProviders = generateDummyProfiles(10) const scoreMatch = (seeker, potentialMatch) => { const seekerResponseValues = seeker.profileResponses.map(res => parseInt(Object.values(res)), ) const potentialMatchResponseValues = potentialMatch.profileResponses.map( res => parseInt(Object.values(res)), ) return Math.floor( similarity(seekerResponseValues, potentialMatchResponseValues) * magic, ) } const compareProfile = (seeker, unorderedPotentialMatches) => { const scored = unorderedPotentialMatches.map(potentialMatch => { // add the match to object keyed by score return { profileMatchScore: scoreMatch(seeker, potentialMatch), profile: potentialMatch, } }) // return ordered by score return scored.sort((a, b) => a.profileMatchScore - b.profileMatchScore) } generatedSeekers.forEach(seeker => { const matchQueue = compareProfile(seeker, generatedProviders).map( provider => ({ score: provider.profileMatchScore, profile_id: provider.profile.id, }), ) console.log(`\n---| Results for job_seeker: ${seeker.id} |---`) console.log(matchQueue) })