UNPKG

6.74 kBJavaScriptView Raw
1import similarity from 'string-similarity';
2
3import {
4 addEntity as addScore,
5 getEntity as getScore,
6 updateEntity as updateScore,
7} from '../../Services/Score';
8import {
9 getEntity as getActivity,
10 updateEntity as updateActivity,
11} from '../../Services/Activity';
12import { getUser } from '../../Services/User';
13import { notifyMatchedActivity } from '../../Services/Notifier';
14
15const DEFAULT_VALUES = {
16 distance: '50',
17 unit: 'km',
18};
19
20const getDefinedUser = (user) => {
21 const userIsDefined = user != null && user !== undefined;
22 return userIsDefined;
23};
24
25const fillActivities = async (user) => {
26 const activities = await Promise.all(user.activitiesID.map(getActivity));
27 return { ...user, activities };
28};
29
30const hasActivities = user => user && user.activitiesID && user.activitiesID.length > 0;
31
32const getCurrentUser = (users, key) => users
33 .filter(getDefinedUser)
34 .filter(user => user.userID === key);
35
36const isNotCurrentUser = (user, key) => user.userID !== key;
37
38const isRequest = activity => activity.type === 'request';
39
40const isSerach = activity => activity.type === 'search';
41
42const isActive = activity => activity.active;
43
44const hasPositiveScore = (users, userID) => users.map(user => user.userID).includes(userID);
45
46const hasSearchActivity = (user) => {
47 if (user.activities && user.activities.length > 0) return false;
48
49 return user.activities.filter(isSerach).length > 0;
50};
51
52const hasRequestActivity = user => user.activities.filter(isRequest).length > 0;
53
54const getScoreActivities = (request, searchActivities) =>
55 searchActivities.map(search => getScoreActivity(search, request));
56
57const getScoreActivity = (search, request) => {
58 const scoreName = similarity.compareTwoStrings(search.name, request.name);
59
60 const scoreDescription = similarity.compareTwoStrings(search.description, request.description);
61
62 const scoreActivity = similarity.compareTwoStrings(search.activity, request.activity);
63
64 const scoreSkills = similarity.compareTwoStrings(
65 search.skills.toString(),
66 request.skills.toString()
67 );
68
69 const scoreSkillDescription = similarity.compareTwoStrings(
70 search.skills.toString(),
71 request.description
72 );
73
74 const scoreDescriptionSkill = similarity.compareTwoStrings(
75 search.description,
76 request.skills.toString()
77 );
78
79 const total = scoreName
80 + scoreDescription
81 + scoreActivity
82 + scoreSkills
83 + scoreSkillDescription
84 + scoreDescriptionSkill;
85
86 console.log('-------------------------------------------------------------------------');
87 console.log(`[${search.userID} | ${request.userID}]`);
88 console.log('-------------------------------------------------------------------------');
89 console.log('scoreName:', scoreName);
90 console.log('scoreDescription:', scoreDescription);
91 console.log('scoreActivity:', scoreActivity);
92 console.log('scoreSkills:', scoreSkills);
93 console.log('scoreSkillDescription:', scoreSkillDescription);
94 console.log('scoreDescriptionSkill:', scoreDescriptionSkill);
95 console.log('SEARCH ACTIVITY ID:', search.activityID);
96 console.log('REQUEST ACTIVITY ID:', request.activityID);
97 console.log('-------------------------------------------------------------------------');
98 console.log('TOTAL:', total / 6);
99 console.log('-------------------------------------------------------------------------');
100 console.log('*************************************************************************');
101
102 return {
103 score: total / 6,
104 activitySearchID: search.activityID,
105 activityRequestID: request.activityID,
106 scoreID: search.activityID + request.activityID,
107 };
108};
109
110export default () => ({
111 execMatchingWorkflow: async (location, getCloseUsersLocations) => {
112 const matchedUsers = await getCloseUsersLocations({
113 id: location.collectionID,
114 key: location.key,
115 distance: location.distance || DEFAULT_VALUES.distance,
116 unit: location.unit || DEFAULT_VALUES.unit,
117 });
118
119 if (!matchedUsers) return matchedUsers;
120
121 const users = await Promise.all(matchedUsers
122 .map(user => user.userName)
123 .map(getUser));
124
125 const currentUser = getCurrentUser(users, location.key)[0];
126
127 if (!hasActivities(currentUser)) return matchedUsers;
128
129 const currentUserWithSearchActivities = await fillActivities(currentUser);
130
131 if (!hasSearchActivity(currentUserWithSearchActivities)) return matchedUsers;
132
133 const usersWithActivities = await Promise.all(users
134 .filter(getDefinedUser)
135 .filter(user => isNotCurrentUser(user, location.key))
136 .filter(hasActivities)
137 .map(fillActivities));
138
139 const usersWithRequestActivitiesActive = usersWithActivities
140 .filter(hasRequestActivity);
141
142 const userWithMatchedActivities = usersWithRequestActivitiesActive.map((user) => {
143 const userScores = user.activities
144 .filter(isRequest)
145 .map((request) => {
146 const requestScores = getScoreActivities(request, currentUserWithSearchActivities.activities);
147 return requestScores;
148 });
149 const mergedUserScores = [].concat(...userScores);
150 return { ...user, scores: mergedUserScores };
151 });
152
153 const userWithPositiveMatchedActivities = [].concat(...userWithMatchedActivities
154 .map((user) => {
155 const positivesScores = user.scores.filter(score => score.score > 0.5);
156 return { ...user, scores: positivesScores };
157 }));
158
159 userWithPositiveMatchedActivities.forEach(user =>
160 user.scores.forEach(async (score) => {
161 const existingScore = await getScore(score.scoreID);
162
163 const searchActivity = currentUserWithSearchActivities.activities
164 .filter(activity => activity.activityID === score.activitySearchID)[0];
165 const matchedActivitiesID = searchActivity.matchedActivitiesID
166 ? searchActivity.matchedActivitiesID
167 : [];
168
169 if (!existingScore) {
170 addScore(score);
171
172 updateActivity({
173 activityID: score.activitySearchID,
174 matchedActivitiesID: [...matchedActivitiesID, score.activityRequestID],
175 });
176
177 notifyMatchedActivity(currentUserWithSearchActivities, searchActivity, user);
178 } else if (score.socre !== existingScore.score) {
179 updateScore(score);
180 }
181 }));
182
183 return matchedUsers.filter(user => hasPositiveScore(userWithPositiveMatchedActivities, user.userName));
184 },
185 acceptToMeetWorkflow: async () => {
186 // const requestActivity = usersWithRequestActivitiesActive
187 // .filter(activity => activity.activityID === score.activityRequestID)[0];
188 // updateActivity({
189 // activityID: score.activityRequestID,
190 // matchedActivitiesID: [...requestActivity.matchedActivitiesID, score.activitySearchID],
191 // });
192 },
193});