Skip to content

Commit

Permalink
Fix float-keying activity level problem (#49179)
Browse files Browse the repository at this point in the history
* Activity diary test now detects float-keying problem

avatar::log_activity_level is now getting fed (floating-point) numbers
that don't match the exact activity levels, due to #45316 making the
activity level per-turn then averaging activity over each 5-minute
period. The activity diary test (in tests/char_biometrics_test.cpp)
was not spotting this since it was still using times in multiples
of 5 minutes. This commit moves around 1 minute of NO_EXERCISE,
keeping the same total number of minutes of each activity level.
Currently, this results in a test failure in which 1 5-minute interval
is missing from each of the activity levels in the diary, since those
5-minute intervals were at intermediate (averaged) levels of activity.

* Process intermediate activity levels for debug output

This "buckets" activity levels that aren't exactly the predefined
set of levels (due to averaging over 5 minutes) into the closest
predefined level in avatar::total_daily_calories_string. Note that
saving of levels will not be bucketed. This, while useful for close
inspection of intermediate levels via looking at the save file, will
make the file slightly larger, slower to input/output, and (even)
harder to read manually. However, this has been true since #45316 was
merged and nobody seems to have noticed it.

* Correct logic error in attempted fix.

I forgot to add the number of 5-minute intervals and was instead adding
just one. It still doesn't quite work right (and I'll need to adjust
the expected gained/spent/total caloric values), but it's a lot closer.

* Adjust expected numbers for mixed intervals

The new results in terms of minutes are actually now correct; the
difference is because the last 5 minutes are 4 minutes of
EXTRA_EXERCISE and 1 minute of NO_EXERCISE, which averages out to
ACTIVE_EXERCISE (410 + 11 = 41; /5 = 8.2, and ACTIVE_EXERCISE = 8.0).
The rest is likely roundoff error, although it still bothers me a bit.

Co-authored-by: actual-nh <[email protected]>
  • Loading branch information
actual-nh and actual-nh authored Jun 8, 2021
1 parent 88b16d4 commit 226bebc
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 11 deletions.
43 changes: 37 additions & 6 deletions src/avatar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1759,19 +1759,50 @@ std::string avatar::total_daily_calories_string() const
const std::string format_string =
" %4d %4d %4d %4d %4d %4d %4d %6d %6d";

const float light_ex_thresh = ( NO_EXERCISE + LIGHT_EXERCISE ) / 2.0f;
const float mod_ex_thresh = ( LIGHT_EXERCISE + MODERATE_EXERCISE ) / 2.0f;
const float brisk_ex_thresh = ( MODERATE_EXERCISE + BRISK_EXERCISE ) / 2.0f;
const float active_ex_thresh = ( BRISK_EXERCISE + ACTIVE_EXERCISE ) / 2.0f;
const float extra_ex_thresh = ( ACTIVE_EXERCISE + EXTRA_EXERCISE ) / 2.0f;

std::string ret = header_string;

// Start with today in the first row, day number from start of cataclysm
int today = day_of_season<int>( calendar::turn ) + 1;
int day_offset = 0;
for( const daily_calories &day : calorie_diary ) {
// Yes, this is clunky.
// Perhaps it should be done in log_activity_level? But that's called a lot more often.
int no_exercise = 0;
int light_exercise = 0;
int moderate_exercise = 0;
int brisk_exercise = 0;
int active_exercise = 0;
int extra_exercise = 0;
for( const std::pair<const float, int> &level : day.activity_levels ) {
if( level.second > 0 ) {
if( level.first < light_ex_thresh ) {
no_exercise += level.second;
} else if( level.first < mod_ex_thresh ) {
light_exercise += level.second;
} else if( level.first < brisk_ex_thresh ) {
moderate_exercise += level.second;
} else if( level.first < active_ex_thresh ) {
brisk_exercise += level.second;
} else if( level.first < extra_ex_thresh ) {
active_exercise += level.second;
} else {
extra_exercise += level.second;
}
}
}
std::string row_data = string_format( format_string, today + day_offset--,
5 * day.activity_levels.at( NO_EXERCISE ),
5 * day.activity_levels.at( LIGHT_EXERCISE ),
5 * day.activity_levels.at( MODERATE_EXERCISE ),
5 * day.activity_levels.at( BRISK_EXERCISE ),
5 * day.activity_levels.at( ACTIVE_EXERCISE ),
5 * day.activity_levels.at( EXTRA_EXERCISE ),
5 * no_exercise,
5 * light_exercise,
5 * moderate_exercise,
5 * brisk_exercise,
5 * active_exercise,
5 * extra_exercise,
day.gained, day.spent );
// Alternate gray and white text for row data
if( day_offset % 2 == 0 ) {
Expand Down
11 changes: 6 additions & 5 deletions tests/char_biometrics_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -453,21 +453,22 @@ TEST_CASE( "activity levels and calories in daily diary", "[avatar][biometrics][

SECTION( "shows time at each activity level for the current day" ) {
dummy.reset_activity_level();
test_activity_duration( dummy, NO_EXERCISE, 1_hours );
test_activity_duration( dummy, NO_EXERCISE, 59_minutes );
test_activity_duration( dummy, LIGHT_EXERCISE, 45_minutes );
test_activity_duration( dummy, MODERATE_EXERCISE, 30_minutes );
test_activity_duration( dummy, BRISK_EXERCISE, 20_minutes );
test_activity_duration( dummy, ACTIVE_EXERCISE, 15_minutes );
test_activity_duration( dummy, EXTRA_EXERCISE, 10_minutes );
test_activity_duration( dummy, NO_EXERCISE, 1_minutes );

int expect_gained_kcal = 1283;
int expect_net_kcal = 551;
int expect_spent_kcal = 732;
int expect_gained_kcal = 1282;
int expect_net_kcal = 552;
int expect_spent_kcal = 730;

CHECK( condensed_spaces( dummy.total_daily_calories_string() ) == string_format(
"<color_c_white> Minutes at each exercise level Calories per day</color>\n"
"<color_c_yellow> Day None Light Moderate Brisk Active Extra Gained Spent Total</color>\n"
"<color_c_light_gray> 61 60 45 30 20 15 10 %d %d</color><color_c_light_blue> %d</color>\n",
"<color_c_light_gray> 61 60 45 30 20 20 5 %d %d</color><color_c_light_blue> %d</color>\n",
expect_gained_kcal, expect_spent_kcal, expect_net_kcal ) );
}
}
Expand Down

0 comments on commit 226bebc

Please sign in to comment.