Skip to content
Commits on Source (7)
2018-06-22 NUTsqlite-2.0.4 released.
2018-06-22 Found a bug in RecipeDone. 100 gram weight record was wrong.
2018-06-17 NUTsqlite-2.0.3 released.
2018-06-17 Load of USDA database is leaving a carriage return and tilde at the
end of each food group. Fixed in proc load_fd_group. Also updated
GUI to show correct percentages of carbs and fat in new Daily Values.
2018-06-10 NUTsqlite-2.0.2 released.
2018-06-10 Windows 10 user "Darwin" found some code in proc FoodChoicevf which
which doesn't work right on his operating system. It's a thread
problem in conjunction with the tcl/sqlite interface.
2018-06-07 NUTsqlite-2.0.1 released.
2018-06-07 Procedure which clears the weight log was not updated to match
bigNUT, so I fixed ClearWeightLog.
2018-05-30 NUTsqlite-2.0 released.
2018-05-30 It looks and acts pretty much the same, but it's a new program made
up of snippets of the old program stitched together in a new way.
bigNUT is the back-end, the GUI is threaded, and the performance is
superb. All computations and logic are now done by SQLite rather
than Tcl. bigNUT uses triggers to keep all the data for the display
up-to-date, so that Tcl only translates user commands into SQL and
then retrieves all relevant data to refresh the GUI as necessary.
2017-06-26 NUTsqlite-1.9.9.6 released.
2017-06-20 Multiple changes: special commented-out code to make it easier to
......
<PRE>
NUT nutrition software
Copyright (C) 1996-2017 by Jim Jozwiak.
Copyright (C) 1996-2018 by Jim Jozwiak.
NUT is nutrition software to record what you eat and analyze your meals for
nutrient composition. Besides the usual features of nutrition software, NUT
......@@ -9,15 +10,11 @@ Copyright (C) 1996-2017 by Jim Jozwiak.
also offers a well-organized presentation of the nutrients that can help you
learn human nutrition by simply playing with the software.
The advantage of using NUTsqlite is that the database is portable across
disparate operating systems and can be queried independently of the NUTsqlite
application by using common SQLite tools. The exact code that runs the
application is in the database itself, so there is no version incompatibility
if you move the database to a different system or decide to update the USDA
tables. And unlike the legacy implementation of NUT, NUTsqlite preserves
enough of the previous USDA databases to always retain referential integrity
among the relational tables such as in the case where the USDA deletes a food
that you ate in some earlier meal.
NUTsqlite-2.x offers better performance with a newly structured SQLite
database that features fully normalized relational tables. In addition,
the database itself is functional even without the graphical user interface,
so it can be used on any device that presents a shell and has sqlite3
installed.
INSTALLATION of NUTsqlite
......@@ -34,40 +31,45 @@ INSTALLATION of NUTsqlite
separate directory, so you need to move all these files to the single
directory you are going to use.
3) Run "updateNUT.tcl" to create or upgrade the NUT code in the SQLite database
that runs the application. If upgrading, you have to be in the same
directory as the "nut.sqlite" file, or else you have to modify
"updateNUT.tcl" on line 24 to provide the full path to the "nut.sqlite" file.
3) Run "./updateNUT.tcl" to create or upgrade the NUT code in the SQLite
database that runs the application. If upgrading, you have to be in the same
directory as the "nut.db" file, or else you have to modify
"updateNUT.tcl" on line 24 to provide the full path to the "nut.db" file.
After this step, "updateNUT.tcl" is not required for anything and can be
deleted. Unlike the legacy implementation of NUT, updating the NUT code is
independent of updating the USDA database, although it is certainly possible
that the USDA could change the format of their tables so that a later version
of "updateNUT.tcl" would be required in order to read their tables or display
deleted. Updating the NUT code with "updateNUT.tcl" is independent of
updating the USDA database, although it is certainly possible that the USDA
could change the format of their tables so that a later version of
"updateNUT.tcl" would be required in order to read their tables or display
new nutrients. The main idea is that your personal data is permanent even
though the application code and USDA tables can change as necessary.
4) Run "nut.tcl" to run NUT. If you are using a launcher and cannot specify the
working directory, you will have to modify "nut.tcl" on line 27 to specify
the full path to "nut.sqlite". When "nut.tcl" runs initially, it will load
the USDA files and any legacy files that exist in your .nutdb directory,
including all your meals if you have just run the legacy NUT console program
which dumps meals in a manner that can be read from Tcl. After NUT performs
the initial database load, the USDA files can be deleted and NUT will not
load any more files until it detects a new USDA database in the directory
from which NUT is running. All "nut.tcl" really does is to start Tcl and
cause Tcl to run the code in the SQLite database. Because the code in the
database does not have to be interpreted until required, there may also be
better performance from the application.
Mac users should do this step from "Terminal" or else modify "updateNUT.tcl"
adding a line to "cd" to the directory to be used.
5) If you prefer NUTsqlite to the legacy implementation, the directory ".nutdb"
can be deleted so it will not be loaded again when you next wish to update
the USDA database. Alternately, you can simply modify line 26 of "nut.tcl"
to look for some non-existent directory as the legacy directory. Another
easy change to "nut.tcl" is the location of the SQLite database file. There
is also a variable "appSize" that can control the size of the window and
fonts when set between approximately 0.7 to 1.3.
4) If you are using a launcher and cannot specify the working directory, you
will have to modify "nut.tcl" on line 27 to specify the full path to
"nut.db". This is especially important for Mac users.
Another easy change to "nut.tcl" is the location of the SQLite database file.
There is also a variable "appSize" that can control the size of the window
and fonts for Linux users when set between approximately 0.7 to 1.3.
Windows and Mac users should leave the value of appSize at 0.0 unless they
have determined the Linux GUI can work well with their system.
5) Run "nut.tcl" to run NUT. When "nut.tcl" runs initially, it will load
the USDA files and any personal data that exists in the NUTsqlite version 1
database, nut.sqlite. After NUT performs the initial database load, the USDA
files can be deleted and NUT will not load any more files until it detects a
new USDA database in the directory from which NUT is running. All "nut.tcl"
really does is to start Tcl and cause Tcl to run the code in the SQLite
database. Because the code in the database does not have to be interpreted
until required, there may also be better performance from the application.
6) The legacy file "nut.sqlite" will no longer be used. The new database name
is "nut.db" and often has two auxiliary files that must not be deleted
because to do so corrupts the database.
Jim Jozwiak
http://nut.sourceforge.net
jozwiak@gmail.com
</PRE>
/*
Custom script to add next meal automatically. Invoke it thus:
.read nextmeal.sqlite3
.read sequence.sqlite3
This is something NUTsqlite can't do, complicated meal ordering with
automatic changes to personal options!
*/
begin;
update mealfoods set nutr_no = null;
update options set defanal_am = (select case when defanal_am >= 45 then 45 when o.currentmeal = lastmeal then defanal_am + 1 else defanal_am end from options o, am_analysis_header);
with newcm (meal_id) as (
with cm1 (base, meal) as (
with cm (base, meal) as (
......@@ -16,12 +21,14 @@ with newcm (meal_id) as (
)
update options set currentmeal = (select meal_id from newcm);
with meal_name (mn) as (
with meal (m) as (
select currentmeal % 100 from options
drop view if exists z_mn;
create temp view z_mn as
with meal (m, mod2) as (
select options.currentmeal % 100, maxmeal % 2 from options, am_analysis_header
)
select case when m = 1 then 'BC' when m = 2 then 'DC' else 'SC' end from meal
)
insert into currentmeal select NDB_No, Gm_Wgt, NutrDesc from theusual where meal_name = (select mn from meal_name);
select case when mod2 = 0 then case when m = 1 then 'K Breakfast' when m = 2 then 'K Dinner' else 'K Supper' end else case when m = 1 then 'K Breakfast' when m = 2 then 'K Dinner' else 'K Supper' end end as mn, m from meal;
insert into currentmeal select NDB_No, Gm_Wgt, NutrDesc from theusual where meal_name = (select mn from z_mn);
drop view z_mn;
commit;
/*
Custom script to add next meal automatically. Invoke it thus:
.read sequence.sqlite3
This is something NUTsqlite can't do, complicated meal ordering with
automatic changes to personal options!
*/
begin;
with newcm (meal_id) as (
with cm1 (base, meal) as (
with cm (base, meal) as (
select currentmeal / 100, currentmeal % 100 from options
)
select case when meal = 3 then date(substr(base, 1, 4) || '-' || substr(base, 5, 2) || '-' || substr(base, 7, 2), '+1 day') else substr(base, 1, 4) || '-' || substr(base, 5, 2) || '-' || substr(base, 7, 2) end, case when meal = 3 then 1 else meal + 1 end from cm
)
select cast( substr(base, 1, 4) || substr(base, 6, 2) || substr(base, 9, 2) as int) * 100 + meal from cm1
)
update options set currentmeal = (select meal_id from newcm);
update options set defanal_am = 1;
drop view if exists z_mn;
create temp view z_mn as
with meal (m) as (
select currentmeal % 100 from options
)
select case when m = 1 then 'R Breakfast' when m = 2 then 'KC Dinner' else 'R Supper' end as mn, m from meal;
insert into currentmeal select NDB_No, Gm_Wgt, NutrDesc from theusual where meal_name = (select mn from z_mn);
update nutr_def set nutopt = 0.0 where NutrDesc = 'Total Fat';
-- update nutr_def set nutopt = case when (select m from z_mn) in (1, 3) then 125.0 else 140.0 end where NutrDesc = 'Protein';
with temp (meal2nfc) as (select sum(Nutr_Val * Gm_Wgt / 100.0) from mealfoods join nut_data nd using (NDB_No) where nd.Nutr_No = 2000 and meal_id = (select max(meal_id) from mealfoods where meal_id % 100 = 2)) update nutr_def set nutopt = case when (select m from z_mn) in (1, 3) then (180.0 - (select meal2nfc from temp)) * 1.5 else -1 end where NutrDesc = 'Non-Fiber Carb';
commit;
/*
Custom script to add next meal automatically. Invoke it thus:
.read sequence.sqlite3
This is something NUTsqlite can't do, complicated meal ordering with
automatic changes to personal options!
*/
begin;
with newcm (meal_id) as (
with cm1 (base, meal) as (
with cm (base, meal) as (
select currentmeal / 100, currentmeal % 100 from options
)
select case when meal = 3 then date(substr(base, 1, 4) || '-' || substr(base, 5, 2) || '-' || substr(base, 7, 2), '+1 day') else substr(base, 1, 4) || '-' || substr(base, 5, 2) || '-' || substr(base, 7, 2) end, case when meal = 3 then 1 else meal + 1 end from cm
)
select cast( substr(base, 1, 4) || substr(base, 6, 2) || substr(base, 9, 2) as int) * 100 + meal from cm1
)
update options set currentmeal = (select meal_id from newcm);
update nutr_def set nutopt = -1 where nutrdesc = 'Total Fat';
update nutr_def set nutopt = 0.0 where nutrdesc = 'Non-Fiber Carb';
update options set defanal_am = case when defanal_am >= 45 then 45 else defanal_am + 1 end;
drop view if exists z_mn;
create temp view z_mn as
with meal (m, mod2) as (
select options.currentmeal % 100, maxmeal % 2 from options, am_analysis_header
)
select case when mod2 = 0 then case when m = 1 then 'R Breakfast' when m = 2 then 'R Dinner' else 'R Supper' end else case when m = 1 then 'P Breakfast' when m = 2 then 'P Dinner' else 'P Supper' end end as mn from meal;
insert into currentmeal select NDB_No, Gm_Wgt, NutrDesc from theusual where meal_name = (select mn from z_mn);
drop view z_mn;
commit;
/*
Custom script to add next meal automatically. Invoke it thus:
.read sequence.sqlite3
This is something NUTsqlite can't do, complicated meal ordering with
automatic changes to personal options!
The basic idea here is 5 low-fat starch meals followed by 3 low-carb meals.
Within the low-fat meals, starch source is alternated. Modulo arithmetic
selects which meal and personal options are to be chosen by defining a little
view which can be repeatedly be selected from by each subsequent SQL
statement in the procedure.
*/
begin;
with newcm (meal_id) as (
with cm1 (base, meal) as (
with cm (base, meal) as (
select currentmeal / 100, currentmeal % 100 from options
)
select case when meal = 3 then date(substr(base, 1, 4) || '-' || substr(base, 5, 2) || '-' || substr(base, 7, 2), '+1 day') else substr(base, 1, 4) || '-' || substr(base, 5, 2) || '-' || substr(base, 7, 2) end, case when meal = 3 then 1 else meal + 1 end from cm
)
select cast( substr(base, 1, 4) || substr(base, 6, 2) || substr(base, 9, 2) as int) * 100 + meal from cm1
)
update options set currentmeal = (select meal_id from newcm);
drop view if exists z_mn;
create temp view z_mn as
with meal (m, mod2, mod8) as (
select options.currentmeal % 100, maxmeal % 2, maxmeal % 8 from options, am_analysis_header
)
select case when mod8 not in (1, 2, 3) then case when mod2 = 1 then case when m = 1 then 'R Breakfast' when m = 2 then 'R Dinner' else 'R Supper' end else case when m = 1 then 'P Breakfast' when m = 2 then 'P Dinner' else 'P Supper' end end else case when m = 1 then 'K Breakfast' when m = 2 then 'K Dinner' else 'K Supper' end end as mn, mod8 from meal;
insert into currentmeal select NDB_No, Gm_Wgt, NutrDesc from theusual where meal_name = (select mn from z_mn);
update nutr_def set nutopt = case when (select mod8 from z_mn) not in (1, 2, 3) then -1 else 0.0 end where nutrdesc = 'Total Fat';
update nutr_def set nutopt = case when (select mod8 from z_mn) not in (1, 2, 3) then 0.0 else -1 end where nutrdesc = 'Non-Fiber Carb';
update options set defanal_am = case when (select mod8 from z_mn) in (2, 5) then 1 else defanal_am + 1 end;
drop view z_mn;
commit;
/*
Custom script to add next meal automatically. Invoke it thus:
.read sequence.sqlite3
This is something NUTsqlite can't do, complicated meal ordering with
automatic changes to personal options!
*/
begin;
update mealfoods set nutr_no = null;
update options set defanal_am = (select case when defanal_am >= 45 then 45 when o.currentmeal = lastmeal then defanal_am + 1 else defanal_am end from options o, am_analysis_header);
with newcm (meal_id) as (
with cm1 (base, meal) as (
with cm (base, meal) as (
select currentmeal / 100, currentmeal % 100 from options
)
select case when meal = 3 then date(substr(base, 1, 4) || '-' || substr(base, 5, 2) || '-' || substr(base, 7, 2), '+1 day') else substr(base, 1, 4) || '-' || substr(base, 5, 2) || '-' || substr(base, 7, 2) end, case when meal = 3 then 1 else meal + 1 end from cm
)
select cast( substr(base, 1, 4) || substr(base, 6, 2) || substr(base, 9, 2) as int) * 100 + meal from cm1
)
update options set currentmeal = (select meal_id from newcm);
drop view if exists z_mn;
create temp view z_mn as
with meal (m, mod2) as (
select options.currentmeal % 100, maxmeal % 2 from options, am_analysis_header
)
select case when mod2 = 0 then case when m = 1 then 'Z Breakfast' when m = 2 then 'Z Dinner' else 'Z Supper' end else case when m = 1 then 'Z Breakfast' when m = 2 then 'Z Dinner' else 'Z Supper' end end as mn, m from meal;
insert into currentmeal select NDB_No, Gm_Wgt, NutrDesc from theusual where meal_name = (select mn from z_mn);
drop view z_mn;
commit;
......@@ -279,6 +279,9 @@ insert into currentmeal values (99051, null, null);
-- Insert a food into the current meal with portion control for Panto. Acid.
insert into currentmeal values (99051, null, 'Panto. Acid');
-- Insert 90 grams of sardines into the current meal
insert into currentmeal values (15088, 90, null);
-- Update weight of sardines in the current meal to 2.5 ounces
uodate currentmeal set Gm_Wgt = 2.5 * 28.35 where NDB_No = 15088;
......
The database for NUTsqlite features denormalized tables and heavy Tcl
involvement to boost performance, and indeed, the performance is excellent.
However, it is a development dead-end because, if one picks some language other
than Tcl for a new nutrition program, the NUTsqlite database becomes useless
because it won't work without Tcl and has to be completely recoded.
The project to develop a database without Tcl wasn't getting anywhere because
of the tedium of working on an abstract API. I realized I needed to think of
the project as just another version of NUT that I could use if I liked it and I
immediately got interested. So, now you can run NUT from the command line
solely using SQL--no Tcl, no GUI, no compiling, etc.
bigNUT is the stand-alone SQLite version of NUT that can also be used as a
backend to future versions of NUT or other programs. In order to make headway
on the project, I realized I needed to think of it as just another version of
NUT that I could use if I liked it. As a result, you can use it without a
GUI or application program, although it is more effort to use it solely by
typing SQL commands and interpreting the output.
This will probably not interest most users, but if you understand what
NUTsqlite is doing and you are interested in SQL, trying to use this new
version may be an entertaining way to teach yourself SQL. If you are a
developer interested in a nutrition database, trying to use this database
can be a painless way to learn the NUT API without doing any coding or
attempting to fathom a lot of abstraction, and you can prune away the fluff
to get a useful pre-written backend for your application.
Here's how you do it. You need to have sqlite3 and you need to have the
NUT is doing and you are interested in SQL, trying to use the bigNUT
stand-alone version may be an entertaining way to teach yourself SQL.
If you are a developer interested in a nutrition database, trying to use
this database can be a painless way to learn the NUT API without doing any
coding or attempting to fathom a lot of abstraction, and you can prune away
the fluff to get a useful pre-written backend for your application. In
addition, there is the available functionality to do things such as
sequencing meals and/or personal option changes automatically and these
features are unlikely to be offered in any other nutrition program.
Here's how you can do it. You need to have sqlite3 and you need to have the
USDA ascii tables unzipped in your directory. You need to edit the
lite2big.tcl script to point to the NUTsqlite db (nut.sqlite) if you want to
transfer your NUTsqlite personal data to the new database; otherwise you omit
the final lite2big.tcl step from the following command sequence:
transfer your NUTsqlite-1.x personal data to the new database; otherwise you
omit the final lite2big.tcl step from the following command sequence:
sqlite3 -init load.sqlite3 nut.db
.quit
......@@ -30,21 +28,29 @@ sqlite3 -init logic.sqlite3 nut.db
.quit
./lite2big.tcl
You can use lite2big.tcl as often as you like, perhaps after every meal to cut
the effort involved using the big database. You only need the load.sqlite3 and
logic.sqlite3 init steps when initializing or upgrading to a new USDA database.
Neither loading nor refreshing the logic erases or changes your personal data.
To use the database all other times, type:
When running bigNUT as a stand-alone program, you only need the load.sqlite3
and logic.sqlite3 init steps when you are initializing or upgrading to a new
USDA database. Neither loading nor refreshing the logic erases or changes
any personal data. You also don't use these two init files when an
application such as NUTsqlite-2.x creates the nut.db database for you.
In this last case, bigNUT is in a subordinate directory from the database,
so to start bigNUT you would "sqlite3 -init bigNUT/user.sqlite3 nut.db".
Alternately, if you want to work from the bigNUT directory, you would specify
the database in the higher directory: "sqlite3 -init user.sqlite ../nut.db".
To use the stand-alone database all other times, type:
sqlite3 -init user.sqlite3 nut.db
Only the initial PRAGMA in user.sqlite3 that sets recursive triggers and the
code for automatic portion control are absolutely necessary at each invocation
of the database, but user.sqlite3 also has my personal views and triggers that
I have found helpful. You can add, delete, or change most of user.sqlite3 to
customize it as you wish. Read the comments and SQL in all the init files to
understand what is going on, and look at the EXAMPLES file to see SQL
statements that perform the most common NUT functions.
code for automatic portion control and the weight log are absolutely
necessary at each invocation of the database, but user.sqlite3 also has my
personal views and triggers that I have found helpful. You can add, delete,
or change most of user.sqlite3 to customize it as you wish. Also, there are
additional *.sqlite3 files that I produced to simplify operation. Read the
comments and SQL in all the init files to understand what is going on, and
look at the EXAMPLES file to see SQL statements that perform the most common
NUT functions.
Jim Jozwiak
http://nut.sourceforge.net
......
/*
This is the select that I use to look at the nutrient values for the
whole analysis period.
*/
select NutrDesc, round(Nutr_Val, 1) || ' ' || Units, cast(cast(round(100.0 + dvpct_offset) as int) as text) || '%' from am_analysis natural join am_dv natural join nutr_def order by dvpct_offset desc;
/*
The sequence series presents a series of customary meals and/or personal
options changes to simplify menu planning. When one looks at the latest
meal and decides another sequence would have been better, changesequence
backtracks and chooses another sequence.
*/
delete from currentmeal;
update options set currentmeal = (select max(meal_id) from mealfoods);
.sys rm sequence.sqlite3
.sys ln -s 1sequence.sqlite3 sequence.sqlite3
.read sequence.sqlite3
update options set defanal_am = 1;
/*
The sequence series presents a series of customary meals and/or personal
options changes to simplify menu planning. When one looks at the latest
meal and decides another sequence would have been better, changesequence
backtracks and chooses another sequence of meals and options.
*/
delete from currentmeal;
update options set currentmeal = (select max(meal_id) from mealfoods);
.sys rm sequence.sqlite3
.sys ln -s 3sequence.sqlite3 sequence.sqlite3
.read sequence.sqlite3
update options set defanal_am = 1;
/*
The sequence series presents a series of customary meals and/or personal
options changes to simplify menu planning. When one looks at the latest
meal and decides another sequence would have been better, changesequence
backtracks and chooses another sequence of meals and options.
*/
delete from currentmeal;
update options set currentmeal = (select max(meal_id) from mealfoods);
.sys rm sequence.sqlite3
.sys ln -s 8sequence.sqlite3 sequence.sqlite3
.read sequence.sqlite3
/*
The sequence series presents a series of customary meals and/or personal
options changes to simplify menu planning. When one looks at the latest
meal and decides another sequence would have been better, changesequence
backtracks and chooses another sequence of meals and options.
*/
delete from currentmeal;
update options set currentmeal = (select max(meal_id) from mealfoods);
.sys rm sequence.sqlite3
.sys ln -s 9sequence.sqlite3 sequence.sqlite3
.read sequence.sqlite3
begin;
/* Especially when you add a GUI and a second thread to handle the database, the
application runs much faster with write-ahead logging. However, to put the
database back into one file, issue the command "pragma journal_mode = delete;".
You would do this if you wanted to move the database to another system. If
you delete nut.db-wal and/or nut.db-shm manually, you will corrupt the database.
PRAGMA journal_mode = WAL;
*/
begin;
/* These temp tables must start out corresponding exactly to the USDA schemas
for import from the USDA's distributed files but in some cases we need
transitional temp tables to safely add what's new from the USDA to what the
......@@ -78,6 +87,7 @@ update tnutr_def set Tagname = 'F18D2T' where Nutr_No = 665;
update tnutr_def set Tagname = 'F18D2I' where Nutr_No = 666;
update tnutr_def set Tagname = 'F22D1C' where Nutr_No = 676;
update tnutr_def set Tagname = 'F18D3I' where Nutr_No = 856;
-- comment out the next line if you want to hassle the non-ascii micro char
update tnutr_def set Units = 'mcg' where hex(Units) = 'B567';
update tnutr_def set Units = 'kc' where Nutr_No = 208;
update tnutr_def set NutrDesc = 'Protein' where Nutr_No = 203;
......@@ -110,16 +120,16 @@ update tnutr_def set NutrDesc = 'Copper' where Nutr_No = 312;
update tnutr_def set NutrDesc = 'Fluoride' where Nutr_No = 313;
update tnutr_def set NutrDesc = 'Manganese' where Nutr_No = 315;
update tnutr_def set NutrDesc = 'Selenium' where Nutr_No = 317;
update tnutr_def set NutrDesc = 'Vitamin A' where Nutr_No = 318;
update tnutr_def set NutrDesc = 'Vit. A, IU' where Nutr_No = 318;
update tnutr_def set NutrDesc = 'Retinol' where Nutr_No = 319;
update tnutr_def set NutrDesc = 'Vit. A, RAE' where Nutr_No = 320;
update tnutr_def set NutrDesc = 'Vitamin A' where Nutr_No = 320;
update tnutr_def set NutrDesc = 'B-Carotene' where Nutr_No = 321;
update tnutr_def set NutrDesc = 'A-Carotene' where Nutr_No = 322;
update tnutr_def set NutrDesc = 'A-Tocopherol' where Nutr_No = 323;
update tnutr_def set NutrDesc = 'Vitamin D' where Nutr_No = 324;
update tnutr_def set NutrDesc = 'Vit. D, IU' where Nutr_No = 324;
update tnutr_def set NutrDesc = 'Vitamin D2' where Nutr_No = 325;
update tnutr_def set NutrDesc = 'Vitamin D3' where Nutr_No = 326;
update tnutr_def set NutrDesc = 'Vitamin D2+D3' where Nutr_No = 328;
update tnutr_def set NutrDesc = 'Vitamin D' where Nutr_No = 328;
update tnutr_def set NutrDesc = 'B-Cryptoxanth.' where Nutr_No = 334;
update tnutr_def set NutrDesc = 'Lycopene' where Nutr_No = 337;
update tnutr_def set NutrDesc = 'Lutein+Zeaxan.' where Nutr_No = 338;
......@@ -244,37 +254,44 @@ insert or ignore into tnutr_def values(3004,'g','LONG6','Long-chain Omega-6', NU
insert or ignore into tnutr_def values(2007,'g','OMEGA3','Omega-3', NULL, NULL);
insert or ignore into tnutr_def values(3005,'g','SHORT3','Short-chain Omega-3', NULL, NULL);
insert or ignore into tnutr_def values(3006,'g','LONG3','Long-chain Omega-3', NULL, NULL);
insert or ignore into tnutr_def values(2008,'IU','VITE','Vitamin E', NULL, NULL);
-- These are the new "daily value" labeling standards minus "ADDED SUGARS" which
-- have not yet appeared in the USDA data.
insert or ignore into tnutr_def values(2008,'mg','VITE','Vitamin E', NULL, NULL);
update tnutr_def set dv_default = 2000.0 where Tagname = 'ENERC_KCAL';
update tnutr_def set dv_default = 50.0 where Tagname = 'PROCNT';
update tnutr_def set dv_default = 65.0 where Tagname = 'FAT';
update tnutr_def set dv_default = 300.0 where Tagname = 'CHOCDF';
update tnutr_def set dv_default = 25.0 where Tagname = 'FIBTG';
update tnutr_def set dv_default = 275.0 where Tagname = 'CHO_NONFIB';
update tnutr_def set dv_default = 1000.0 where Tagname = 'CA';
update tnutr_def set dv_default = 1000.0 where Tagname = 'P';
update tnutr_def set dv_default = 78.0 where Tagname = 'FAT';
update tnutr_def set dv_default = 275.0 where Tagname = 'CHOCDF';
update tnutr_def set dv_default = 28.0 where Tagname = 'FIBTG';
update tnutr_def set dv_default = 247.0 where Tagname = 'CHO_NONFIB';
update tnutr_def set dv_default = 1300.0 where Tagname = 'CA';
update tnutr_def set dv_default = 1250.0 where Tagname = 'P';
update tnutr_def set dv_default = 18.0 where Tagname = 'FE';
update tnutr_def set dv_default = 2400.0 where Tagname = 'NA';
update tnutr_def set dv_default = 3500.0 where Tagname = 'K';
update tnutr_def set dv_default = 400.0 where Tagname = 'MG';
update tnutr_def set dv_default = 15.0 where Tagname = 'ZN';
update tnutr_def set dv_default = 2.0 where Tagname = 'CU';
update tnutr_def set dv_default = 2.0 where Tagname = 'MN';
update tnutr_def set dv_default = 70.0 where Tagname = 'SE';
update tnutr_def set dv_default = 5000.0 where Tagname = 'VITA_IU';
update tnutr_def set dv_default = 30.0 where Tagname = 'VITE';
update tnutr_def set dv_default = 80.0 where Tagname = 'VITK1';
update tnutr_def set dv_default = 1.5 where Tagname = 'THIA';
update tnutr_def set dv_default = 1.7 where Tagname = 'RIBF';
update tnutr_def set dv_default = 20.0 where Tagname = 'NIA';
update tnutr_def set dv_default = 10.0 where Tagname = 'PANTAC';
update tnutr_def set dv_default = 2.0 where Tagname = 'VITB6A';
update tnutr_def set dv_default = 2300.0 where Tagname = 'NA';
update tnutr_def set dv_default = 4700.0 where Tagname = 'K';
update tnutr_def set dv_default = 420.0 where Tagname = 'MG';
update tnutr_def set dv_default = 11.0 where Tagname = 'ZN';
update tnutr_def set dv_default = 0.9 where Tagname = 'CU';
update tnutr_def set dv_default = 2.3 where Tagname = 'MN';
update tnutr_def set dv_default = 55.0 where Tagname = 'SE';
update tnutr_def set dv_default = null where Tagname = 'VITA_IU';
update tnutr_def set dv_default = 900.0 where Tagname = 'VITA_RAE';
update tnutr_def set dv_default = 15.0 where Tagname = 'VITE';
update tnutr_def set dv_default = 120.0 where Tagname = 'VITK1';
update tnutr_def set dv_default = 1.2 where Tagname = 'THIA';
update tnutr_def set dv_default = 1.3 where Tagname = 'RIBF';
update tnutr_def set dv_default = 16.0 where Tagname = 'NIA';
update tnutr_def set dv_default = 5.0 where Tagname = 'PANTAC';
update tnutr_def set dv_default = 1.7 where Tagname = 'VITB6A';
update tnutr_def set dv_default = 400.0 where Tagname = 'FOL';
update tnutr_def set dv_default = 6.0 where Tagname = 'VITB12';
update tnutr_def set dv_default = 60.0 where Tagname = 'VITC';
update tnutr_def set dv_default = 2.4 where Tagname = 'VITB12';
update tnutr_def set dv_default = 550.0 where Tagname = 'CHOLN';
update tnutr_def set dv_default = 90.0 where Tagname = 'VITC';
update tnutr_def set dv_default = 20.0 where Tagname = 'FASAT';
update tnutr_def set dv_default = 300.0 where Tagname = 'CHOLE';
update tnutr_def set dv_default = 400.0 where Tagname = 'VITD';
update tnutr_def set dv_default = null where Tagname = 'VITD';
update tnutr_def set dv_default = 20.0 where Tagname = 'VITD_BOTH';
update tnutr_def set dv_default = 8.9 where Tagname = 'FAPU';
update tnutr_def set dv_default = 0.2 where Tagname = 'AA';
update tnutr_def set dv_default = 3.8 where Tagname = 'ALA';
......@@ -345,7 +362,7 @@ drop table tnut_data;
because the values are already there */
--insert VITE records into nut_data
insert or replace into nut_data select f.NDB_No, 2008, case when vite_added.Nutr_Val is null then tocpha.Nutr_Val * 1.5 when tocpha.Nutr_Val is null then vite_added.Nutr_Val / 0.45 else (vite_added.Nutr_Val / 0.45) + (tocpha.Nutr_Val - vite_added.Nutr_Val) * 1.5 end from food_des f left join nut_data tocpha on f.NDB_No = tocpha.NDB_No and tocpha.Nutr_No = 323 left join nut_data vite_added on f.NDB_No = vite_added.NDB_No and vite_added.Nutr_No = 573 where tocpha.Nutr_Val is not null or vite_added.Nutr_Val is not null;
insert or replace into nut_data select f.NDB_No, 2008, ifnull(tocpha.Nutr_Val, 0.0) from food_des f left join nut_data tocpha on f.NDB_No = tocpha.NDB_No and tocpha.Nutr_No = 323 where tocpha.Nutr_Val is not null;
--insert LA records into nut_data
insert or replace into nut_data select f.NDB_No, 2001, case when f18d2cn6.Nutr_Val is not null then f18d2cn6.Nutr_Val when f18d2.Nutr_Val is not null then f18d2.Nutr_Val - ifnull(f18d2t.Nutr_Val, 0.0) - ifnull(f18d2tt.Nutr_Val, 0.0) - ifnull(f18d2i.Nutr_Val, 0.0) - ifnull(f18d2cla.Nutr_Val, 0.0) end from food_des f left join nut_data f18d2 on f.NDB_No = f18d2.NDB_No and f18d2.Nutr_No = 618 left join nut_data f18d2cn6 on f.NDB_No = f18d2cn6.NDB_No and f18d2cn6.Nutr_No = 675 left join nut_data f18d2t on f.NDB_No = f18d2t.NDB_No and f18d2t.Nutr_No = 665 left join nut_data f18d2tt on f.NDB_No = f18d2tt.NDB_No and f18d2tt.Nutr_No = 669 left join nut_data f18d2i on f.NDB_No = f18d2i.NDB_No and f18d2i.Nutr_No = 666 left join nut_data f18d2cla on f.NDB_No = f18d2cla.NDB_No and f18d2cla.Nutr_No = 670 where f18d2.Nutr_Val is not null or f18d2cn6.Nutr_Val is not null or f18d2t.Nutr_Val is not null or f18d2tt.Nutr_Val is not null or f18d2i.Nutr_Val is not null or f18d2cla.Nutr_Val is not null;
......@@ -384,9 +401,9 @@ insert or replace into nut_data select f.NDB_No, 2007, ifnull(short3.Nutr_Val, 0
insert or replace into nut_data select f.NDB_No, 2000, case when chocdf.Nutr_Val - ifnull(fibtg.Nutr_Val, 0.0) < 0.0 then 0.0 else chocdf.Nutr_Val - ifnull(fibtg.Nutr_Val, 0.0) end from food_des f left join nut_data chocdf on f.NDB_No = chocdf.NDB_No and chocdf.Nutr_No = 205 left join nut_data fibtg on f.NDB_No = fibtg.NDB_No and fibtg.Nutr_No = 291 where chocdf.Nutr_Val is not null;
--replace empty strings with values for macronutrient factors in food_des
update food_des set Pro_Factor = 4.0 where Pro_Factor = '';
update food_des set Fat_Factor = 9.0 where Fat_Factor = '';
update food_des set CHO_Factor = 4.0 where CHO_Factor = '';
update food_des set Pro_Factor = 4.0 where Pro_Factor = '' or Pro_Factor is null;
update food_des set Fat_Factor = 9.0 where Fat_Factor = '' or Fat_Factor is null;
update food_des set CHO_Factor = 4.0 where CHO_Factor = '' or CHO_Factor is null;
--insert calories from macronutrients into nut_data
insert or replace into nut_data select f.NDB_No, 3000, f.Pro_Factor * procnt.Nutr_Val from food_des f join nut_data procnt on f.NDB_No = procnt.NDB_No and procnt.Nutr_No = 203;
......@@ -408,9 +425,10 @@ insert or replace into nut_data select f.NDB_No, 3002, f.CHO_Factor * chocdf.Nut
wltweak Part of the automatic calorie set feature. If NUT moves the
calories during a cycle to attempt better body composition,
wltweak is true. It is always changed to false at the
beginning of a cycle.
beginning of a cycle. However, current algorithm doesn't use it.
wlpolarity In order not to favor gaining lean mass over losing fat mass,
NUT cycles this between true and false to alternate strategies
NUT cycles this between true and false to alternate strategies.
However, current algorithm doesn't use it.
autocal 0 means no autocal feature, 2 means feature turned on.
The autocal feature moves calories to try to achieve
a calorie level that allows both fat mass loss and lean mass
......@@ -420,7 +438,11 @@ insert or replace into nut_data select f.NDB_No, 3002, f.CHO_Factor * chocdf.Nut
create table if not exists options(protect integer primary key, defanal_am integer default 2147123119, FAPU1 real default 0.0, meals_per_day int default 3, grams int default 1, currentmeal int default 0, wltweak integer default 0, wlpolarity integer default 0, autocal integer default 0);
/*
The table of what and how much eaten at each meal.
The table of what and how much eaten at each meal, plus a place for a
nutrient number to signify automatic portion control on this serving.
Automatic portion control (PCF) means add up everything from this meal
for this single nutrient and then adjust the quantity of this particular
food so that the daily value is exactly satisfied.
*/
create table if not exists mealfoods(meal_id int, NDB_No int, Gm_Wgt real, Nutr_No int, primary key(meal_id, NDB_No));
......
This diff is collapsed.
......@@ -2,4 +2,4 @@
This is the screen I look at when editing or viewing the current meal.
*/
select * from shopview; select * from currentmeal; select * from am_analysis_header;
select * from shopview; select plan_name || ': ' || cm_string || ' $' || cast(cast(100.0 * cost as int) / 100 as text) || '.' || substr(cast(100.0 * cost as int) % 100 + 100,2,2) from eating_plan, cm_string, food_cost_cm; select * from currentmeal; select * from am_analysis_header;
/*
Custom script to add next day's meals automatically. Invoke it thus:
.read nextday.sqlite3
*/
begin;
drop table if exists meal_add_list;
create temp table meal_add_list (n integer primary key, meal_id integer, meal_name text);
with meallist as (
with idbase as (
with nextday as (
with formattedld as (
with lastday as (select max(meal_id) / 100 from mealfoods)
select
substr( (select * from lastday), 1, 4 ) || '-' ||
substr( (select * from lastday), 5, 2 ) || '-' ||
substr( (select * from lastday), 7, 2 )
)
select date( (select * from formattedld), '+1 day')
)
select
substr( (select * from nextday), 1, 4 ) ||
substr( (select * from nextday), 6, 2 ) ||
substr( (select * from nextday), 9, 2 )
)
select (select * from idbase) * 100 + 1, 'BC' union
select (select * from idbase) * 100 + 2, 'DC' union
select (select * from idbase) * 100 + 3, 'SC'
)
insert into meal_add_list select null, * from meallist;
update options set currentmeal = (select meal_id from meal_add_list where n = 1);
insert into currentmeal select NDB_No, Gm_Wgt, NutrDesc from theusual where meal_name = (select meal_name from meal_add_list where n = 1);
update options set currentmeal = (select meal_id from meal_add_list where n = 2);
insert into currentmeal select NDB_No, Gm_Wgt, NutrDesc from theusual where meal_name = (select meal_name from meal_add_list where n = 2);
update options set currentmeal = (select meal_id from meal_add_list where n = 3);
insert into currentmeal select NDB_No, Gm_Wgt, NutrDesc from theusual where meal_name = (select meal_name from meal_add_list where n = 3);
drop table meal_add_list;
commit;
/*
This is the select that I use to look at the nutrient values for the current meal.
*/
select NutrDesc, round(Nutr_Val, 1) || ' ' || Units, cast(cast(round(100.0 + dvpct_offset) as int) as text) || '%' from rm_analysis natural join rm_dv natural join nutr_def order by dvpct_offset desc;