CleverRaven / Cataclysm-DDA

Cataclysm - Dark Days Ahead. A turn-based survival game set in a post-apocalyptic world.
http://cataclysmdda.org
Other
10.65k stars 4.18k forks source link

Have vitamins defined in mgs instead of RDA #64722

Closed Karol1223 closed 1 year ago

Karol1223 commented 1 year ago

Is your feature request related to a problem? Please describe.

RDA changes. It did so last year, for example, and this means that any values added before then are already outdated. The mg content of food typically doesn't change. I'll explain why that's a big deal below. Also as it stands we cannot differentiate the RDA between character sizes either.

Solution you would like.

Have the vitamins in JSON defined in milligrams instead of RDA% value. Like I said, RDA changes and when that change happens in our current system you gotta edit every single comestible, whereas if we defined it in mgs this would not be a problem whatsoever.

Granted that showing it in RDA% for players is very helpful - what I propose is we define vitamin amount in mgs but have C++ have defined RDA% values somewhere. Then have the C++ code actually calculate the RDA% from the mgs to show it to players the same way we have it now.

This would not only mean that if/when RDA changes we have much less to edit (one cpp file) but also means we can distinguish between different RDAs for different sizes of player characters (or perhaps add that into EOCs so we can have specific conditions change RDAs too? Like for example having a Dermatik Larva in your body)

Also would make it far less confusing for contributors working on comestibles. I had a hell of a time in #64695 calculating the RDA from the mg amount I've actually gotten and this would save me some more trouble. Doesn't help that all nutritional value websites use a different RDA either.

Describe alternatives you have considered.

No response

Additional context

I will personally react with all the positive reactions to whoever implements that.

epsimpson commented 1 year ago

RDA doesn't change. RDA is government defined. The government no longer exists. Only package labels change as the numbers wear off.

Anything that makes future changes easier is good. That's really the only reason to make such a change. So long as the user never has to worry about knowing which mg->RDA conversion factors are currently trending. If you insist on changing health effects to comply with government RDAs, then the mg -> RDA conversions need to set in JSON, definitely not hard coded into c++.

But changing RDAs to comply with current government declarations shouldn't happen anyway.

RDA is more politics than science, as you discovered when you tried to find "real" RDA values. Best continue to pretend RDA at the time the world ended actually meant necessary time-averaged daily requirements. It doesn't. At all. RDA is, at best, mean requirement plus two standard deviations plus an "expert" fudge factor. It's explicitly designed to ensure that almost nobody in the population becomes severely deficient, with no concern whatsoever about anyone getting too much. You could roll random nutritional requirements for each character and get a more realistic health effect.

Karol1223 commented 1 year ago

RDA at the time the world ended

The problem here is that the game's events happen current day + 1 year roughly meaning when the FDA RDA changes (which is the one we're going with according to the devcord, and it is the one I've been working with) technically so would the RDA ingame.

Now, I agree that this isn't a big deal more often than not. Whether the dosage of calcium is 9% or 11% doesn't matter in the context of the game at all. But it does make working on comestibles more confusing when you realize the sources you've been using and the sources the other person has been using 5 years ago both were correct and it is the FDA RDA values that changed.

Zireael07 commented 1 year ago

@epsimpson The problem is RDA used to design consumables is the real-world RDA, which changes, not the in-universe one, which probably doesn't

