/* ranking.c */ /* NUT nutrition software Copyright (C) 1996-2007 by Jim Jozwiak. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "ranking.h" #include "food.h" #include "util.h" #include "options.h" #include #include int Minut = -1; int Fdgrp = -1; void view_nuts(int opt) { int num = 0; char head[80]; for ( ; ; ) { if (opt == 0 && options.screen == 0) header("NUT: View \"Daily Values\" and Rank Foods by Nutrients per 100 Calories"); if (opt == 1 && options.screen == 0) header("NUT: View \"Daily Values\" and Rank Foods by Nutrients per 100 Grams"); if (opt == 3 && options.screen == 0) header("NUT: View \"Daily Values\" and Rank Foods by Nutrients per 100 Grams Dry Weight"); if (opt == 4 && options.screen == 0) header("NUT: View \"Daily Values\" and Rank Foods by Nutrients per Serving"); if (opt == 2 && options.screen == 0) header("NUT: View \"Daily Values\" and Rank Foods by Nutrients per Daily Recorded Meals"); if (opt == 0 && options.screen > 0) header("NUT: View Nutrients and Rank Foods by Nutrients per 100 Calories"); if (opt == 1 && options.screen > 0) header("NUT: View Nutrients and Rank Foods by Nutrients per 100 Grams"); if (opt == 3 && options.screen > 0) header("NUT: View Nutrients and Rank Foods by Nutrients per 100 Grams Dry Weight"); if (opt == 4 && options.screen > 0) header("NUT: View Nutrients and Rank Foods by Nutrients per Serving"); if (opt == 2 && options.screen > 0) header("NUT: View Nutrients and Rank Foods by Nutrients per Daily Recorded Meals"); if (opt == 5) { strcpy(head,"NUT: Rank Foods by Nutrients per Serving, Minimize "); strcat(head,Minut == -1 ? "?" : Nutrient[Minut]); header(head); nut_list(); if (Minut == -1) { printf("\nType number of Nutrient to Minimize (or to quit): "); num = get_int(); if (num < 1 || num > *ScreenMap[options.screen]) return; Minut = ScreenMap[options.screen][num]; } strcpy(head,"NUT: Rank Foods by Nutrients per Serving, Minimize "); strcat(head,Minut == -1 ? "?" : Nutrient[Minut]); header(head); } if (opt == 6) { strcpy(head,"NUT: Rank Foods by Nutrients within "); strcat(head,Fdgrp == -1 ? "?" : FdGrp[Fdgrp]); header(head); fdgrp_list(); if (Fdgrp == -1) { printf("\nType number of Food Group (or to quit): "); num = get_int(); if (num < 1 || num > MaxFdGrp) return; Fdgrp = FdGrpMap[num-1]; } strcpy(head,"NUT: Rank Foods by Nutrients within "); strcat(head,Fdgrp == -1 ? "?" : FdGrp[Fdgrp]); header(head); } nut_list(); printf("\nType number of Nutrient to see food rankings (or to quit): "); num = get_int(); if (num < 1 || num > *ScreenMap[options.screen]) return; rank_foods(ScreenMap[options.screen][num],opt); } } void rank_foods(int num, int opt) { int count, max = 0, junk, displayed = 0, meal = 0, meals = 0, maxmeal = options.defanal; int mincount = 0; float minavg = 0; float abacus[MAX_FOOD]; struct food *food_ptr = &food_root; struct meal *meal_ptr = &meal_root; char head[80]; char thisname[60], meal_date[9]; float theseounces, days; if (options.screen == 0) strcpy(head,"NUT: Foods Ranked by % of "); else strcpy(head,"NUT: Foods Ranked by "); if ( meal_count(options.temp_meal_root) < options.defanal || options.defanal == 0) { days = (float) meal_count(options.temp_meal_root) / (float) options.mealsperday; maxmeal = meal_count(options.temp_meal_root); } else { days = (float) options.defanal / (float) options.mealsperday; maxmeal = options.defanal; } strcat(head,Nutrient[num]); if (opt == 0 && options.screen == 0) strcat(head," DV per 100 Calories"); if (opt == 1 && options.screen == 0) strcat(head," DV per 100 Grams (3.5 oz)"); if (opt == 4 && options.screen == 0) strcat(head," DV per Serving"); if (opt == 2 && options.screen == 0) strcat(head," DV per Daily Recorded Meals"); if (opt == 3 && options.screen == 0) strcat(head," DV per 100 Grams Dry Weight"); if (opt == 0 && options.screen > 0) strcat(head," per 100 Calories"); if (opt == 1 && options.screen > 0) strcat(head," per 100 Grams (3.5 oz)"); if (opt == 3 && options.screen > 0) strcat(head," per 100 Grams Dry Weight"); if (opt == 4 && options.screen > 0) strcat(head," per Serving"); if (opt == 2 && options.screen > 0) strcat(head," per Daily Recorded Meals"); if (opt == 5) sprintf(head,"%-49s%14s %14s","NUT: Foods Ranked by Nutrients per Serving:",Nutrient[num],Nutrient[Minut]); if (opt == 6 && options.screen > 0) sprintf(head,"%-21s %1s %2s %-1s","NUT: Foods Ranked by",Nutrient[num],"in 100g",FdGrp[Fdgrp]); if (opt == 6 && options.screen == 0) sprintf(head,"%-21s %1s %2s %-1s","NUT: Foods Ranked by %DV",Nutrient[num],"in 100g",FdGrp[Fdgrp]); if (opt == 2 && meal_count(options.temp_meal_root) == 0) { header(head); printf("These rankings show which foods actually eaten are contributing to the Daily\n"); printf("Values, but there are no meals in the meal database.\n"); spacer(2); printf("\nPress to continue... "); junk = get_int(); return; } if (num == ENERC_KCAL && opt == 0 && options.screen == 0) { header(head); printf("These rankings are percentages of the \"Daily Value\" per 100 calories, to\n"); printf("identify the foods which provide a high daily percentage of a nutrient with\n"); printf("a low daily percentage of calories. Thus, calories are not ranked.\n"); spacer(3); printf("\nPress to continue... "); junk = get_int(); return; } if ((num == ENERC_KCAL || num == ENERC_KJ) && opt == 0 && options.screen > 0) { header(head); printf("These rankings are greatest nutrient values per 100 calories, to identify\n"); printf("foods which provide a high amount of a nutrient with low energy values.\n"); printf("Thus energy in kilocalories or kilojoules is not ranked.\n"); spacer(3); printf("\nPress to continue... "); junk = get_int(); return; } if (opt == 3 && num == WATER) { header(head); printf("These rankings subtract water from the food, so water itself is not ranked.\n"); spacer(1); printf("\nPress to continue... "); junk = get_int(); return; } if (opt == 1) for (count = 0 ; count < FoodCount ; count++) { food_ptr = food_ptr->next; if (options.screen == 0) abacus[count] = 100 * food_ptr->nutrient[num] / DV[num]; else abacus[count] = food_ptr->nutrient[num]; } if (opt == 6) for (count = 0 ; count < FoodCount ; count++) { food_ptr = food_ptr->next; if (options.screen == 0) abacus[count] = 100 * food_ptr->nutrient[num] / DV[num]; else abacus[count] = food_ptr->nutrient[num]; if (food_ptr->fdgrp != Fdgrp) abacus[count] = -1; } if (opt == 5) { for (count = 0 ; count < FoodCount ; count++) { food_ptr = food_ptr->next; if (! test_for_negative_zero(&food_ptr->nutrient[Minut])) { minavg += food_ptr->nutrient[Minut]; mincount++; } } if (mincount > 0) minavg /= mincount; food_ptr = &food_root; for (count = 0 ; count < FoodCount ; count++) { food_ptr = food_ptr->next; if (mincount == 0 || test_for_negative_zero(&food_ptr->nutrient[num]) || test_for_negative_zero(&food_ptr->nutrient[Minut]) || Minut == num || (num == VITE && Minut == TOCPHA) || (num == TOCPHA && Minut == VITE) || (num == LA && Minut == F18D2) || (num == F18D2 && Minut == LA) || (num == LA && Minut == F18D2CN6) || (num == F18D2CN6 && Minut == LA) || (num == AA && Minut == F20D4) || (num == F20D4 && Minut == AA) || (num == ALA && Minut == F18D3) || (num == F18D3 && Minut == ALA) || (num == ALA && Minut == F18D3CN3) || (num == F18D3CN3 && Minut == ALA) || (num == EPA && Minut == F20D5) || (num == F20D5 && Minut == EPA) || (num == DHA && Minut == F22D6) || (num == F22D6 && Minut == DHA)) abacus[count] = 0; else abacus[count] = (food_ptr->grams / -100 * food_ptr->nutrient[num]) * ((food_ptr->grams / 100 * food_ptr->nutrient[Minut] / minavg) - 1); } } if (opt == 0) for (count = 0 ; count < FoodCount ; count++) { food_ptr = food_ptr->next; if (food_ptr->nutrient[ENERC_KCAL] > 0) { if (options.screen == 0) abacus[count] = (10000 * food_ptr->nutrient[num]) / (food_ptr->nutrient[ENERC_KCAL] * DV[num]); else abacus[count] = 100 * food_ptr->nutrient[num] / food_ptr->nutrient[ENERC_KCAL]; } else abacus[count] = 0; } if (opt == 4) for (count = 0 ; count < FoodCount ; count++) { food_ptr = food_ptr->next; if (options.screen == 0) abacus[count] = (food_ptr->grams * food_ptr->nutrient[num]) / DV[num]; else abacus[count] = food_ptr->grams / 100 * food_ptr->nutrient[num]; } if (opt == 3) for (count = 0 ; count < FoodCount ; count++) { food_ptr = food_ptr->next; if (options.screen == 0) abacus[count] = (10000 * food_ptr->nutrient[num]) / ((100 - food_ptr->nutrient[WATER]) * DV[num]); if (options.screen > 0) abacus[count] = (100 * food_ptr->nutrient[num]) / (100 - food_ptr->nutrient[WATER]); } if (opt == 2) { for (count = 0 ; count < FoodCount ; count++) abacus[count] = 0; meal_ptr = options.temp_meal_root; meals = 0; while ( meal_ptr->next != NULL && meals <= maxmeal ) { meal_ptr = meal_ptr->next; if (strcmp(meal_date,meal_ptr->meal_date) != 0 || meal != meal_ptr->meal) { strcpy(meal_date,meal_ptr->meal_date); meal = meal_ptr->meal; meals++; } if ( meals <= maxmeal ) abacus[meal_ptr->food_no] += meal_ptr->grams; } for (count = 0 ; count < FoodCount ; count++) { abacus[count] /= days; if (options.screen == 0) abacus[count] *= FoodIndex[count]->nutrient[num] / DV[num]; if (options.screen > 0) abacus[count] *= FoodIndex[count]->nutrient[num]; } } junk = 'm'; max = max_array(abacus); while (displayed <= (FoodCount - 20) && (junk == 'm' || junk == 'M')) { header(head); for (count = 0; count < 20; count++) { if ( abacus[max] == 0 ) { max = FoodCount + 1; displayed = FoodCount + 1; spacer(count); count = 20; printf("\nPress to quit... "); junk = get_char(); break; } food_ptr = food_number(max); strncpy(thisname,food_ptr->name,54); thisname[54] = '\0'; if (opt == 5) strncpy(thisname,food_ptr->name,52); thisname[52] = '\0'; if (opt == 2 && options.screen == 0) { theseounces = abacus[max] * DV[num] / ( food_ptr->nutrient[num] * 28.35); if (options.grams) printf("%-54s %7.1f g %5.0f%%\n",thisname,theseounces*28.35,abacus[max]); if (!options.grams) printf("%-54s %6.1f oz %5.0f%%\n",thisname,theseounces,abacus[max]); } if (opt == 2 && options.screen > 0 && options.screen < 4) { theseounces = abacus[max] / (food_ptr->nutrient[num] * 28.35); if (options.grams) printf("%-54s %7.1f g %9.1f %-3s\n",thisname,theseounces*28.35,abacus[max]/100,Unit[num]); if (!options.grams) printf("%-54s %6.1f oz %9.1f %-3s\n",thisname,theseounces,abacus[max]/100,Unit[num]); } if (opt == 2 && options.screen > 3) { theseounces = abacus[max] / (food_ptr->nutrient[num] * 28.35); if (options.grams) printf("%-54s %7.1f g %9.2f %-3s\n",thisname,theseounces*28.35,abacus[max]/100,Unit[num]); if (!options.grams) printf("%-54s %6.1f oz %9.2f %-3s\n",thisname,theseounces,abacus[max]/100,Unit[num]); } if (opt == 1 && options.screen == 0) printf("%-54s %5.0f%%\n",thisname,abacus[max]); if (opt == 1 && options.screen > 0 && options.screen < 4) printf("%-54s %10.1f %-3s\n",thisname,abacus[max],Unit[num]); if (opt == 1 && options.screen > 0 && options.screen > 3) printf("%-54s %10.2f %-3s\n",thisname,abacus[max],Unit[num]); if (opt == 6 && options.screen == 0) printf("%-54s %5.0f%%\n",thisname,abacus[max]); if (opt == 6 && options.screen > 0 && options.screen < 4) printf("%-54s %10.1f %-3s\n",thisname,abacus[max],Unit[num]); if (opt == 6 && options.screen > 0 && options.screen > 3) printf("%-54s %10.2f %-3s\n",thisname,abacus[max],Unit[num]); if (opt == 3 && options.screen == 0 && options.grams) printf("%-54s %7.1f g %5.0f%%\n",thisname,10000 / (100 - food_ptr->nutrient[WATER]),abacus[max]); if (opt == 3 && options.screen == 0 && !options.grams) printf("%-54s %6.1f oz %5.0f%%\n",thisname,10000 / (100 - food_ptr->nutrient[WATER]) / 28.35,abacus[max]); if (opt == 3 && options.screen > 0 && options.screen < 4 && options.grams) printf("%-54s %7.1f g %9.1f %-3s\n",thisname,10000 / (100 - food_ptr->nutrient[WATER]),abacus[max],Unit[num]); if (opt == 3 && options.screen > 0 && options.screen < 4 && !options.grams) printf("%-54s %6.1f oz %9.1f %-3s\n",thisname,10000 / (100 - food_ptr->nutrient[WATER]) / 28.35,abacus[max],Unit[num]); if (opt == 3 && options.screen > 0 && options.screen > 3 && options.grams) printf("%-54s %7.1f g %9.2f %-3s\n",thisname,10000 / (100 - food_ptr->nutrient[WATER]),abacus[max],Unit[num]); if (opt == 3 && options.screen > 0 && options.screen > 3 && !options.grams) printf("%-54s %6.1f oz %9.2f %-3s\n",thisname,10000 / (100 - food_ptr->nutrient[WATER]) / 28.35,abacus[max],Unit[num]); if (opt == 0 && options.screen == 0 && options.grams) printf("%-54s %7.1f g %5.0f%%\n",thisname,10000 / food_ptr->nutrient[ENERC_KCAL],abacus[max]); if (opt == 0 && options.screen == 0 && !options.grams) printf("%-54s %6.1f oz %5.0f%%\n",thisname,10000 / food_ptr->nutrient[ENERC_KCAL] / 28.35,abacus[max]); if (opt == 0 && options.screen > 0 && options.screen < 4 && options.grams) printf("%-54s %7.1f g %9.1f %-3s\n",thisname,10000 / food_ptr->nutrient[ENERC_KCAL],abacus[max],Unit[num]); if (opt == 0 && options.screen > 0 && options.screen < 4 && !options.grams) printf("%-54s %6.1f oz %9.1f %-3s\n",thisname,10000 / food_ptr->nutrient[ENERC_KCAL] / 28.35,abacus[max],Unit[num]); if (opt == 0 && options.screen > 0 && options.screen > 3 && options.grams) printf("%-54s %7.1f g %9.2f %-3s\n",thisname,10000 / food_ptr->nutrient[ENERC_KCAL],abacus[max],Unit[num]); if (opt == 0 && options.screen > 0 && options.screen > 3 && !options.grams) printf("%-54s %6.1f oz %9.2f %-3s\n",thisname,10000 / food_ptr->nutrient[ENERC_KCAL] / 28.35,abacus[max],Unit[num]); if (opt == 5) printf("%-52s %7.1f %-3s %7.1f %-3s\n",thisname,food_ptr->grams / 100 * food_ptr->nutrient[num],Unit[num],food_ptr->grams / 100 * food_ptr->nutrient[Minut],Unit[Minut]); if (opt == 4 && options.screen == 0 && options.grams) printf("%-54s %7.1f g %5.0f%%\n",thisname,food_ptr->grams,abacus[max]); if (opt == 4 && options.screen == 0 && !options.grams) printf("%-54s %6.1f oz %5.0f%%\n",thisname,food_ptr->grams / 28.35,abacus[max]); if (opt == 4 && options.screen > 0 && options.screen < 4 && options.grams) printf("%-54s %7.1f g %9.1f %-3s\n",thisname,food_ptr->grams,abacus[max],Unit[num]); if (opt == 4 && options.screen > 0 && options.screen < 4 && !options.grams) printf("%-54s %6.1f oz %9.1f %-3s\n",thisname,food_ptr->grams / 28.35,abacus[max],Unit[num]); if (opt == 4 && options.screen > 0 && options.screen > 3 && options.grams) printf("%-54s %7.1f g %9.2f %-3s\n",thisname,food_ptr->grams,abacus[max],Unit[num]); if (opt == 4 && options.screen > 0 && options.screen > 3 && !options.grams) printf("%-54s %6.1f oz %9.2f %-3s\n",thisname,food_ptr->grams / 28.35,abacus[max],Unit[num]); abacus[max] = 0; max = max_array(abacus); } displayed += 20; if ( max < FoodCount && abacus[max] != 0 ) { printf("\nPress \"m\" for more (or just to quit)... "); junk = get_char(); } if ( abacus[max] == 0 && max < FoodCount ) { max = FoodCount + 1; spacer(count); printf("\nPress to quit... "); junk = get_char(); break; } } } int max_array(float abacus[]) { int count, i = 0; for ( count = 1 ; count < FoodCount ; count++ ) if (abacus[count] > abacus[i]) i = count; return i; } void nut_list() { int count; int intdiv = *ScreenMap[options.screen] / 2 + (*ScreenMap[options.screen] % 2 == 0 ? 0 : 1); for ( count = 0 ; count <= *ScreenMap[options.screen] / 2 - (*ScreenMap[options.screen] % 2 == 0 ? 1 : 0); count++) { if (options.screen == 0) { printf(" %2d. %-14s %7.1f %-3s ",count+1,Nutrient[ScreenMap[options.screen][count+1]],DV[ScreenMap[options.screen][count+1]],Unit[ScreenMap[options.screen][count+1]]); if (count+intdiv < *ScreenMap[options.screen]) printf(" %2d. %-14s %7.1f %-3s \n",count+1+intdiv,Nutrient[ScreenMap[options.screen][count+1+intdiv]],DV[ScreenMap[options.screen][count+1+intdiv]],Unit[ScreenMap[options.screen][count+1+intdiv]]); } else { printf(" %2d. %-14s %7s ",count+1,Nutrient[ScreenMap[options.screen][count+1]]," "); if (count+intdiv < *ScreenMap[options.screen]) printf(" %2d. %-14s\n",count+1+intdiv,Nutrient[ScreenMap[options.screen][count+1+intdiv]]); } if (count+intdiv >= *ScreenMap[options.screen]) printf("\n"); } spacer(count); } void fdgrp_list() { int count; int intdiv = MaxFdGrp / 2 + (MaxFdGrp % 2 == 0 ? 0 : 1); printf("\n\n"); for ( count = 0 ; count <= MaxFdGrp / 2 - (MaxFdGrp % 2 == 0 ? 1 : 0); count++) { printf("%2d. %-33s %1s ",count+1,FdGrp[FdGrpMap[count]]," "); if (count+intdiv < MaxFdGrp) printf("%2d. %-33s\n",count+1+intdiv,FdGrp[FdGrpMap[count+intdiv]]); if (count+intdiv >= MaxFdGrp) printf("\n"); } spacer(count+2); }