@sunsteel/contracts 0.69.0 → 0.71.0
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/dist/index.cjs +325 -3
- package/dist/index.d.cts +143 -10
- package/dist/index.d.ts +143 -10
- package/dist/index.js +304 -2
- package/package.json +40 -40
package/dist/index.cjs
CHANGED
|
@@ -37,6 +37,8 @@ __export(index_exports, {
|
|
|
37
37
|
ACTIVITY_REACTIONS: () => ACTIVITY_REACTIONS,
|
|
38
38
|
ACTIVITY_TYPES: () => ACTIVITY_TYPES,
|
|
39
39
|
ACTIVITY_TYPE_SECTIONS: () => ACTIVITY_TYPE_SECTIONS,
|
|
40
|
+
BAR_CHOICES_KG: () => BAR_CHOICES_KG,
|
|
41
|
+
BAR_WARM_UP_STEPS: () => BAR_WARM_UP_STEPS,
|
|
40
42
|
BLOCKED_MEMBERS_MAX: () => BLOCKED_MEMBERS_MAX,
|
|
41
43
|
CLONE_ROUTINE_REFUSALS: () => CLONE_ROUTINE_REFUSALS,
|
|
42
44
|
COMEBACK_MIN_INACTIVE_DAYS: () => COMEBACK_MIN_INACTIVE_DAYS,
|
|
@@ -64,6 +66,8 @@ __export(index_exports, {
|
|
|
64
66
|
FOLLOW_SUGGESTIONS_DEFAULT_LIMIT: () => FOLLOW_SUGGESTIONS_DEFAULT_LIMIT,
|
|
65
67
|
FOLLOW_SUGGESTIONS_MAX_LIMIT: () => FOLLOW_SUGGESTIONS_MAX_LIMIT,
|
|
66
68
|
FOLLOW_SUGGESTION_REASONS: () => FOLLOW_SUGGESTION_REASONS,
|
|
69
|
+
LIMITED_SHORTFALL_KG: () => LIMITED_SHORTFALL_KG,
|
|
70
|
+
MAX_SETS_PER_EXERCISE: () => MAX_SETS_PER_EXERCISE,
|
|
67
71
|
MEASURABLE_GOALS_MAX: () => MEASURABLE_GOALS_MAX,
|
|
68
72
|
MEASURABLE_GOAL_DIRECTIONS: () => MEASURABLE_GOAL_DIRECTIONS,
|
|
69
73
|
MEASURABLE_GOAL_TYPES: () => MEASURABLE_GOAL_TYPES,
|
|
@@ -79,12 +83,14 @@ __export(index_exports, {
|
|
|
79
83
|
NOTIFICATIONS_RETENTION_DAYS: () => NOTIFICATIONS_RETENTION_DAYS,
|
|
80
84
|
NOTIFICATION_CATEGORIES: () => NOTIFICATION_CATEGORIES,
|
|
81
85
|
NOTIFICATION_KINDS: () => NOTIFICATION_KINDS,
|
|
86
|
+
OTHER_WARM_UP_STEPS: () => OTHER_WARM_UP_STEPS,
|
|
82
87
|
PLATEAU_MIN_DAYS_SINCE_BEST: () => PLATEAU_MIN_DAYS_SINCE_BEST,
|
|
83
88
|
PLATEAU_MIN_SESSIONS: () => PLATEAU_MIN_SESSIONS,
|
|
84
89
|
PLATEAU_MIN_SESSIONS_MAX: () => PLATEAU_MIN_SESSIONS_MAX,
|
|
85
90
|
PLATEAU_MIN_SESSIONS_MIN: () => PLATEAU_MIN_SESSIONS_MIN,
|
|
86
91
|
PLATEAU_RECENT_DAYS: () => PLATEAU_RECENT_DAYS,
|
|
87
92
|
PLATEAU_WINDOW_DAYS: () => PLATEAU_WINDOW_DAYS,
|
|
93
|
+
PLATE_SETS: () => PLATE_SETS,
|
|
88
94
|
PREFERRED_TRAINING_STYLE_VALUES: () => PREFERRED_TRAINING_STYLE_VALUES,
|
|
89
95
|
PROFILE_BIO_MAX_LENGTH: () => PROFILE_BIO_MAX_LENGTH,
|
|
90
96
|
PROFILE_FAVORITE_EXERCISES_MAX: () => PROFILE_FAVORITE_EXERCISES_MAX,
|
|
@@ -140,6 +146,8 @@ __export(index_exports, {
|
|
|
140
146
|
SESSION_SHARE_DEFAULT_FIELDS: () => SESSION_SHARE_DEFAULT_FIELDS,
|
|
141
147
|
SESSION_SHARE_FIELDS: () => SESSION_SHARE_FIELDS,
|
|
142
148
|
SESSION_SHARE_MAX_ACTIVE_LINKS: () => SESSION_SHARE_MAX_ACTIVE_LINKS,
|
|
149
|
+
SET_KINDS: () => SET_KINDS,
|
|
150
|
+
SET_KIND_LABELS: () => SET_KIND_LABELS,
|
|
143
151
|
SEXES: () => SEXES,
|
|
144
152
|
SHARED_ROUTINE_SOURCES: () => SHARED_ROUTINE_SOURCES,
|
|
145
153
|
STARRED_EXERCISES_MAX: () => STARRED_EXERCISES_MAX,
|
|
@@ -175,15 +183,27 @@ __export(index_exports, {
|
|
|
175
183
|
WORKOUT_SESSION_STATUSES: () => WORKOUT_SESSION_STATUSES,
|
|
176
184
|
accountExportFileName: () => accountExportFileName,
|
|
177
185
|
applyDeload: () => applyDeload,
|
|
186
|
+
buildWarmUpRamp: () => buildWarmUpRamp,
|
|
187
|
+
calculatePlateLoading: () => calculatePlateLoading,
|
|
188
|
+
countsAsWork: () => countsAsWork,
|
|
189
|
+
countsForProgression: () => countsForProgression,
|
|
190
|
+
defaultWarmUpEquipment: () => defaultWarmUpEquipment,
|
|
178
191
|
deloadLengthDays: () => deloadLengthDays,
|
|
192
|
+
followWorkingLoad: () => followWorkingLoad,
|
|
193
|
+
isBarLoaded: () => isBarLoaded,
|
|
194
|
+
isSetKind: () => isSetKind,
|
|
179
195
|
isWithinQuietHours: () => isWithinQuietHours,
|
|
196
|
+
leadWorkingWeight: () => leadWorkingWeight,
|
|
180
197
|
matchesDeletionConfirmation: () => matchesDeletionConfirmation,
|
|
198
|
+
requiredToFinish: () => requiredToFinish,
|
|
181
199
|
resolveActiveTrainingBlock: () => resolveActiveTrainingBlock,
|
|
182
200
|
resolveRoutinePlan: () => resolveRoutinePlan,
|
|
183
201
|
routineDayLabel: () => routineDayLabel,
|
|
184
202
|
sessionCorrectionWindow: () => sessionCorrectionWindow,
|
|
203
|
+
setKindOf: () => setKindOf,
|
|
185
204
|
setLogValuesDiffer: () => setLogValuesDiffer,
|
|
186
|
-
trainingBlockCovers: () => trainingBlockCovers
|
|
205
|
+
trainingBlockCovers: () => trainingBlockCovers,
|
|
206
|
+
warmUpLoad: () => warmUpLoad
|
|
187
207
|
});
|
|
188
208
|
module.exports = __toCommonJS(index_exports);
|
|
189
209
|
|
|
@@ -511,6 +531,283 @@ var COMEBACK_WINDOW_DAYS = 14;
|
|
|
511
531
|
var COMEBACK_SESSION_LOOKBACK = 500;
|
|
512
532
|
var COMEBACK_RECOGNITION_LIMIT = 20;
|
|
513
533
|
|
|
534
|
+
// src/set-kinds.ts
|
|
535
|
+
var SET_KINDS = ["WORKING", "WARMUP", "DROP", "OPTIONAL"];
|
|
536
|
+
var SET_KIND_LABELS = {
|
|
537
|
+
WORKING: "Working",
|
|
538
|
+
WARMUP: "Warm-up",
|
|
539
|
+
DROP: "Drop",
|
|
540
|
+
OPTIONAL: "Optional"
|
|
541
|
+
};
|
|
542
|
+
function isSetKind(value) {
|
|
543
|
+
return SET_KINDS.includes(value);
|
|
544
|
+
}
|
|
545
|
+
function setKindOf(item) {
|
|
546
|
+
return item?.kind ?? "WORKING";
|
|
547
|
+
}
|
|
548
|
+
function countsAsWork(kind) {
|
|
549
|
+
return (kind ?? "WORKING") !== "WARMUP";
|
|
550
|
+
}
|
|
551
|
+
function countsForProgression(kind) {
|
|
552
|
+
const k = kind ?? "WORKING";
|
|
553
|
+
return k === "WORKING" || k === "OPTIONAL";
|
|
554
|
+
}
|
|
555
|
+
function requiredToFinish(kind) {
|
|
556
|
+
const k = kind ?? "WORKING";
|
|
557
|
+
return k === "WORKING" || k === "DROP";
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// src/plate-loading.ts
|
|
561
|
+
var CANONICAL_SCALE = 1e4;
|
|
562
|
+
var DENSE_CAPACITY_LIMIT = 2e5;
|
|
563
|
+
var toCanonicalUnits = (weightKg) => Math.round(weightKg * CANONICAL_SCALE);
|
|
564
|
+
var fromCanonicalUnits = (units) => units / CANONICAL_SCALE;
|
|
565
|
+
var greatestCommonDivisor = (left, right) => {
|
|
566
|
+
let a = Math.abs(left);
|
|
567
|
+
let b = Math.abs(right);
|
|
568
|
+
while (b > 0) {
|
|
569
|
+
const remainder = a % b;
|
|
570
|
+
a = b;
|
|
571
|
+
b = remainder;
|
|
572
|
+
}
|
|
573
|
+
return a;
|
|
574
|
+
};
|
|
575
|
+
var buildChunks = (plates, divisor) => {
|
|
576
|
+
const chunks = [];
|
|
577
|
+
plates.forEach((plate, plateIndex) => {
|
|
578
|
+
const pairValue = Math.round(
|
|
579
|
+
toCanonicalUnits(plate.weightKg) * 2 / divisor
|
|
580
|
+
);
|
|
581
|
+
let remaining = plate.pairCount;
|
|
582
|
+
let chunkSize = 1;
|
|
583
|
+
while (remaining > 0) {
|
|
584
|
+
const quantity = Math.min(chunkSize, remaining);
|
|
585
|
+
chunks.push({
|
|
586
|
+
plateIndex,
|
|
587
|
+
quantity,
|
|
588
|
+
value: pairValue * quantity
|
|
589
|
+
});
|
|
590
|
+
remaining -= quantity;
|
|
591
|
+
chunkSize *= 2;
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
return chunks;
|
|
595
|
+
};
|
|
596
|
+
var reconstructSelection = (best, chunks, previousSum, previousChunk, plateCount) => {
|
|
597
|
+
const selection = Array.from({ length: plateCount }, () => 0);
|
|
598
|
+
let current = best;
|
|
599
|
+
while (current > 0) {
|
|
600
|
+
const chunkIndex = previousChunk(current);
|
|
601
|
+
if (chunkIndex < 0) break;
|
|
602
|
+
const chunk = chunks[chunkIndex];
|
|
603
|
+
selection[chunk.plateIndex] += chunk.quantity;
|
|
604
|
+
current = previousSum(current);
|
|
605
|
+
}
|
|
606
|
+
return selection;
|
|
607
|
+
};
|
|
608
|
+
var solveDense = (capacity, chunks, plateCount) => {
|
|
609
|
+
const reachable = new Uint8Array(capacity + 1);
|
|
610
|
+
const previousSum = new Int32Array(capacity + 1);
|
|
611
|
+
const previousChunk = new Int16Array(capacity + 1);
|
|
612
|
+
previousSum.fill(-1);
|
|
613
|
+
previousChunk.fill(-1);
|
|
614
|
+
reachable[0] = 1;
|
|
615
|
+
chunks.forEach((chunk, chunkIndex) => {
|
|
616
|
+
for (let sum = capacity; sum >= chunk.value; sum -= 1) {
|
|
617
|
+
if (!reachable[sum] && reachable[sum - chunk.value]) {
|
|
618
|
+
reachable[sum] = 1;
|
|
619
|
+
previousSum[sum] = sum - chunk.value;
|
|
620
|
+
previousChunk[sum] = chunkIndex;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
});
|
|
624
|
+
let best = capacity;
|
|
625
|
+
while (best > 0 && !reachable[best]) best -= 1;
|
|
626
|
+
return {
|
|
627
|
+
best,
|
|
628
|
+
selection: reconstructSelection(
|
|
629
|
+
best,
|
|
630
|
+
chunks,
|
|
631
|
+
(sum) => previousSum[sum],
|
|
632
|
+
(sum) => previousChunk[sum],
|
|
633
|
+
plateCount
|
|
634
|
+
)
|
|
635
|
+
};
|
|
636
|
+
};
|
|
637
|
+
var solveSparse = (capacity, chunks, plateCount) => {
|
|
638
|
+
const reachable = /* @__PURE__ */ new Map();
|
|
639
|
+
reachable.set(0, { previous: -1, chunkIndex: -1 });
|
|
640
|
+
chunks.forEach((chunk, chunkIndex) => {
|
|
641
|
+
const currentSums = Array.from(reachable.keys());
|
|
642
|
+
for (const sum of currentSums) {
|
|
643
|
+
const next = sum + chunk.value;
|
|
644
|
+
if (next <= capacity && !reachable.has(next)) {
|
|
645
|
+
reachable.set(next, { previous: sum, chunkIndex });
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
});
|
|
649
|
+
let best = 0;
|
|
650
|
+
for (const sum of reachable.keys()) {
|
|
651
|
+
if (sum > best) best = sum;
|
|
652
|
+
}
|
|
653
|
+
return {
|
|
654
|
+
best,
|
|
655
|
+
selection: reconstructSelection(
|
|
656
|
+
best,
|
|
657
|
+
chunks,
|
|
658
|
+
(sum) => reachable.get(sum)?.previous ?? -1,
|
|
659
|
+
(sum) => reachable.get(sum)?.chunkIndex ?? -1,
|
|
660
|
+
plateCount
|
|
661
|
+
)
|
|
662
|
+
};
|
|
663
|
+
};
|
|
664
|
+
var heaviestFirst = (target, pairValues, counts) => {
|
|
665
|
+
let remaining = target;
|
|
666
|
+
const selection = pairValues.map((value, index) => {
|
|
667
|
+
const take = Math.min(counts[index], Math.floor(remaining / value));
|
|
668
|
+
remaining -= take * value;
|
|
669
|
+
return take;
|
|
670
|
+
});
|
|
671
|
+
return remaining === 0 ? selection : null;
|
|
672
|
+
};
|
|
673
|
+
var plateTotal = (selection) => selection.reduce((total, count) => total + count, 0);
|
|
674
|
+
var calculatePlateLoading = (targetWeightKg, barWeightKg, availablePlatePairs) => {
|
|
675
|
+
const targetUnits = Math.max(0, toCanonicalUnits(targetWeightKg));
|
|
676
|
+
const barUnits = Math.max(0, toCanonicalUnits(barWeightKg));
|
|
677
|
+
if (targetUnits < barUnits) {
|
|
678
|
+
return {
|
|
679
|
+
targetWeightKg: fromCanonicalUnits(targetUnits),
|
|
680
|
+
loadedWeightKg: fromCanonicalUnits(barUnits),
|
|
681
|
+
differenceKg: fromCanonicalUnits(barUnits - targetUnits),
|
|
682
|
+
status: "over",
|
|
683
|
+
platesPerSide: []
|
|
684
|
+
};
|
|
685
|
+
}
|
|
686
|
+
const plates = availablePlatePairs.filter((plate) => plate.weightKg > 0 && plate.pairCount > 0).sort((left, right) => right.weightKg - left.weightKg);
|
|
687
|
+
const pairValues = plates.map((plate) => toCanonicalUnits(plate.weightKg) * 2);
|
|
688
|
+
const divisor = pairValues.reduce(greatestCommonDivisor, 0) || 1;
|
|
689
|
+
const residualUnits = targetUnits - barUnits;
|
|
690
|
+
const requestedCapacity = Math.floor(residualUnits / divisor);
|
|
691
|
+
const inventoryCapacity = pairValues.reduce(
|
|
692
|
+
(total, value, index) => total + value / divisor * plates[index].pairCount,
|
|
693
|
+
0
|
|
694
|
+
);
|
|
695
|
+
const capacity = Math.min(requestedCapacity, inventoryCapacity);
|
|
696
|
+
const chunks = buildChunks(plates, divisor);
|
|
697
|
+
const solution = capacity <= DENSE_CAPACITY_LIMIT ? solveDense(capacity, chunks, plates.length) : solveSparse(capacity, chunks, plates.length);
|
|
698
|
+
const greedy = heaviestFirst(
|
|
699
|
+
solution.best,
|
|
700
|
+
pairValues.map((value) => value / divisor),
|
|
701
|
+
plates.map((plate) => plate.pairCount)
|
|
702
|
+
);
|
|
703
|
+
const selection = greedy && plateTotal(greedy) <= plateTotal(solution.selection) ? greedy : solution.selection;
|
|
704
|
+
const plateUnits = solution.best * divisor;
|
|
705
|
+
const loadedUnits = barUnits + plateUnits;
|
|
706
|
+
const differenceUnits = targetUnits - loadedUnits;
|
|
707
|
+
return {
|
|
708
|
+
targetWeightKg: fromCanonicalUnits(targetUnits),
|
|
709
|
+
loadedWeightKg: fromCanonicalUnits(loadedUnits),
|
|
710
|
+
differenceKg: fromCanonicalUnits(differenceUnits),
|
|
711
|
+
status: differenceUnits === 0 ? "exact" : "short",
|
|
712
|
+
platesPerSide: plates.flatMap(
|
|
713
|
+
(plate, index) => selection[index] > 0 ? [
|
|
714
|
+
{
|
|
715
|
+
weightKg: plate.weightKg,
|
|
716
|
+
platesPerSide: selection[index]
|
|
717
|
+
}
|
|
718
|
+
] : []
|
|
719
|
+
)
|
|
720
|
+
};
|
|
721
|
+
};
|
|
722
|
+
|
|
723
|
+
// src/warm-ups.ts
|
|
724
|
+
var MAX_SETS_PER_EXERCISE = 10;
|
|
725
|
+
var BAR_WARM_UP_STEPS = [
|
|
726
|
+
{ share: 0, reps: 10 },
|
|
727
|
+
{ share: 0.4, reps: 5 },
|
|
728
|
+
{ share: 0.6, reps: 3 },
|
|
729
|
+
{ share: 0.8, reps: 2 }
|
|
730
|
+
];
|
|
731
|
+
var OTHER_WARM_UP_STEPS = [
|
|
732
|
+
{ share: 0.5, reps: 8 },
|
|
733
|
+
{ share: 0.75, reps: 3 }
|
|
734
|
+
];
|
|
735
|
+
var BAR_LOADED = /* @__PURE__ */ new Set(["barbell", "ez-bar", "smith-machine"]);
|
|
736
|
+
var isBarLoaded = (equipmentRequired) => (equipmentRequired ?? []).some((item) => BAR_LOADED.has(item));
|
|
737
|
+
var POUNDS_PER_KILOGRAM = 2.2046226218;
|
|
738
|
+
var lb = (pounds) => pounds / POUNDS_PER_KILOGRAM;
|
|
739
|
+
var BAR_CHOICES_KG = {
|
|
740
|
+
KG: [20, 15, 10],
|
|
741
|
+
LB: [lb(45), lb(35), lb(15)]
|
|
742
|
+
};
|
|
743
|
+
var pairs = (weights, heaviestPairs) => weights.map((weightKg, index) => ({
|
|
744
|
+
weightKg,
|
|
745
|
+
pairCount: index === 0 ? heaviestPairs : 2
|
|
746
|
+
}));
|
|
747
|
+
var PLATE_SETS = {
|
|
748
|
+
KG: {
|
|
749
|
+
STANDARD: pairs([25, 20, 15, 10, 5, 2.5, 1.25], 4),
|
|
750
|
+
LIGHT: pairs([20, 15, 10, 5, 2.5, 1.25], 2)
|
|
751
|
+
},
|
|
752
|
+
LB: {
|
|
753
|
+
STANDARD: pairs([45, 35, 25, 10, 5, 2.5].map(lb), 4),
|
|
754
|
+
LIGHT: pairs([25, 10, 5, 2.5].map(lb), 2)
|
|
755
|
+
}
|
|
756
|
+
};
|
|
757
|
+
var LIMITED_SHORTFALL_KG = 2.5;
|
|
758
|
+
var defaultWarmUpEquipment = (unit) => ({
|
|
759
|
+
barWeightKg: BAR_CHOICES_KG[unit][0],
|
|
760
|
+
platePairs: PLATE_SETS[unit].STANDARD
|
|
761
|
+
});
|
|
762
|
+
var round = (value) => Math.round(value * 1e4) / 1e4;
|
|
763
|
+
function warmUpLoad(share, workingWeightKg, equipment) {
|
|
764
|
+
const target = share * workingWeightKg;
|
|
765
|
+
if (equipment.barLoaded) {
|
|
766
|
+
const loading = calculatePlateLoading(
|
|
767
|
+
Math.max(target, equipment.barWeightKg),
|
|
768
|
+
equipment.barWeightKg,
|
|
769
|
+
[...equipment.platePairs]
|
|
770
|
+
);
|
|
771
|
+
return {
|
|
772
|
+
weightKg: round(loading.loadedWeightKg),
|
|
773
|
+
platesPerSide: loading.platesPerSide,
|
|
774
|
+
limited: share > 0 && loading.status === "short" && loading.differenceKg >= LIMITED_SHORTFALL_KG - 1e-9
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
const increment = equipment.incrementKg > 0 ? equipment.incrementKg : 2.5;
|
|
778
|
+
return {
|
|
779
|
+
weightKg: round(Math.floor(target / increment + 1e-9) * increment),
|
|
780
|
+
limited: false
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
function buildWarmUpRamp(input) {
|
|
784
|
+
const work = input.workingWeightKg;
|
|
785
|
+
if (!(work > 0)) return { sets: [], leftOut: 0 };
|
|
786
|
+
const steps = input.barLoaded ? BAR_WARM_UP_STEPS : OTHER_WARM_UP_STEPS;
|
|
787
|
+
const sets = [];
|
|
788
|
+
for (const step of steps) {
|
|
789
|
+
const load = warmUpLoad(step.share, work, input);
|
|
790
|
+
const previous = sets[sets.length - 1];
|
|
791
|
+
if (load.weightKg <= 0 || load.weightKg >= work - 1e-9) continue;
|
|
792
|
+
if (previous && load.weightKg <= previous.weightKg + 1e-9) continue;
|
|
793
|
+
sets.push({ ...load, reps: step.reps, share: step.share });
|
|
794
|
+
}
|
|
795
|
+
const room = Math.max(0, input.room);
|
|
796
|
+
const kept = sets.slice(Math.max(0, sets.length - room));
|
|
797
|
+
return { sets: kept, leftOut: sets.length - kept.length };
|
|
798
|
+
}
|
|
799
|
+
function leadWorkingWeight(sets) {
|
|
800
|
+
const lead = sets.find((set) => countsForProgression(set.kind));
|
|
801
|
+
return typeof lead?.weight === "number" && lead.weight > 0 ? lead.weight : null;
|
|
802
|
+
}
|
|
803
|
+
function followWorkingLoad(sets, equipment) {
|
|
804
|
+
const work = leadWorkingWeight(sets);
|
|
805
|
+
if (work === null) return [...sets];
|
|
806
|
+
return sets.map(
|
|
807
|
+
(set) => set.kind === "WARMUP" && typeof set.warmUpShare === "number" ? { ...set, weight: warmUpLoad(set.warmUpShare, work, equipment).weightKg } : set
|
|
808
|
+
);
|
|
809
|
+
}
|
|
810
|
+
|
|
514
811
|
// src/routine.ts
|
|
515
812
|
var ROUTINE_SCHEDULE_MODES = ["WEEKLY", "ROTATION"];
|
|
516
813
|
var ROUTINE_DAYS_MAX = 7;
|
|
@@ -632,13 +929,18 @@ var lighterOnGrid = (original, target, increment) => {
|
|
|
632
929
|
const stepped = Math.round(Math.round(target / step) * step * 1e3) / 1e3;
|
|
633
930
|
return stepped > 0 && stepped < original ? stepped : original;
|
|
634
931
|
};
|
|
932
|
+
function halveSets(sets) {
|
|
933
|
+
const work = sets.filter((set) => countsAsWork(set.kind));
|
|
934
|
+
const keep = new Set(work.slice(0, Math.ceil(work.length / 2)));
|
|
935
|
+
return sets.filter((set) => !countsAsWork(set.kind) || keep.has(set)).map((set, index) => ({ ...set, setNumber: index + 1 }));
|
|
936
|
+
}
|
|
635
937
|
function applyDeload(setup, options) {
|
|
636
938
|
const factor = 1 - options.loadReductionPercent / 100;
|
|
637
939
|
let lighter = false;
|
|
638
940
|
const days = setup.days.map((day) => ({
|
|
639
941
|
...day,
|
|
640
942
|
exercises: day.exercises.map((exercise) => {
|
|
641
|
-
const kept = options.setMode === "HALF" ?
|
|
943
|
+
const kept = options.setMode === "HALF" ? halveSets(exercise.sets) : exercise.sets;
|
|
642
944
|
if (kept.length < exercise.sets.length) lighter = true;
|
|
643
945
|
return {
|
|
644
946
|
...exercise,
|
|
@@ -931,6 +1233,8 @@ function accountExportFileName(username, exportedAt) {
|
|
|
931
1233
|
ACTIVITY_REACTIONS,
|
|
932
1234
|
ACTIVITY_TYPES,
|
|
933
1235
|
ACTIVITY_TYPE_SECTIONS,
|
|
1236
|
+
BAR_CHOICES_KG,
|
|
1237
|
+
BAR_WARM_UP_STEPS,
|
|
934
1238
|
BLOCKED_MEMBERS_MAX,
|
|
935
1239
|
CLONE_ROUTINE_REFUSALS,
|
|
936
1240
|
COMEBACK_MIN_INACTIVE_DAYS,
|
|
@@ -958,6 +1262,8 @@ function accountExportFileName(username, exportedAt) {
|
|
|
958
1262
|
FOLLOW_SUGGESTIONS_DEFAULT_LIMIT,
|
|
959
1263
|
FOLLOW_SUGGESTIONS_MAX_LIMIT,
|
|
960
1264
|
FOLLOW_SUGGESTION_REASONS,
|
|
1265
|
+
LIMITED_SHORTFALL_KG,
|
|
1266
|
+
MAX_SETS_PER_EXERCISE,
|
|
961
1267
|
MEASURABLE_GOALS_MAX,
|
|
962
1268
|
MEASURABLE_GOAL_DIRECTIONS,
|
|
963
1269
|
MEASURABLE_GOAL_TYPES,
|
|
@@ -973,12 +1279,14 @@ function accountExportFileName(username, exportedAt) {
|
|
|
973
1279
|
NOTIFICATIONS_RETENTION_DAYS,
|
|
974
1280
|
NOTIFICATION_CATEGORIES,
|
|
975
1281
|
NOTIFICATION_KINDS,
|
|
1282
|
+
OTHER_WARM_UP_STEPS,
|
|
976
1283
|
PLATEAU_MIN_DAYS_SINCE_BEST,
|
|
977
1284
|
PLATEAU_MIN_SESSIONS,
|
|
978
1285
|
PLATEAU_MIN_SESSIONS_MAX,
|
|
979
1286
|
PLATEAU_MIN_SESSIONS_MIN,
|
|
980
1287
|
PLATEAU_RECENT_DAYS,
|
|
981
1288
|
PLATEAU_WINDOW_DAYS,
|
|
1289
|
+
PLATE_SETS,
|
|
982
1290
|
PREFERRED_TRAINING_STYLE_VALUES,
|
|
983
1291
|
PROFILE_BIO_MAX_LENGTH,
|
|
984
1292
|
PROFILE_FAVORITE_EXERCISES_MAX,
|
|
@@ -1034,6 +1342,8 @@ function accountExportFileName(username, exportedAt) {
|
|
|
1034
1342
|
SESSION_SHARE_DEFAULT_FIELDS,
|
|
1035
1343
|
SESSION_SHARE_FIELDS,
|
|
1036
1344
|
SESSION_SHARE_MAX_ACTIVE_LINKS,
|
|
1345
|
+
SET_KINDS,
|
|
1346
|
+
SET_KIND_LABELS,
|
|
1037
1347
|
SEXES,
|
|
1038
1348
|
SHARED_ROUTINE_SOURCES,
|
|
1039
1349
|
STARRED_EXERCISES_MAX,
|
|
@@ -1069,13 +1379,25 @@ function accountExportFileName(username, exportedAt) {
|
|
|
1069
1379
|
WORKOUT_SESSION_STATUSES,
|
|
1070
1380
|
accountExportFileName,
|
|
1071
1381
|
applyDeload,
|
|
1382
|
+
buildWarmUpRamp,
|
|
1383
|
+
calculatePlateLoading,
|
|
1384
|
+
countsAsWork,
|
|
1385
|
+
countsForProgression,
|
|
1386
|
+
defaultWarmUpEquipment,
|
|
1072
1387
|
deloadLengthDays,
|
|
1388
|
+
followWorkingLoad,
|
|
1389
|
+
isBarLoaded,
|
|
1390
|
+
isSetKind,
|
|
1073
1391
|
isWithinQuietHours,
|
|
1392
|
+
leadWorkingWeight,
|
|
1074
1393
|
matchesDeletionConfirmation,
|
|
1394
|
+
requiredToFinish,
|
|
1075
1395
|
resolveActiveTrainingBlock,
|
|
1076
1396
|
resolveRoutinePlan,
|
|
1077
1397
|
routineDayLabel,
|
|
1078
1398
|
sessionCorrectionWindow,
|
|
1399
|
+
setKindOf,
|
|
1079
1400
|
setLogValuesDiffer,
|
|
1080
|
-
trainingBlockCovers
|
|
1401
|
+
trainingBlockCovers,
|
|
1402
|
+
warmUpLoad
|
|
1081
1403
|
});
|