//check for other similar meals that are close to the proposed meal //d - is the day to start checking from //t - is the meal type function proximityAllowable(d, t){ for (pDay=d-1; (pDay>0 && pDay>(d-minMealProximity-1)); pDay--){ //check against types of the already planned meals if (listContains(menu[pDay].type, t)){ return false; } } return true; } //check for repeat side-dishes //d - is the day to start checking from //iSide - is which side to check (integer, currently must be 1 or 2) //sSide - is the value of the side dish chosen function sideProximityAllowable(d, iSide, sSide){ if (sSide == ""){ return true; } for (pDay=d-1; (pDay>0 && pDay>(d-minSideProximity-1)); pDay--){ //check against types of the already planned meals if (listContains(evaluate("menu[pDay].side#iSide#"), sSide)){ return false; } } return true; } //this function implements all of our per-meal rules function mealAllowable(day, randMealTypeList){ for(t=1; t<=listLen(randMealTypeList); t++){ //for each type of the random meal if (minMealProximity > 0){ //allow 0-proximity check ("don't care") if (!(proximityAllowable(day, listGetAt(randMealTypeList, t)))){ return false; } }else{ return true; } } return true; } //as the function name should imply, this function will return a random item from the provided list function getRandomListItem(lst){ if (lst == ""){return "";} //return empty string if list is empty if (listLen(lst) == 1){return lst;} //if only one list item, don't bother randomizing, just return the 1 item r = Randomize(RandRange(1,100), "SHA1PRNG"); //use the new SHA1PRNG randomization method (why? I have no idea! But it's new!) itm = RandRange(1, listLen(lst), "SHA1PRNG"); //find random number within range of list items return listGetAt(lst, itm); //return random list item } //this function will: // - copy the meal struct from the meals array to the menu array // - if the meal has been used the maximum number of times, it is taken out of the meals array so it won't be chosen at random again function assignMeal(day, mealIndex){ menu_meals[mealIndex].spent++; menu[day] = menu_meals[mealIndex]; menu[day].side1 = getRandomListItem(menu_meals[mealIndex].side1); tries = 0; while (!(sideProximityAllowable(day, 1, menu_meals[mealIndex].side1)) && tries < 20){ menu[day].side1 = getRandomListItem(menu_meals[mealIndex].side1); tries++; } menu[day].side2 = getRandomListItem(fruit_n_veggie_list); tries = 0; while (!(sideProximityAllowable(day, 2, menu_meals[mealIndex].side2)) && tries < 20){ menu[day].side2 = getRandomListItem(menu_meals[mealIndex].side2); tries++; } if (menu_meals[mealIndex].spent >= menu_meals[mealIndex].maxFrequency){ //if meal used max number of times, remove it from the array to speed future searches up arrayDeleteAt(menu_meals, mealIndex); } } //displays a calendar view of the menu array function displayCal(){ crLF = chr(13) & chr(10); //carriage return & line feed WriteOutput("#crLF##crLF##MonthAsString(menuMonth)# #menuYear##crLF#"); WriteOutput("#crLF#"); WriteOutput("#crLF#"); WriteOutput("#crLF##crLF#"); WriteOutput("

#MonthAsString(menuMonth)# #menuYear#

#crLF#"); WriteOutput("
#crLF##crLF##crLF#"); WriteOutput("#crLF#"); for (spacer=1; spacer #crLF#"); //special case for weekend class, in case anyone wants to style those differently (note that there will never be a spacer in position 7, because then the whole week is blank and we should skip it) }else{ WriteOutput("#crLF#"); } } for (day=1; day<=daysInMonth; day++){ //display calendar this_dayOfWeek = DayOfWeek(CreateDate(menuYear, menuMonth, day)); if (this_dayOfWeek == 1 || this_dayOfWeek == 7){ if (menu[day].exception != ""){ addedClass = "class='weekend exception'"; } else{ addedClass = "class='weekend'"; } }else{ if (menu[day].exception != ""){ addedClass = "class='exception'"; } else{ addedClass = "class=''"; } } if (menu[day].exception == ""){ WriteOutput("#crLF#"); }else{ WriteOutput("#crLF#"); } if ((DayOfWeek(CreateDate(menuYear, menuMonth, day)) == 7) && (day < daysInMonth)){ //split weeks, part after && is to not create a new row if the last day of the month is a Saturday WriteOutput("#crLF##crLF#"); } } for (spacer=DayOfWeek(CreateDate(menuYear, menuMonth, daysInMonth)); spacer < 7; spacer++){ //pad end of calendar accordingly if (spacer == 7){ WriteOutput("#crLF#"); //special case for weekend class }else{ WriteOutput("#crLF#"); } } WriteOutput("#crLF#
SundayMondayTuesdayWednesdayThursdayFridaySaturday
 
#day#
#menu[day].name#"); if (menu[day].side1 != ""){ WriteOutput("
#menu[day].side1#"); } if (menu[day].side2 != ""){ WriteOutput("
#menu[day].side2#"); } WriteOutput("
#day#
#menu[day].exception#
  
#crLF#
"); //close last row and table }
SKIPPED", type="skipped", side1="", side2="", difficulty=1, maxFrequency=0, spent=0, exception=""}> bContinue = true; for (x_check = 1; x_check <= arrayLen(exceptions); x_check++){ if (exceptions[x_check].date == day){ menu[day] = exceptions[x_check]; menu[day].type = ""; //added here so that it's not needed when declaring exceptions - must exist for proximity check for nearby meals menu[day].side1 = ""; //same^ menu[day].side2 = ""; //same^ mealMatch = true; bContinue = false; break; } } if (bContinue){ randomMeal = RandRange(1, arrayLen(menu_meals)); //choose a meal at random if (day > 1){ if (mealAllowable(day, menu_meals[randomMeal].type)){ //does the random choice meet all requirements? assignMeal(day, randomMeal); mealMatch = true; } }else{ assignMeal(day, randomMeal); mealMatch = true; } }