Revised score calculation
parent
ba37ca72f8
commit
b5aa8d93fb
|
@ -1,6 +1,6 @@
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'package:flutter/foundation.dart' show kDebugMode, debugPrint;
|
|
||||||
import '../enumerations.dart';
|
import '../enumerations.dart';
|
||||||
|
import '../models/language.dart';
|
||||||
import '../models/user_profile.dart';
|
import '../models/user_profile.dart';
|
||||||
|
|
||||||
/// Approximate determination of age
|
/// Approximate determination of age
|
||||||
|
@ -95,96 +95,102 @@ double shortestDistanceBetweenUsers(
|
||||||
|
|
||||||
/// Calculates the matching score of [otherUser] for [currentUser].
|
/// Calculates the matching score of [otherUser] for [currentUser].
|
||||||
double calculateMatchScore(UserProfile currentUser, UserProfile otherUser) {
|
double calculateMatchScore(UserProfile currentUser, UserProfile otherUser) {
|
||||||
// weights
|
|
||||||
const double distanceWeight = 0.55;
|
|
||||||
const double skillWeight = 0.25;
|
|
||||||
const double availabilityWeight = 0.065;
|
|
||||||
const double visionWeight = 0.04;
|
|
||||||
const double riskWeight = 0.035;
|
|
||||||
const double workWeight = 0.025;
|
|
||||||
const double cultureWeight = 0.02;
|
|
||||||
const double communicationWeight = 0.015;
|
|
||||||
|
|
||||||
if (kDebugMode) {
|
|
||||||
double weightSum = (distanceWeight +
|
|
||||||
skillWeight +
|
|
||||||
availabilityWeight +
|
|
||||||
visionWeight +
|
|
||||||
riskWeight +
|
|
||||||
workWeight +
|
|
||||||
cultureWeight +
|
|
||||||
communicationWeight);
|
|
||||||
if (weightSum != 1) {
|
|
||||||
debugPrint(
|
|
||||||
'DEBUG Info --> calculateMatchScore : Weights Sum $weightSum != 1');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Score on locations distance
|
// Score on locations distance
|
||||||
double distance = shortestDistanceBetweenUsers(currentUser, otherUser);
|
double distance = shortestDistanceBetweenUsers(currentUser, otherUser);
|
||||||
double distanceScore = _distanceToPercentage(distance);
|
double distanceScore = _distanceToPoints(distance);
|
||||||
|
|
||||||
|
// Score on common languages
|
||||||
|
List<Language> currentLang = currentUser.languages;
|
||||||
|
List<Language> otherLang = otherUser.languages;
|
||||||
|
int matchingLanguages =
|
||||||
|
currentLang.toSet().intersection(otherLang.toSet()).length;
|
||||||
|
int langScore = 0;
|
||||||
|
if (matchingLanguages >= 3) {
|
||||||
|
langScore = 10;
|
||||||
|
} else if (matchingLanguages == 2) {
|
||||||
|
langScore = 9;
|
||||||
|
} else if (matchingLanguages == 1) {
|
||||||
|
langScore = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Score on common Sectors
|
||||||
|
List<SectorOption> currentSectors = currentUser.sectors;
|
||||||
|
List<SectorOption> otherSectors = otherUser.sectors;
|
||||||
|
int matchingSectors =
|
||||||
|
currentSectors.toSet().intersection(otherSectors.toSet()).length;
|
||||||
|
int sectorScore = 0;
|
||||||
|
if (matchingSectors >= 4) {
|
||||||
|
sectorScore = 10;
|
||||||
|
} else if (matchingSectors == 3) {
|
||||||
|
sectorScore = 9;
|
||||||
|
} else if (matchingSectors == 2) {
|
||||||
|
sectorScore = 7;
|
||||||
|
} else if (matchingSectors == 1) {
|
||||||
|
sectorScore = 5;
|
||||||
|
}
|
||||||
|
|
||||||
// Score on skills
|
// Score on skills
|
||||||
int matchingSkillsSought = currentUser.skillsSought
|
int matchingSkillsSought = currentUser.skillsSought
|
||||||
.toSet()
|
.toSet()
|
||||||
.intersection(otherUser.skills.toSet())
|
.intersection(otherUser.skills.toSet())
|
||||||
.length;
|
.length;
|
||||||
int matchingSkillsOffered = otherUser.skills
|
int matchingSkillsOffered = currentUser.skills
|
||||||
.toSet()
|
.toSet()
|
||||||
.intersection(currentUser.skillsSought.toSet())
|
.intersection(otherUser.skillsSought.toSet())
|
||||||
.length;
|
.length;
|
||||||
|
|
||||||
int skillsSought = currentUser.skillsSought.length;
|
|
||||||
int skillsOffered = otherUser.skills.length;
|
int skillsOffered = otherUser.skills.length;
|
||||||
|
|
||||||
// Idea: Calculate sum of matching skills divided by amount of skills listed.
|
int scoreSought = 0;
|
||||||
// As each list can have up to 3 skills max, this gives the following equation
|
if (matchingSkillsSought >= 3) {
|
||||||
// with 3 skills: 0 1/3 2/3 3/3; with 2 skills: 0 1/2 2/2; with 1 skill: 0 1.
|
scoreSought = 15;
|
||||||
// In total this will result in a total of 5 different states:
|
} else if (matchingSkillsSought == 2) {
|
||||||
// [0], [1/3], [1/2], [2/3], and [1].
|
scoreSought = 12;
|
||||||
|
} else if (matchingSkillsSought == 1) {
|
||||||
double valueSought = matchingSkillsSought / skillsSought;
|
scoreSought = 9;
|
||||||
int scoreSought;
|
|
||||||
if (valueSought == 1) {
|
|
||||||
scoreSought = 4;
|
|
||||||
} else if (valueSought == 2 / 3) {
|
|
||||||
scoreSought = 3;
|
|
||||||
} else if (valueSought == 1 / 2) {
|
|
||||||
scoreSought = 2;
|
|
||||||
} else if (valueSought == 1 / 3) {
|
|
||||||
scoreSought = 1;
|
|
||||||
} else {
|
|
||||||
scoreSought = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double valueOffered = matchingSkillsOffered / skillsOffered;
|
double valueOffered = matchingSkillsOffered / skillsOffered;
|
||||||
int scoreOffered;
|
int scoreOffered;
|
||||||
if (valueOffered == 1) {
|
if (valueOffered == 1) {
|
||||||
scoreOffered = 4;
|
scoreOffered = 15;
|
||||||
|
} else if (valueOffered == 4 / 5) {
|
||||||
|
scoreOffered = 14;
|
||||||
|
} else if (valueOffered == 3 / 4) {
|
||||||
|
scoreOffered = 13;
|
||||||
} else if (valueOffered == 2 / 3) {
|
} else if (valueOffered == 2 / 3) {
|
||||||
scoreOffered = 3;
|
scoreOffered = 12;
|
||||||
|
} else if (valueOffered == 3 / 5) {
|
||||||
|
scoreOffered = 11;
|
||||||
} else if (valueOffered == 1 / 2) {
|
} else if (valueOffered == 1 / 2) {
|
||||||
scoreOffered = 2;
|
scoreOffered = 10;
|
||||||
|
} else if (valueOffered == 2 / 5) {
|
||||||
|
scoreOffered = 9;
|
||||||
} else if (valueOffered == 1 / 3) {
|
} else if (valueOffered == 1 / 3) {
|
||||||
scoreOffered = 1;
|
scoreOffered = 8;
|
||||||
|
} else if (valueOffered == 1 / 4) {
|
||||||
|
scoreOffered = 7;
|
||||||
|
} else if (valueOffered == 1 / 5) {
|
||||||
|
scoreOffered = 6;
|
||||||
} else {
|
} else {
|
||||||
scoreOffered = 0;
|
scoreOffered = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int skillsScore = scoreSought + scoreOffered; // 8 points max
|
double skillsScore = (scoreSought + scoreOffered) / 1.5;
|
||||||
|
|
||||||
// Score on availability
|
// Score on availability
|
||||||
int availabilityScore;
|
int availabilityScore;
|
||||||
AvailabilityOption currentAvail = currentUser.availability;
|
AvailabilityOption currentAvail = currentUser.availability;
|
||||||
AvailabilityOption otherAvail = otherUser.availability;
|
AvailabilityOption otherAvail = otherUser.availability;
|
||||||
|
|
||||||
if (currentAvail == AvailabilityOption.flexible ||
|
if (currentAvail != otherAvail &&
|
||||||
otherAvail == AvailabilityOption.flexible ||
|
(currentAvail == AvailabilityOption.flexible ||
|
||||||
currentAvail == otherAvail) {
|
otherAvail == AvailabilityOption.flexible)) {
|
||||||
availabilityScore = 3;
|
availabilityScore = 4;
|
||||||
} else {
|
} else {
|
||||||
int availabilityDifference = (currentAvail.index - otherAvail.index).abs();
|
int availabilityDifference = (currentAvail.index - otherAvail.index).abs();
|
||||||
availabilityScore = 3 - availabilityDifference;
|
// map possible values [0 1 2 3] to points {0 1 3 5]
|
||||||
|
availabilityScore = (3 - availabilityDifference) * 2 - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Score on Vision
|
// Score on Vision
|
||||||
|
@ -223,15 +229,20 @@ double calculateMatchScore(UserProfile currentUser, UserProfile otherUser) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Score on Risk
|
// Score on Risk
|
||||||
|
RiskTolerance currentRisk = currentUser.risk;
|
||||||
|
RiskTolerance otherRisk = currentUser.risk;
|
||||||
int riskScore = 0;
|
int riskScore = 0;
|
||||||
if (currentUser.risk == otherUser.risk) {
|
if (currentUser.risk == otherUser.risk) {
|
||||||
riskScore = 1;
|
riskScore = 3;
|
||||||
|
} else {
|
||||||
|
int riskDifference = (currentRisk.index - otherRisk.index).abs();
|
||||||
|
riskScore = 3 - riskDifference;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Score on CorporateCulture
|
// Score on CorporateCulture
|
||||||
int cultureScore = 0;
|
int cultureScore = 0;
|
||||||
if (currentUser.culture == otherUser.culture) {
|
if (currentUser.culture == otherUser.culture) {
|
||||||
cultureScore = 1;
|
cultureScore = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Score on Communication
|
// Score on Communication
|
||||||
|
@ -242,43 +253,45 @@ double calculateMatchScore(UserProfile currentUser, UserProfile otherUser) {
|
||||||
|
|
||||||
// Calc total score. Sum of each score divided by its own max score value,
|
// Calc total score. Sum of each score divided by its own max score value,
|
||||||
// multiplied with its own weight.
|
// multiplied with its own weight.
|
||||||
double totalScore = (distanceWeight * distanceScore / 100) +
|
double totalScore = distanceScore +
|
||||||
(skillWeight * skillsScore / 8) +
|
langScore +
|
||||||
(availabilityWeight * availabilityScore / 3) +
|
sectorScore +
|
||||||
(visionWeight * visionScore / 4) +
|
skillsScore +
|
||||||
(workWeight * workScore / 4) +
|
availabilityScore +
|
||||||
(riskWeight * riskScore) +
|
riskScore +
|
||||||
(cultureWeight * cultureScore) +
|
visionScore +
|
||||||
(communicationWeight * communicationScore);
|
workScore +
|
||||||
|
cultureScore +
|
||||||
|
communicationScore;
|
||||||
|
|
||||||
return totalScore * 100;
|
return min(totalScore, 99.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
double _distanceToPercentage(double distance) {
|
double _distanceToPoints(double distance) {
|
||||||
// Self predefined data points
|
// Self predefined data points
|
||||||
final List<double> distances = [0, 5, 50, 100, 200];
|
final List<double> distances = [0, 10, 100, 200, 500, 700, 1000];
|
||||||
final List<double> percentages = [100, 99.5, 95, 90, 50];
|
final List<double> points = [60, 55, 40, 20, 10, 5, 0];
|
||||||
|
|
||||||
if (distance.isNaN || distance >= distances.last) {
|
if (distance.isNaN || distance >= distances.last) {
|
||||||
return percentages.last;
|
return points.last;
|
||||||
} else if (distance <= distances[0]) {
|
} else if (distance <= distances[0]) {
|
||||||
return percentages[0];
|
return points[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Linear interpolation
|
// Linear interpolation
|
||||||
for (int i = 1; i < distances.length; i++) {
|
for (int i = 1; i < distances.length; i++) {
|
||||||
if (distances[i] >= distance) {
|
if (distances[i] >= distance) {
|
||||||
double x0 = distances[i - 1];
|
double x0 = distances[i - 1];
|
||||||
double y0 = percentages[i - 1];
|
double y0 = points[i - 1];
|
||||||
double x1 = distances[i];
|
double x1 = distances[i];
|
||||||
double y1 = percentages[i];
|
double y1 = points[i];
|
||||||
|
|
||||||
// Interpolate
|
// Interpolate
|
||||||
double percentage = y0 + (y1 - y0) * (distance - x0) / (x1 - x0);
|
double result = y0 + (y1 - y0) * (distance - x0) / (x1 - x0);
|
||||||
return percentage;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback return value, though code should never reach here
|
// Fallback return value, though code should never reach here
|
||||||
return percentages.last; // 50
|
return points.last; // 50
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue