mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2026-07-31 07:44:24 +02:00
This extracts the following metrics and stores them in a new GenericMetricSample / GENERIC_METRIC_SAMPLE table: - endurance score - functional threshold power - hill endurance - hill score - hill strength - MET max VO2 - running lactate threshold power - training readiness Visualisation and charts aren't part of this PR.
This commit is contained in:
+2
@@ -50,6 +50,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.GarminSleepStageSampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.GarminSleepStatsSampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.GarminSpo2SampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.GarminStressSampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.GenericMetricSampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.GenericTrainingLoadAcuteSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.GenericTrainingLoadAcuteSampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.GenericTrainingLoadChronicSample;
|
||||
@@ -126,6 +127,7 @@ public abstract class GarminCoordinator extends AbstractBLEDeviceCoordinator {
|
||||
put(session.getPendingFileDao(), PendingFileDao.Properties.DeviceId);
|
||||
put(session.getGenericTrainingLoadAcuteSampleDao(), GenericTrainingLoadAcuteSampleDao.Properties.DeviceId);
|
||||
put(session.getGenericTrainingLoadChronicSampleDao(), GenericTrainingLoadChronicSampleDao.Properties.DeviceId);
|
||||
put(session.getGenericMetricSampleDao(), GenericMetricSampleDao.Properties.DeviceId);
|
||||
}};
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/* Copyright (C) 2026 Thomas Kuehne
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.model;
|
||||
|
||||
import androidx.annotation.IntRange;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitEnduranceScore;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitFunctionalMetrics;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitHillScore;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitMaxMetData;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitTrainingReadiness;
|
||||
|
||||
public interface MetricSample extends TimeSample {
|
||||
default Metric getMetric() {
|
||||
int dbId = getMetricType();
|
||||
return Metric.fromDbId(dbId);
|
||||
}
|
||||
|
||||
default void setMetric(@NonNull Metric type) {
|
||||
setMetricType(type.dbId);
|
||||
}
|
||||
|
||||
default void setMetric(@NonNull Metric type, @Nullable Double value, @Nullable Long extra) {
|
||||
setMetricType(type.dbId);
|
||||
setMetricScore(value);
|
||||
setMetricExtra(extra);
|
||||
}
|
||||
|
||||
int getMetricType();
|
||||
|
||||
/// use {@link #setMetric(Metric)} or {@link #setMetric(Metric, Double, Long)} instead
|
||||
void setMetricType(@IntRange(from = 0, to = 8) int type);
|
||||
|
||||
@Nullable
|
||||
Double getMetricScore();
|
||||
|
||||
void setMetricScore(@Nullable Double value);
|
||||
|
||||
@Nullable
|
||||
Long getMetricExtra();
|
||||
|
||||
void setMetricExtra(@Nullable Long extra);
|
||||
|
||||
enum Metric {
|
||||
UNKNOWN(0),
|
||||
/// @see FitEnduranceScore#getEnduranceScore()
|
||||
/// @see FitEnduranceScore#getLevel()
|
||||
GARMIN_ENDURANCE_SCORE(1),
|
||||
/// @see FitFunctionalMetrics#getFunctionalThresholdPower()
|
||||
/// @see FitFunctionalMetrics#getCyclingLactaceThresholdHr()
|
||||
GARMIN_FUNCTIONAL_THRESHOLD_POWER(2),
|
||||
/// @see FitHillScore#getHillEndurance()
|
||||
/// @see FitHillScore#getLevel()
|
||||
GARMIN_HILL_ENDURANCE(3),
|
||||
/// @see FitHillScore#getHillScore()
|
||||
/// @see FitHillScore#getLevel()
|
||||
GARMIN_HILL_SCORE(4),
|
||||
/// @see FitHillScore#getHillStrength()
|
||||
/// @see FitHillScore#getLevel()
|
||||
GARMIN_HILL_STRENGTH(5),
|
||||
/// @see FitMaxMetData#getVo2Max()
|
||||
/// @see FitMaxMetData#getMaxMetCategory()
|
||||
GARMIN_MET_MAX_VO2(6),
|
||||
/// @see FitFunctionalMetrics#getRunningLactateThresholdPower()
|
||||
/// @see FitFunctionalMetrics#getRunningLactateThresholdHr()
|
||||
GARMIN_RUNNING_LACTATE_THRESHOLD_POWER(7),
|
||||
/// @see FitTrainingReadiness#getTrainingReadiness()
|
||||
/// @see FitTrainingReadiness#getLevel()
|
||||
GARMIN_TRAINING_READINESS(8);
|
||||
|
||||
final int dbId;
|
||||
|
||||
Metric(int dbId) {
|
||||
this.dbId = dbId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static Metric fromDbId(int dbId) {
|
||||
for (Metric metric : values()) {
|
||||
if (metric.dbId == dbId) {
|
||||
return metric;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+114
@@ -77,6 +77,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.GarminSleepStageSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.GarminSleepStatsSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.GarminSpo2Sample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.GarminStressSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.GenericMetricSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.GenericTrainingLoadAcuteSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.GenericTrainingLoadChronicSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.User;
|
||||
@@ -87,16 +88,21 @@ import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySummaryParser;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityTrack;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.FitActivityTrackProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MetricSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.Spo2Sample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.FileType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.exception.FitParseException;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.fieldDefinitions.FieldDefinitionHrvStatus;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.fieldDefinitions.FieldDefinitionSleepStage;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitDeviceStatus;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitEnduranceScore;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitEvent;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitFileId;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitFunctionalMetrics;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitHillScore;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitHrvSummary;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitHrvValue;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitMaxMetData;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitMonitoring;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitMonitoringHrData;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitMonitoringInfo;
|
||||
@@ -115,6 +121,7 @@ import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitStressLevel;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitTimeInZone;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitTrainingLoad;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitTrainingReadiness;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.messages.FitUserProfile;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
@@ -147,6 +154,7 @@ public class FitImporter {
|
||||
private final List<GarminSleepRestlessMomentsSample> sleepRestlessMomentsSamples = new ArrayList<>();
|
||||
private final List<BatteryLevel> batterySamples = new ArrayList<>();
|
||||
private FitFileId fileId = null;
|
||||
private final List<GenericMetricSample> genericMetricSamples = new ArrayList<>();
|
||||
|
||||
private final GarminWorkoutParser workoutParser;
|
||||
|
||||
@@ -406,6 +414,99 @@ public class FitImporter {
|
||||
batteryLevel.setLevel(level);
|
||||
batterySamples.add(batteryLevel);
|
||||
}
|
||||
} else if (record instanceof FitHillScore fitHillScore) {
|
||||
final Integer rawLevel = fitHillScore.getLevel();
|
||||
final Long level = (rawLevel == null) ? null : rawLevel.longValue();
|
||||
|
||||
final Integer rawEndurance = fitHillScore.getHillEndurance();
|
||||
final double endurance = (rawEndurance == null) ? Double.NaN : rawEndurance.doubleValue();
|
||||
if (endurance > 0.0) {
|
||||
final GenericMetricSample sample = new GenericMetricSample();
|
||||
sample.setTimestamp(ts);
|
||||
sample.setMetric(MetricSample.Metric.GARMIN_HILL_ENDURANCE, endurance, level);
|
||||
genericMetricSamples.add(sample);
|
||||
}
|
||||
|
||||
final Integer rawScore = fitHillScore.getHillScore();
|
||||
final double score = (rawScore == null) ? Double.NaN : rawScore.doubleValue();
|
||||
if (score > 0.0) {
|
||||
final GenericMetricSample sample = new GenericMetricSample();
|
||||
sample.setTimestamp(ts);
|
||||
sample.setMetric(MetricSample.Metric.GARMIN_HILL_SCORE, score, level);
|
||||
genericMetricSamples.add(sample);
|
||||
}
|
||||
|
||||
final Integer rawStrength = fitHillScore.getHillStrength();
|
||||
final double strength = (rawStrength == null) ? Double.NaN : rawStrength.doubleValue();
|
||||
if (strength > 0.0) {
|
||||
final GenericMetricSample sample = new GenericMetricSample();
|
||||
sample.setTimestamp(ts);
|
||||
sample.setMetric(MetricSample.Metric.GARMIN_HILL_STRENGTH, strength, level);
|
||||
genericMetricSamples.add(sample);
|
||||
}
|
||||
} else if (record instanceof FitTrainingReadiness fitTrainingReadiness) {
|
||||
final Integer rawReadiness = fitTrainingReadiness.getTrainingReadiness();
|
||||
final Integer rawLevel = fitTrainingReadiness.getLevel();
|
||||
|
||||
final Double readiness = (rawReadiness == null) ? null : rawReadiness.doubleValue();
|
||||
final Long level = (rawLevel == null) ? null : rawLevel.longValue();
|
||||
|
||||
if ((level != null && level > 0) || (readiness != null && readiness > 0)) {
|
||||
final GenericMetricSample sample = new GenericMetricSample();
|
||||
sample.setTimestamp(ts);
|
||||
sample.setMetric(MetricSample.Metric.GARMIN_TRAINING_READINESS, readiness, level);
|
||||
genericMetricSamples.add(sample);
|
||||
}
|
||||
} else if (record instanceof FitEnduranceScore fitEnduranceScore) {
|
||||
final Integer rawScore = fitEnduranceScore.getEnduranceScore();
|
||||
final Integer rawLevel = fitEnduranceScore.getLevel();
|
||||
|
||||
final Double score = (rawScore == null) ? null : rawScore.doubleValue();
|
||||
final Long level = (rawLevel == null) ? null : rawLevel.longValue();
|
||||
|
||||
if ((level != null && level > 0) || (score != null && score > 0)) {
|
||||
final GenericMetricSample sample = new GenericMetricSample();
|
||||
sample.setTimestamp(ts);
|
||||
sample.setMetric(MetricSample.Metric.GARMIN_ENDURANCE_SCORE, score, level);
|
||||
genericMetricSamples.add(sample);
|
||||
}
|
||||
} else if (record instanceof FitFunctionalMetrics fitFunctionalMetrics) {
|
||||
final Integer rawFtp = fitFunctionalMetrics.getFunctionalThresholdPower();
|
||||
if (rawFtp != null && rawFtp > 0) {
|
||||
final Double ftp = rawFtp.doubleValue();
|
||||
final Integer rawHr = fitFunctionalMetrics.getCyclingLactaceThresholdHr();
|
||||
final Long hr = (rawHr == null) ? null : rawHr.longValue();
|
||||
|
||||
final GenericMetricSample sample = new GenericMetricSample();
|
||||
sample.setTimestamp(ts);
|
||||
sample.setMetric(MetricSample.Metric.GARMIN_FUNCTIONAL_THRESHOLD_POWER, ftp, hr);
|
||||
genericMetricSamples.add(sample);
|
||||
}
|
||||
|
||||
final Integer rawLtp = fitFunctionalMetrics.getRunningLactateThresholdPower();
|
||||
if (rawLtp != null && rawLtp > 0) {
|
||||
final Double ltp = rawLtp.doubleValue();
|
||||
final Integer rawHr = fitFunctionalMetrics.getRunningLactateThresholdHr();
|
||||
final Long hr = (rawHr == null) ? null : rawHr.longValue();
|
||||
|
||||
final GenericMetricSample sample = new GenericMetricSample();
|
||||
sample.setTimestamp(ts);
|
||||
sample.setMetric(MetricSample.Metric.GARMIN_RUNNING_LACTATE_THRESHOLD_POWER, ltp, hr);
|
||||
genericMetricSamples.add(sample);
|
||||
}
|
||||
}else if(record instanceof FitMaxMetData fitMaxMetData){
|
||||
final Float rawVo2Max = fitMaxMetData.getVo2Max();
|
||||
final Integer rawMaxMetCategory = fitMaxMetData.getMaxMetCategory();
|
||||
|
||||
final Double vo2Max = (rawVo2Max == null) ? null : rawVo2Max.doubleValue();
|
||||
final Long maxMetCategory = (rawMaxMetCategory == null) ? null : rawMaxMetCategory.longValue();
|
||||
|
||||
if((vo2Max != null && vo2Max > 0) || (maxMetCategory != null && maxMetCategory > 0)){
|
||||
final GenericMetricSample sample = new GenericMetricSample();
|
||||
sample.setTimestamp(ts);
|
||||
sample.setMetric(MetricSample.Metric.GARMIN_MET_MAX_VO2, vo2Max, maxMetCategory);
|
||||
genericMetricSamples.add(sample);
|
||||
}
|
||||
} else {
|
||||
LOG.trace("Unknown record: {}", record);
|
||||
|
||||
@@ -506,7 +607,9 @@ public class FitImporter {
|
||||
try (DBHandler handler = GBApplication.acquireDB()) {
|
||||
final DaoSession session = handler.getDaoSession();
|
||||
final long deviceId = DBHelper.getDevice(gbDevice, session).getId();
|
||||
final long userId = DBHelper.getUser(session).getId();
|
||||
persistBattery(session, deviceId);
|
||||
persistGenericMetrics(session, deviceId, userId);
|
||||
} catch (final Exception e) {
|
||||
GB.toast(context, "Error saving generic samples", Toast.LENGTH_LONG, GB.ERROR, e);
|
||||
}
|
||||
@@ -526,6 +629,16 @@ public class FitImporter {
|
||||
}
|
||||
}
|
||||
|
||||
private void persistGenericMetrics(final DaoSession session, final long deviceId, final long userId) {
|
||||
if (!genericMetricSamples.isEmpty()) {
|
||||
genericMetricSamples.forEach(sample -> {
|
||||
sample.setUserId(userId);
|
||||
sample.setDeviceId(deviceId);
|
||||
});
|
||||
session.getGenericMetricSampleDao().insertOrReplaceInTx(genericMetricSamples);
|
||||
}
|
||||
}
|
||||
|
||||
private void persistWorkout(final File file, final DaoSession session, boolean isReprocessing) {
|
||||
LOG.debug("Persisting workout for {}", fileId);
|
||||
|
||||
@@ -613,6 +726,7 @@ public class FitImporter {
|
||||
batterySamples.clear();
|
||||
fileId = null;
|
||||
workoutParser.reset();
|
||||
genericMetricSamples.clear();
|
||||
}
|
||||
|
||||
private void persistActivitySamples(final DaoSession session) {
|
||||
|
||||
+7
-7
@@ -1855,12 +1855,12 @@ public class NativeFITMessage {
|
||||
new FieldDefinitionPrimitive(0, BaseType.UINT8, "unknown_0"),
|
||||
new FieldDefinitionPrimitive(2, BaseType.UINT32, "unknown_2"),
|
||||
new FieldDefinitionPrimitive(3, BaseType.UINT32, "unknown_3"),
|
||||
new FieldDefinitionPrimitive(4, BaseType.UINT16, "functional_threshold_power"), // W
|
||||
new FieldDefinitionPrimitive(4, BaseType.UINT16, "functional_threshold_power"), // Watt
|
||||
new FieldDefinitionPrimitive(5, BaseType.UINT8, "unknown_5"),
|
||||
new FieldDefinitionPrimitive(6, BaseType.UINT8, "unknown_6"),
|
||||
new FieldDefinitionPrimitive(7, BaseType.UINT16, "running_lactate_threshold_power"),
|
||||
new FieldDefinitionPrimitive(8, BaseType.UINT8, "running_lactate_threshold_hr"),
|
||||
new FieldDefinitionPrimitive(9, BaseType.UINT8, "cycling_lactace_threshold_hr"),
|
||||
new FieldDefinitionPrimitive(7, BaseType.UINT16, "running_lactate_threshold_power"), // Watt
|
||||
new FieldDefinitionPrimitive(8, BaseType.UINT8, "running_lactate_threshold_hr"), // BPM
|
||||
new FieldDefinitionPrimitive(9, BaseType.UINT8, "cycling_lactace_threshold_hr"), // BPM
|
||||
new FieldDefinitionPrimitive(10, BaseType.UINT16, "unknown_10"),
|
||||
new FieldDefinitionPrimitive(11, BaseType.ENUM, "unknown_11"),
|
||||
new FieldDefinitionPrimitive(12, BaseType.ENUM, "unknown_12"),
|
||||
@@ -1870,7 +1870,7 @@ public class NativeFITMessage {
|
||||
// Source: #5710
|
||||
public static NativeFITMessage TRAINING_READINESS = new NativeFITMessage(369, "TRAINING_READINESS", Arrays.asList(
|
||||
new FieldDefinitionPrimitive(0, BaseType.UINT8, "training_readiness"),
|
||||
new FieldDefinitionPrimitive(1, BaseType.ENUM, "level"), // 4 high, 5 prime
|
||||
new FieldDefinitionPrimitive(1, BaseType.ENUM, "level"), // 1=poor, 2=low, 3=moderate, 4=high, 5=prime
|
||||
new FieldDefinitionPrimitive(2, BaseType.ENUM, "unknown_2"),
|
||||
new FieldDefinitionPrimitive(3, BaseType.ENUM, "unknown_3"),
|
||||
new FieldDefinitionPrimitive(4, BaseType.UINT8, "unknown_4"),
|
||||
@@ -2028,7 +2028,7 @@ public class NativeFITMessage {
|
||||
new FieldDefinitionPrimitive(1, BaseType.UINT8, "hill_strength"),
|
||||
new FieldDefinitionPrimitive(2, BaseType.UINT8, "hill_endurance"),
|
||||
new FieldDefinitionPrimitive(3, BaseType.ENUM, "unknown_3"), // 2?
|
||||
new FieldDefinitionPrimitive(4, BaseType.ENUM, "unknown_4"), // 2?
|
||||
new FieldDefinitionPrimitive(4, BaseType.ENUM, "level"), // 1=recreational, 2=challenger, 3=trained, 4=skilled, 5=expert, 6=elite
|
||||
new FieldDefinitionPrimitive(5, BaseType.ENUM, "unknown_5"),
|
||||
new FieldDefinitionPrimitive(253, BaseType.UINT32, "timestamp", FieldDefinitionFactory.FIELD.TIMESTAMP)
|
||||
));
|
||||
@@ -2036,7 +2036,7 @@ public class NativeFITMessage {
|
||||
// Source: #5708
|
||||
public static NativeFITMessage ENDURANCE_SCORE = new NativeFITMessage(403, "ENDURANCE_SCORE", Arrays.asList(
|
||||
new FieldDefinitionPrimitive(0, BaseType.UINT16, "endurance_score"),
|
||||
new FieldDefinitionPrimitive(1, BaseType.ENUM, "level"), // 6 superior 7 elite
|
||||
new FieldDefinitionPrimitive(1, BaseType.ENUM, "level"), // 1=recreational, 2=intermediate, 3=trained, 4=well-trained, 5=expert, 6=superior, 7=elite
|
||||
new FieldDefinitionPrimitive(2, BaseType.ENUM, "unknown_2"),
|
||||
// Matches the boundaries from https://www8.garmin.com/manuals/webhelp/GUID-C001C335-A8EC-4A41-AB0E-BAC434259F92/EN-US/GUID-573861DC-64B1-4120-847F-A944BA683DBA.html
|
||||
new FieldDefinitionPrimitive(3, BaseType.UINT16, "lower_bound_intermediate"),
|
||||
|
||||
+2
-2
@@ -60,7 +60,7 @@ public class FitHillScore extends RecordData {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getUnknown4() {
|
||||
public Integer getLevel() {
|
||||
return getFieldByNumber(4, Integer.class);
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ public class FitHillScore extends RecordData {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setUnknown4(final Integer value) {
|
||||
public Builder setLevel(final Integer value) {
|
||||
setFieldByNumber(4, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user