/* meal.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 "meal.h" #include "food.h" #include "util.h" #include "options.h" #include "db.h" #include #include #include #include struct meal theusual_root, *new_theusual, meal_root, *new_meal; void order_new_meal() { struct meal *meal_ptr = &meal_root; while (meal_ptr->next != NULL && strcmp(new_meal->meal_date, meal_ptr->next->meal_date) < 0) meal_ptr = meal_ptr->next; while (meal_ptr->next != NULL && strcmp(new_meal->meal_date, meal_ptr->next->meal_date) <= 0 && new_meal->meal < meal_ptr->next->meal) meal_ptr = meal_ptr->next; while (meal_ptr->next != NULL && strcmp(new_meal->meal_date, meal_ptr->next->meal_date) <= 0 && new_meal->meal <= meal_ptr->next->meal && strcmp(FoodIndex[new_meal->food_no]->name,FoodIndex[meal_ptr->next->food_no]->name) > 0) meal_ptr = meal_ptr->next; new_meal->next = meal_ptr->next; meal_ptr->next = new_meal; } void order_new_theusual() { struct meal *theusual_ptr = &theusual_root; while (theusual_ptr->next != NULL && strcmp(new_theusual->meal_date, theusual_ptr->next->meal_date) > 0) theusual_ptr = theusual_ptr->next; while (theusual_ptr->next != NULL && strcmp(new_theusual->meal_date, theusual_ptr->next->meal_date) >= 0 && strcmp(FoodIndex[new_theusual->food_no]->name,FoodIndex[theusual_ptr->next->food_no]->name) > 0) theusual_ptr = theusual_ptr->next; new_theusual->next = theusual_ptr->next; theusual_ptr->next = new_theusual; } struct meal *theusual_choice(char *screentitle, char *key) { struct meal *theusual_ptr; char meal_date[9]; char new_meal_date[9]; int c; for (c = 8; c < 17; c++) meal_date[c-8] = key[c]; for ( ; ; ) { theusual_ptr = theusual_find(meal_date); if (theusual_ptr != NULL) return theusual_ptr; header(screentitle); spacer(theusual_list()-1); printf("\nType \"The Usual\" Identifier (max. 8 characters): "); get_string(new_meal_date,8); if (strlen(new_meal_date) == 0) return (struct meal *) 0; for (c = 0 ; c < 9 ; c++) meal_date[c] = toupper(new_meal_date[c]); theusual_ptr = theusual_find(meal_date); if (theusual_ptr != NULL) return theusual_ptr; } } int meal_show(char *meal_date, int meal) { struct meal *meal_ptr = &meal_root; char namebuf[60]; int count = 0; printf("Meal Date: %s Meal Number: %d\n\n",meal_date,meal); for ( ; ; ) { if (strcmp(meal_date,meal_ptr->meal_date) == 0 && meal == meal_ptr->meal) { count++; strncpy(namebuf,FoodIndex[meal_ptr->food_no]->name,59); namebuf[59] = '\0'; if (options.grams) printf("%2d. %-59s %9.1f g\n",count,namebuf,meal_ptr->grams); if (!options.grams) printf("%2d. %-59s %8.1f oz\n",count,namebuf,meal_ptr->grams/28.35); } if (meal_ptr->next == NULL) break; meal_ptr = meal_ptr->next; } if (count == 0) { printf("\n\n\nNo foods have yet been recorded for this meal.\n"); spacer(6); return 0; } spacer(count + 2); return 1; } int theusual_show(char *meal_date) { struct meal *theusual_ptr = &theusual_root; char namebuf[60]; int count = 0; printf("\"The Usual\" Identifier: %s\n\n",meal_date); for ( ; ; ) { if (strcmp(meal_date,theusual_ptr->meal_date) == 0) { count++; strncpy(namebuf,FoodIndex[theusual_ptr->food_no]->name,59); namebuf[59] = '\0'; if (options.grams) printf("%2d. %-59s %9.1f g\n",count,namebuf,theusual_ptr->grams); if (!options.grams) printf("%2d. %-59s %8.1f oz\n",count,namebuf,theusual_ptr->grams/28.35); } if (theusual_ptr->next == NULL) break; theusual_ptr = theusual_ptr->next; } if (count == 0) { printf("\n\n\nNo foods have yet been recorded for this customary meal.\n"); spacer(6); return 0; } spacer(count + 2); return 1; } struct meal *meal_find(char *meal_date,int meal) { struct meal *meal_ptr = &meal_root; while (meal_ptr->next != NULL) { meal_ptr = meal_ptr->next; if (strcmp(meal_ptr->meal_date,meal_date) == 0 && meal_ptr->meal == meal) return meal_ptr; } return NULL; } struct meal *theusual_find(char *meal_date) { struct meal *theusual_ptr = &theusual_root; while (theusual_ptr->next != NULL) { theusual_ptr = theusual_ptr->next; if (strcmp(theusual_ptr->meal_date,meal_date) == 0) return theusual_ptr; } return NULL; } struct meal *prev_meal(struct meal *meal_after) { struct meal *meal_ptr = &meal_root; while (meal_ptr->next != meal_after) meal_ptr = meal_ptr->next; return meal_ptr; } void modify_meal(char *meal_date, int meal, int num, char *qty) { struct meal *m, *meal_ptr = &meal_root; int count = 0; float newqty; while (meal_ptr->next != NULL) { if (strcmp(meal_date,meal_ptr->next->meal_date) == 0 && meal == meal_ptr->next->meal) { count++; if (count == num) { newqty = evaluate_qty(food_number(meal_ptr->next->food_no),qty); if (newqty == 0) { m = meal_ptr->next; meal_ptr->next = meal_ptr->next->next; free(m); } else meal_ptr->next->grams = newqty; return; } } meal_ptr = meal_ptr->next; } } void delete_meal_with_ptr(struct meal *target) { struct meal *meal_ptr = &meal_root; while (meal_ptr->next != NULL) { if (meal_ptr->next == target) { meal_ptr->next = target->next; free(target); return; } meal_ptr = meal_ptr->next; } } void delete_theusual_with_ptr(struct meal *target) { struct meal *meal_ptr = &theusual_root; while (meal_ptr->next != NULL) { if (meal_ptr->next == target) { meal_ptr->next = target->next; free(target); return; } meal_ptr = meal_ptr->next; } } void modify_theusual(char *meal_date, int num, char *qty) { struct meal *m, *theusual_ptr = &theusual_root; int count = 0; float newqty; while (theusual_ptr->next != NULL) { if (strcmp(meal_date,theusual_ptr->next->meal_date) == 0) { count++; if (count == num) { newqty = evaluate_qty(food_number(theusual_ptr->next->food_no),qty); if (newqty == 0) { m = theusual_ptr->next; theusual_ptr->next = theusual_ptr->next->next; free(m); } else theusual_ptr->next->grams = newqty; return; } } theusual_ptr = theusual_ptr->next; } } int meal_count(struct meal *meal_ptr) { int count = 0; char lastdate[9]; int lastmeal; if (meal_ptr->next == NULL) return 0; meal_ptr = meal_ptr->next; strcpy(lastdate,meal_ptr->meal_date); lastmeal = meal_ptr->meal; count = 1; while ((meal_ptr = meal_ptr->next)) { if (strcmp(lastdate,meal_ptr->meal_date) != 0 || lastmeal != meal_ptr->meal) { count++; strcpy(lastdate,meal_ptr->meal_date); lastmeal = meal_ptr->meal; } } return count; } void delete_meals(int keep) { struct meal *meal_ptr = &meal_root, *last_meal_ptr = NULL; int count = 0; char meal_date[9], meal = 0; if (keep < 0) return; strcpy(meal_date,""); while (count <= keep && meal_ptr->next != NULL) { last_meal_ptr = meal_ptr; meal_ptr = meal_ptr->next; if (strcmp(meal_date,meal_ptr->meal_date) != 0 || meal != meal_ptr->meal) { count++; strcpy(meal_date,meal_ptr->meal_date); meal = meal_ptr->meal; } } if (count <= keep) return; last_meal_ptr->next = NULL; while (meal_ptr != NULL) { last_meal_ptr = meal_ptr; meal_ptr = meal_ptr->next; free(last_meal_ptr); } } int theusual_list() { struct meal *theusual_ptr = &theusual_root; char last_meal_date[9]; int c = 0; last_meal_date[0] = '\0'; printf("Customary Meals so far:\n\n"); while (theusual_ptr->next != NULL) { theusual_ptr = theusual_ptr->next; if (strcmp(last_meal_date,theusual_ptr->meal_date) == 0) continue; strcpy(last_meal_date,theusual_ptr->meal_date); printf(" %-8s",theusual_ptr->meal_date); c++; if (c%7 == 0) printf("\n"); else printf(" "); } return c/7+3; } void meal_list(char *bufptr) { struct meal *meal_ptr = &meal_root; int c; int missing[20]; for (c=0; c<20; c++) missing[c] = 0; while (meal_ptr->next != NULL && strcmp(bufptr,meal_ptr->meal_date) != 0) meal_ptr = meal_ptr->next; if (meal_ptr->next == NULL && strcmp(bufptr,meal_ptr->meal_date) != 0) { for (c = options.mealsperday; c >= 1; c--) { missing[0]++; missing[c] = 1; } } else for (c = options.mealsperday; c >= 1; c--) { if (c != meal_ptr->meal) { missing[0]++; missing[c] = 1; } while (c == meal_ptr->meal && meal_ptr->next != NULL && strcmp(bufptr,meal_ptr->next->meal_date) == 0) meal_ptr = meal_ptr->next; } if (missing[0] == 0) printf("\n\n\n"); else { printf("Missing Meals:\n\n"); for (c=1; c<20; c++) if (missing[c] == 1) printf("%-4d",c); printf("\n"); } } void reindex_meals(int foodnum) { struct meal *meal_ptr = &meal_root; while (meal_ptr->next != NULL) { meal_ptr = meal_ptr->next; if (meal_ptr->food_no >= foodnum) meal_ptr->food_no++; } meal_ptr = &theusual_root; while (meal_ptr->next != NULL) { meal_ptr = meal_ptr->next; if (meal_ptr->food_no >= foodnum) meal_ptr->food_no++; } } void full_meal_reindexing() { struct meal *meal_ptr = &meal_root; printf("\nStarting to re-index meals...\n"); while (meal_ptr->next != NULL) { if (meal_ptr->next->ndb_no == 0 && version(0) < 9) meal_ptr->next->ndb_no = 42231; meal_ptr->next->food_no = find_ndbno(meal_ptr->next->ndb_no); while (meal_ptr->next->food_no == -1) { delete_meal_with_ptr(meal_ptr->next); if (meal_ptr->next == NULL) break; if (meal_ptr->next->ndb_no == 0 && version(0) < 9) meal_ptr->next->ndb_no = 42231; meal_ptr->next->food_no = find_ndbno(meal_ptr->next->ndb_no); } if (meal_ptr->next != NULL) meal_ptr = meal_ptr->next; } if (meal_ptr->ndb_no == 0 && version(0) < 9) meal_ptr->ndb_no = 42231; meal_ptr->food_no = find_ndbno(meal_ptr->ndb_no); if (meal_ptr->food_no == -1) delete_meal_with_ptr(meal_ptr); meal_ptr = &theusual_root; while (meal_ptr->next != NULL) { if (meal_ptr->next->ndb_no == 0 && version(0) < 9) meal_ptr->next->ndb_no = 42231; meal_ptr->next->food_no = find_ndbno(meal_ptr->next->ndb_no); while (meal_ptr->next->food_no == -1) { delete_theusual_with_ptr(meal_ptr->next); if (meal_ptr->next == NULL) return; if (meal_ptr->next->ndb_no == 0 && version(0) < 9) meal_ptr->next->ndb_no = 42231; meal_ptr->next->food_no = find_ndbno(meal_ptr->next->ndb_no); } if (meal_ptr->next != NULL) meal_ptr = meal_ptr->next; } if (meal_ptr->ndb_no == 0 && version(0) < 9) meal_ptr->ndb_no = 42231; meal_ptr->food_no = find_ndbno(meal_ptr->ndb_no); if (meal_ptr->food_no == -1) delete_theusual_with_ptr(meal_ptr); } float average_cals(void) { struct meal *meal_ptr = &meal_root; float calsum = 0; int count; while (meal_ptr->next != NULL) { meal_ptr = meal_ptr->next; calsum += meal_ptr->grams / 100 * FoodIndex[meal_ptr->food_no]->nutrient[ENERC_KCAL]; } count = meal_count(&meal_root); if (count > 0) return calsum / count * options.mealsperday; else return 2000; }