github-actions[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. Please do not bump or comment on this issue unless you are actively working on it. Stale issues, and stale issues that are closed are still considered.

GuardianDll commented 1 year ago

Btw, won't it create an opposite problem, when you need to tweak food RDA every time the food weight/volume is changed? surely it doesn't happen so often, but still

Karol1223 commented 1 year ago

Btw, won't it create an opposite problem, when you need to tweak food RDA every time the food weight/volume is changed? surely it doesn't happen so often, but still

We already need to do that. Any time the weight of food is changed, it should provide different vitamin "%/RDA" or whatever we have right now. 30g of watermelon will have different vitamin content than 50g of watermelon. Changing this is a necessity now, changing vitamins to milligrams won't make that issue go away but it also won't make it any more difficult to maintain.

GuardianDll commented 1 year ago

but if i have a piece of meat, that gives 3% of iron, it would give 3% of it no matter what the weight of the meat, meanwhile having it "3 mg" when the piece of meat is "275 g" means if we change piece of meat to be "300 g", we should also adapt the vitamin weight in the item, don't we?

Zireael07 commented 1 year ago

We could express it as a fraction of the piece's weight I guess?

GuardianDll commented 1 year ago

Oh damn, i think i forgot it's percent of player's daily dose, somehow i thought it's a percent from food weight already

Procyonae commented 1 year ago

We could express it as a fraction of the piece's weight I guess?

That just sounds like more of a PITA, if you make a new meal now you can't just add up the components mg and would instead have to weighted average the fraction over the components

Karol1223 commented 1 year ago

Oh damn, i think i forgot it's percent of player's daily dose, somehow i thought it's a percent from food weight already

Yep, that's the issue. The % isn't % of food's mass. It's % of recommended daily intake (i.e. the RDA% of the food) which needs to be adjusted manually every time the weight of the food item is adjusted.

Procyonae commented 1 year ago

What units are the numbers in data\json\vitamin.json currently? (I read the C++ and don't understand)

Karol1223 commented 1 year ago

What units are the numbers in data\json\vitamin.json currently? (I read the C++ and don't understand)

I have no idea. I know what the vitamin numbers in the food json are, but what are the numbers in the vitamin json? 🤔

ehughsbaird commented 1 year ago

A solution looks something like this: This doesn't work, because it requires that vitamins are loaded before items. It needs to load both the unit style of vitamin and the weight style, then once all the data is loaded, process those both into units.


diff --git a/src/item_factory.cpp b/src/item_factory.cpp
index 708c3e76d1..ec0d2d6a99 100644
--- a/src/item_factory.cpp
+++ b/src/item_factory.cpp
@@ -3318,7 +3318,12 @@ void Item_factory::load( islot_comestible &slot, const JsonObject &jo, const std
     if( jo.has_array( "vitamins" ) ) {
         for( JsonArray pair : jo.get_array( "vitamins" ) ) {
             vitamin_id vit( pair.get_string( 0 ) );
-            slot.default_nutrition.vitamins[ vit ] = pair.get_int( 1 );
+            if( pair.has_int( 1 ) ) {
+                slot.default_nutrition.vitamins[ vit ] = pair.get_int( 1 );
+            } else if( pair.has_string( 1 ) ) {
+                units::mass val = read_from_json_string<units::mass>( pair[1], units::mass_units );
+                slot.default_nutrition.vitamins[vit] = val / vit->weight_per_unit;
+            }
         }

     } else if( relative.has_array( "vitamins" ) ) {
diff --git a/src/vitamin.cpp b/src/vitamin.cpp
index 0fa28055aa..216d1ec56a 100644
--- a/src/vitamin.cpp
+++ b/src/vitamin.cpp
@@ -6,6 +6,7 @@
 #include "calendar.h"
 #include "debug.h"
 #include "enum_conversions.h"
+#include "generic_factory.h"
 #include "json.h"
 #include "units.h"

@@ -88,6 +89,8 @@ void vitamin::load_vitamin( const JsonObject &jo )
     } else {
         vitamins_all[ vit.id_ ] = vit;
     }
+
+    assign( jo, "weight_per_unit", vit.weight_per_unit  );
 }

 const std::map<vitamin_id, vitamin> &vitamin::all()
diff --git a/src/vitamin.h b/src/vitamin.h
index 5bd1311a52..0c4d2d6679 100644
--- a/src/vitamin.h
+++ b/src/vitamin.h
@@ -12,6 +12,7 @@
 #include "calendar.h"
 #include "translations.h"
 #include "type_id.h"
+#include "units.h"

 class JsonObject;
 template <typename T> struct enum_traits;
@@ -108,6 +109,7 @@ class vitamin
          */
         float RDA_to_default( int percent ) const;

+        units::mass weight_per_unit;
     private:
         vitamin_id id_;
         vitamin_type type_ = vitamin_type::num_vitamin_types;