hevy-shared 1.0.699 → 1.0.701
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 +6 -0
- package/built/filterExercises.js +126 -1
- package/built/index.d.ts +3 -0
- package/package.json +2 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import Fuse from 'fuse.js';
|
|
1
2
|
import { EquipmentFilter, Language, LibraryExercise, MuscleGroupFilter, CustomExercise } from './index';
|
|
2
3
|
export interface SearchableLibraryExercise extends LibraryExercise {
|
|
3
4
|
localized_muscle_group_name: string;
|
|
@@ -20,6 +21,11 @@ interface FilterExercisesProps {
|
|
|
20
21
|
searchText: string;
|
|
21
22
|
language: Language;
|
|
22
23
|
}
|
|
24
|
+
export declare const createFuseInstance: () => Fuse<string>;
|
|
25
|
+
export declare const newFilterExercises: ({ fuseInstance, exercises, muscleGroupFilter, equipmentType, searchText, language, muscleGroupMatchPenalty, }: FilterExercisesProps & {
|
|
26
|
+
muscleGroupMatchPenalty: number;
|
|
27
|
+
fuseInstance: Fuse<string>;
|
|
28
|
+
}) => SearchableExerciseTemplateWithStringScore[];
|
|
23
29
|
export declare const filterExercises: ({ exercises, muscleGroupFilter, equipmentType, searchText, language, }: FilterExercisesProps) => (CustomExercise | LibraryExercise)[];
|
|
24
30
|
/**
|
|
25
31
|
* Exercise templates that are shown at the top of the Exercise Library to
|
package/built/filterExercises.js
CHANGED
|
@@ -1,8 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.popularExerciseTemplateIds = exports.filterExercises = void 0;
|
|
6
|
+
exports.popularExerciseTemplateIds = exports.filterExercises = exports.newFilterExercises = exports.createFuseInstance = void 0;
|
|
7
|
+
const fuse_js_1 = __importDefault(require("fuse.js"));
|
|
4
8
|
const utils_1 = require("./utils");
|
|
5
9
|
const lodash_1 = require("lodash");
|
|
10
|
+
const createFuseInstance = () => {
|
|
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, }) => {
|
|
20
|
+
let result = exercises;
|
|
21
|
+
result = filterExercisesWithMuscleGroup(muscleGroupFilter, result);
|
|
22
|
+
result = filterExercisesWithEquipment(equipmentType, result);
|
|
23
|
+
const normalizedSearchText = normalizeSearchText(searchText, language);
|
|
24
|
+
result = newFilterExercisesWithSearchText(fuseInstance, normalizedSearchText, result, language, muscleGroupMatchPenalty);
|
|
25
|
+
result = orderExercisesWithSearchText(normalizedSearchText, result);
|
|
26
|
+
return result;
|
|
27
|
+
};
|
|
28
|
+
exports.newFilterExercises = newFilterExercises;
|
|
6
29
|
const filterExercises = ({ exercises, muscleGroupFilter, equipmentType, searchText, language, }) => {
|
|
7
30
|
let result = exercises;
|
|
8
31
|
result = filterExercisesWithMuscleGroup(muscleGroupFilter, result);
|
|
@@ -25,6 +48,25 @@ const filterExercisesWithEquipment = (equipmentType, exercises) => {
|
|
|
25
48
|
}
|
|
26
49
|
return exercises.filter((rd) => rd.equipment_category === equipmentType);
|
|
27
50
|
};
|
|
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
|
+
// Old filter exercise functionality, will be removed when new feature goes live
|
|
28
70
|
const filterExercisesWithSearchText = (searchText, exercises, language) => {
|
|
29
71
|
if (searchText.length === 0) {
|
|
30
72
|
return exercises;
|
|
@@ -84,6 +126,89 @@ const filterExercisesWithSearchText = (searchText, exercises, language) => {
|
|
|
84
126
|
return false;
|
|
85
127
|
});
|
|
86
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
|
+
}
|
|
135
|
+
return exercises.reduce((accu, e) => {
|
|
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
|
+
}, []);
|
|
211
|
+
};
|
|
87
212
|
const orderExercisesWithSearchText = (searchText, exercises) => {
|
|
88
213
|
if (searchText.length === 0) {
|
|
89
214
|
return exercises;
|
package/built/index.d.ts
CHANGED
|
@@ -72,6 +72,7 @@ export interface AccountResponse {
|
|
|
72
72
|
is_coached: boolean;
|
|
73
73
|
birthday?: string;
|
|
74
74
|
sex?: Sex;
|
|
75
|
+
height_cm?: number;
|
|
75
76
|
}
|
|
76
77
|
export interface UserAccountResponse {
|
|
77
78
|
id: string;
|
|
@@ -106,6 +107,7 @@ export interface UserAccountResponse {
|
|
|
106
107
|
sex?: Sex;
|
|
107
108
|
email_consent: boolean;
|
|
108
109
|
email_verified: boolean;
|
|
110
|
+
height_cm?: number;
|
|
109
111
|
}
|
|
110
112
|
export interface CoachAppPushTarget {
|
|
111
113
|
type: 'android' | 'ios';
|
|
@@ -160,6 +162,7 @@ export interface AccountUpdate {
|
|
|
160
162
|
accepted_terms_and_conditions?: boolean;
|
|
161
163
|
sex?: Sex;
|
|
162
164
|
birthday?: string;
|
|
165
|
+
height_cm?: number;
|
|
163
166
|
}
|
|
164
167
|
export interface AppleSignUpRequest {
|
|
165
168
|
email?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hevy-shared",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.701",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "built/index.js",
|
|
6
6
|
"types": "built/index.d.ts",
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"typescript": "5.8.2"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
+
"fuse.js": "^7.0.0",
|
|
38
39
|
"lodash": "^4.17.21"
|
|
39
40
|
}
|
|
40
41
|
}
|