hevy-shared 1.0.710 → 1.0.712
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/built/filterExercises.d.ts +5 -7
- package/built/filterExercises.js +30 -147
- package/built/index.d.ts +2 -0
- package/package.json +1 -2
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import Fuse from 'fuse.js';
|
|
2
1
|
import { EquipmentFilter, Language, LibraryExercise, MuscleGroupFilter, CustomExercise } from './index';
|
|
3
2
|
export interface SearchableLibraryExercise extends LibraryExercise {
|
|
4
3
|
localized_muscle_group_name: string;
|
|
@@ -21,12 +20,11 @@ interface FilterExercisesProps {
|
|
|
21
20
|
searchText: string;
|
|
22
21
|
language: Language;
|
|
23
22
|
}
|
|
24
|
-
export declare const
|
|
25
|
-
export
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
export declare const filterExercises: ({ exercises, muscleGroupFilter, equipmentType, searchText, language, }: FilterExercisesProps) => (CustomExercise | LibraryExercise)[];
|
|
23
|
+
export declare const getExerciseMatches: ({ exercises, muscleGroupFilter, equipmentType, searchText, language, }: FilterExercisesProps) => ExerciseSearchMatch<SearchableExerciseTemplate>[];
|
|
24
|
+
export type ExerciseSearchMatch<T> = {
|
|
25
|
+
exercise: T;
|
|
26
|
+
matchType: 'title' | 'muscle_group' | 'other' | 'custom';
|
|
27
|
+
};
|
|
30
28
|
/**
|
|
31
29
|
* Exercise templates that are shown at the top of the Exercise Library to
|
|
32
30
|
* users who don't have any workouts logged.
|
package/built/filterExercises.js
CHANGED
|
@@ -1,41 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.popularExerciseTemplateIds = exports.
|
|
7
|
-
const fuse_js_1 = __importDefault(require("fuse.js"));
|
|
3
|
+
exports.popularExerciseTemplateIds = exports.getExerciseMatches = void 0;
|
|
8
4
|
const utils_1 = require("./utils");
|
|
9
5
|
const lodash_1 = require("lodash");
|
|
10
|
-
const
|
|
11
|
-
const stringSimilarityFuseInstance = new fuse_js_1.default([''], {
|
|
12
|
-
includeScore: true,
|
|
13
|
-
threshold: 0.4,
|
|
14
|
-
location: 0, // Prefer matches at the beginning of the string
|
|
15
|
-
});
|
|
16
|
-
return stringSimilarityFuseInstance;
|
|
17
|
-
};
|
|
18
|
-
exports.createFuseInstance = createFuseInstance;
|
|
19
|
-
const newFilterExercises = ({ fuseInstance, exercises, muscleGroupFilter, equipmentType, searchText, language, muscleGroupMatchPenalty, }) => {
|
|
6
|
+
const getExerciseMatches = ({ exercises, muscleGroupFilter, equipmentType, searchText, language, }) => {
|
|
20
7
|
let result = exercises;
|
|
21
8
|
result = filterExercisesWithMuscleGroup(muscleGroupFilter, result);
|
|
22
9
|
result = filterExercisesWithEquipment(equipmentType, result);
|
|
23
10
|
const normalizedSearchText = normalizeSearchText(searchText, language);
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return
|
|
11
|
+
let matches = filterExercisesWithSearchText(normalizedSearchText, result, language);
|
|
12
|
+
matches = orderExercisesWithSearchText(normalizedSearchText, matches);
|
|
13
|
+
return matches;
|
|
27
14
|
};
|
|
28
|
-
exports.
|
|
29
|
-
const filterExercises = ({ exercises, muscleGroupFilter, equipmentType, searchText, language, }) => {
|
|
30
|
-
let result = exercises;
|
|
31
|
-
result = filterExercisesWithMuscleGroup(muscleGroupFilter, result);
|
|
32
|
-
result = filterExercisesWithEquipment(equipmentType, result);
|
|
33
|
-
const normalizedSearchText = normalizeSearchText(searchText, language);
|
|
34
|
-
result = filterExercisesWithSearchText(normalizedSearchText, result, language);
|
|
35
|
-
result = orderExercisesWithSearchText(normalizedSearchText, result);
|
|
36
|
-
return result;
|
|
37
|
-
};
|
|
38
|
-
exports.filterExercises = filterExercises;
|
|
15
|
+
exports.getExerciseMatches = getExerciseMatches;
|
|
39
16
|
const filterExercisesWithMuscleGroup = (muscleGroup, exercises) => {
|
|
40
17
|
if (muscleGroup === 'all_muscles') {
|
|
41
18
|
return exercises;
|
|
@@ -48,30 +25,13 @@ const filterExercisesWithEquipment = (equipmentType, exercises) => {
|
|
|
48
25
|
}
|
|
49
26
|
return exercises.filter((rd) => rd.equipment_category === equipmentType);
|
|
50
27
|
};
|
|
51
|
-
const fuseScoreToSimilarity = (score) => {
|
|
52
|
-
if (score === 0)
|
|
53
|
-
return 'exact';
|
|
54
|
-
if (score < 0.05)
|
|
55
|
-
return 'extremely-similar';
|
|
56
|
-
if (score < 0.3)
|
|
57
|
-
return 'very-similar';
|
|
58
|
-
if (score < 0.6)
|
|
59
|
-
return 'somewhat-similar';
|
|
60
|
-
return 'not-similar';
|
|
61
|
-
};
|
|
62
|
-
const getStringSimilarityScore = (searchString, targetString, fuseInstance) => {
|
|
63
|
-
var _a, _b;
|
|
64
|
-
fuseInstance.setCollection([targetString]);
|
|
65
|
-
const result = fuseInstance.search(searchString);
|
|
66
|
-
const score = (_b = (_a = result[0]) === null || _a === void 0 ? void 0 : _a.score) !== null && _b !== void 0 ? _b : 1.0;
|
|
67
|
-
return score;
|
|
68
|
-
};
|
|
69
28
|
// Old filter exercise functionality, will be removed when new feature goes live
|
|
70
29
|
const filterExercisesWithSearchText = (searchText, exercises, language) => {
|
|
71
30
|
if (searchText.length === 0) {
|
|
72
|
-
return exercises;
|
|
31
|
+
return exercises.map((e) => ({ exercise: e, matchType: 'other' }));
|
|
73
32
|
}
|
|
74
|
-
|
|
33
|
+
const matches = [];
|
|
34
|
+
for (const e of exercises) {
|
|
75
35
|
const searchableSearchText = searchable(searchText);
|
|
76
36
|
const searchableEnglishTitle = searchable(e.title);
|
|
77
37
|
const searchableLocalizedTitleMap = !e.is_custom
|
|
@@ -99,13 +59,18 @@ const filterExercisesWithSearchText = (searchText, exercises, language) => {
|
|
|
99
59
|
const searchableTags = !e.is_custom && e.manual_tag ? searchable(e.manual_tag) : '';
|
|
100
60
|
const searchableAka = !e.is_custom && e.aka ? searchable(e.aka) : '';
|
|
101
61
|
if (searchableLocalizedTitle.includes(searchableSearchText) ||
|
|
102
|
-
searchableEnglishTitle.includes(searchableSearchText)
|
|
103
|
-
|
|
62
|
+
searchableEnglishTitle.includes(searchableSearchText)) {
|
|
63
|
+
matches.push({ exercise: e, matchType: 'title' });
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
else if (searchableLocalizedMuscleGroupName.includes(searchableSearchText) ||
|
|
104
67
|
searchableMuscleGroup.includes(searchableSearchText)) {
|
|
105
|
-
|
|
68
|
+
matches.push({ exercise: e, matchType: 'muscle_group' });
|
|
69
|
+
continue;
|
|
106
70
|
}
|
|
107
71
|
if (e.is_custom && 'custom'.includes(searchableSearchText)) {
|
|
108
|
-
|
|
72
|
+
matches.push({ exercise: e, matchType: 'custom' });
|
|
73
|
+
continue;
|
|
109
74
|
}
|
|
110
75
|
const splitSearch = searchableSearchText.split(' ');
|
|
111
76
|
const splitTitle = [
|
|
@@ -121,111 +86,29 @@ const filterExercisesWithSearchText = (searchText, exercises, language) => {
|
|
|
121
86
|
// title ['arnold', 'press', '(barbell)']
|
|
122
87
|
// search ['press', 'bar']
|
|
123
88
|
if ((0, lodash_1.intersectionWith)(splitSearch, splitTitle, (search, title) => title.includes(search)).length === splitSearch.length) {
|
|
124
|
-
|
|
89
|
+
matches.push({ exercise: e, matchType: 'other' });
|
|
90
|
+
continue;
|
|
125
91
|
}
|
|
126
|
-
return false;
|
|
127
|
-
});
|
|
128
|
-
};
|
|
129
|
-
const newFilterExercisesWithSearchText = (fuseInstance, searchText, exercises, language,
|
|
130
|
-
// 0 means no penalty, 1 means don't match muscle groups (because a score > 1 means no match)
|
|
131
|
-
muscleGroupMatchPenalty) => {
|
|
132
|
-
if (searchText.length === 0) {
|
|
133
|
-
return exercises;
|
|
134
92
|
}
|
|
135
|
-
return
|
|
136
|
-
const searchableSearchText = searchable(searchText);
|
|
137
|
-
const searchableEnglishTitle = searchable(e.title);
|
|
138
|
-
const searchableLocalizedTitleMap = !e.is_custom
|
|
139
|
-
? {
|
|
140
|
-
en: searchable(e.title),
|
|
141
|
-
es: e.es_title ? searchable(e.es_title) : undefined,
|
|
142
|
-
de: e.de_title ? searchable(e.de_title) : undefined,
|
|
143
|
-
fr: e.fr_title ? searchable(e.fr_title) : undefined,
|
|
144
|
-
it: e.it_title ? searchable(e.it_title) : undefined,
|
|
145
|
-
pt: e.pt_title ? searchable(e.pt_title) : undefined,
|
|
146
|
-
tr: e.tr_title ? searchable(e.tr_title) : undefined,
|
|
147
|
-
zh_CN: e.zh_cn_title ? searchable(e.zh_cn_title) : undefined,
|
|
148
|
-
zh_TW: e.zh_tw_title ? searchable(e.zh_tw_title) : undefined,
|
|
149
|
-
ru: e.ru_title ? searchable(e.ru_title) : undefined,
|
|
150
|
-
ja: e.ja_title ? searchable(e.ja_title) : undefined,
|
|
151
|
-
ko: e.ko_title ? searchable(e.ko_title) : undefined,
|
|
152
|
-
}
|
|
153
|
-
: {
|
|
154
|
-
en: searchable(e.title),
|
|
155
|
-
};
|
|
156
|
-
const searchableLocalizedTitle = searchableLocalizedTitleMap[language] || searchableLocalizedTitleMap.en;
|
|
157
|
-
const searchableLocalizedMuscleGroupName = searchable(e.localized_muscle_group_name);
|
|
158
|
-
const searchableMuscleGroup = searchable(e.muscle_group);
|
|
159
|
-
const searchableMisspelledDumbbellEquipment = e.equipment_category === 'dumbbell' ? 'dumbell' : '';
|
|
160
|
-
const searchableTags = !e.is_custom && e.manual_tag ? searchable(e.manual_tag) : '';
|
|
161
|
-
const searchableAka = !e.is_custom && e.aka ? searchable(e.aka) : '';
|
|
162
|
-
const englishSimilarityScore = getStringSimilarityScore(searchableSearchText, searchableEnglishTitle, fuseInstance);
|
|
163
|
-
const localizedSimilarityScore = getStringSimilarityScore(searchableSearchText, searchableLocalizedTitle, fuseInstance);
|
|
164
|
-
let englishMuscleGroupSimilarityScore = 1;
|
|
165
|
-
let muscleGroupSimilarityScore = 1;
|
|
166
|
-
if (muscleGroupMatchPenalty < 1) {
|
|
167
|
-
englishMuscleGroupSimilarityScore = getStringSimilarityScore(searchableSearchText, searchableMuscleGroup, fuseInstance);
|
|
168
|
-
muscleGroupSimilarityScore = getStringSimilarityScore(searchableSearchText, searchableLocalizedMuscleGroupName, fuseInstance);
|
|
169
|
-
}
|
|
170
|
-
// We always return the best score, regardless of where the match happens
|
|
171
|
-
const bestScore = Math.min(englishSimilarityScore, localizedSimilarityScore, englishMuscleGroupSimilarityScore + muscleGroupMatchPenalty, muscleGroupSimilarityScore + muscleGroupMatchPenalty);
|
|
172
|
-
if (fuseScoreToSimilarity(englishSimilarityScore) !== 'not-similar') {
|
|
173
|
-
accu.push(Object.assign(Object.assign({}, e), { searchStringScore: bestScore }));
|
|
174
|
-
return accu;
|
|
175
|
-
}
|
|
176
|
-
if (fuseScoreToSimilarity(localizedSimilarityScore) !== 'not-similar') {
|
|
177
|
-
accu.push(Object.assign(Object.assign({}, e), { searchStringScore: bestScore }));
|
|
178
|
-
return accu;
|
|
179
|
-
}
|
|
180
|
-
if (['exact', 'extremely-similar'].includes(fuseScoreToSimilarity(englishMuscleGroupSimilarityScore))) {
|
|
181
|
-
accu.push(Object.assign(Object.assign({}, e), { searchStringScore: bestScore }));
|
|
182
|
-
return accu;
|
|
183
|
-
}
|
|
184
|
-
if (['exact', 'extremely-similar'].includes(fuseScoreToSimilarity(muscleGroupSimilarityScore))) {
|
|
185
|
-
accu.push(Object.assign(Object.assign({}, e), { searchStringScore: bestScore }));
|
|
186
|
-
return accu;
|
|
187
|
-
}
|
|
188
|
-
if (e.is_custom && 'custom'.includes(searchableSearchText)) {
|
|
189
|
-
accu.push(e);
|
|
190
|
-
return accu;
|
|
191
|
-
}
|
|
192
|
-
const splitSearch = searchableSearchText.split(' ');
|
|
193
|
-
const splitTitle = [
|
|
194
|
-
searchableLocalizedTitle,
|
|
195
|
-
searchableEnglishTitle,
|
|
196
|
-
searchableTags,
|
|
197
|
-
searchableAka,
|
|
198
|
-
searchableMisspelledDumbbellEquipment,
|
|
199
|
-
]
|
|
200
|
-
.join(' ')
|
|
201
|
-
.split(' ');
|
|
202
|
-
// Find:
|
|
203
|
-
// title ['arnold', 'press', '(barbell)']
|
|
204
|
-
// search ['press', 'bar']
|
|
205
|
-
if ((0, lodash_1.intersectionWith)(splitSearch, splitTitle, (search, title) => title.includes(search)).length === splitSearch.length) {
|
|
206
|
-
accu.push(e);
|
|
207
|
-
return accu;
|
|
208
|
-
}
|
|
209
|
-
return accu;
|
|
210
|
-
}, []);
|
|
93
|
+
return matches;
|
|
211
94
|
};
|
|
212
|
-
const orderExercisesWithSearchText = (searchText,
|
|
95
|
+
const orderExercisesWithSearchText = (searchText, exerciseMatches) => {
|
|
213
96
|
if (searchText.length === 0) {
|
|
214
|
-
return
|
|
97
|
+
return exerciseMatches;
|
|
215
98
|
}
|
|
216
|
-
return
|
|
217
|
-
.reduce((accu,
|
|
218
|
-
const lowercaseTitle =
|
|
99
|
+
return exerciseMatches
|
|
100
|
+
.reduce((accu, currentMatch) => {
|
|
101
|
+
const lowercaseTitle = currentMatch.exercise.title.toLowerCase();
|
|
219
102
|
if (lowercaseTitle.startsWith(searchText)) {
|
|
220
103
|
accu.push({
|
|
221
|
-
exercise:
|
|
222
|
-
weight:
|
|
104
|
+
exercise: currentMatch,
|
|
105
|
+
weight: currentMatch.exercise.priority * 2,
|
|
223
106
|
});
|
|
224
107
|
return accu;
|
|
225
108
|
}
|
|
226
109
|
accu.push({
|
|
227
|
-
exercise:
|
|
228
|
-
weight:
|
|
110
|
+
exercise: currentMatch,
|
|
111
|
+
weight: currentMatch.exercise.priority,
|
|
229
112
|
});
|
|
230
113
|
return accu;
|
|
231
114
|
}, [])
|
package/built/index.d.ts
CHANGED
|
@@ -1198,6 +1198,8 @@ export interface OutstandingInvitesForCoachTeamResponse {
|
|
|
1198
1198
|
invites: CoachTeamInvite[];
|
|
1199
1199
|
}
|
|
1200
1200
|
export interface HevyTrainerProgram {
|
|
1201
|
+
created_at: string;
|
|
1202
|
+
updated_at: string;
|
|
1201
1203
|
title: string;
|
|
1202
1204
|
level: TrainingLevel;
|
|
1203
1205
|
goal: TrainingGoal;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hevy-shared",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.712",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "built/index.js",
|
|
6
6
|
"types": "built/index.d.ts",
|
|
@@ -35,7 +35,6 @@
|
|
|
35
35
|
"typescript": "5.8.2"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"fuse.js": "^7.0.0",
|
|
39
38
|
"lodash": "^4.17.21"
|
|
40
39
|
}
|
|
41
40
|
}
|