static TimetableOption[] GenerateTimetableOptions(Event[] events) { int combinations = 1; foreach (Event event_ in events) { combinations *= event_.options.Count(); } TimetableOption[] timetableOptions = new TimetableOption[combinations]; // setting first timetableOption to all zeroes timetableOptions[0] = new TimetableOption(new int[events.Count()]); for (int i = 0; i < timetableOptions[0].eventOptionIndices.Count(); i++) { timetableOptions[0].eventOptionIndices[i] = 0; } // generating all other possible combinations for (int i = 1; i < combinations; i++) { timetableOptions[i] = IterateTimetableOptionIndices(timetableOptions[i - 1], events); } return(timetableOptions); }
/// <summary> /// Basically a counter where the base of each digit is equal to the number of eventOptions available for that event /// </summary> private static TimetableOption IterateTimetableOptionIndices(TimetableOption timetableOptionIndices, Event[] events) { TimetableOption newTimetableOptionIndices = new TimetableOption((int[])timetableOptionIndices.eventOptionIndices.Clone()); for (int eventIndex = newTimetableOptionIndices.eventOptionIndices.Count() - 1; eventIndex > 0; eventIndex--) // should be while eventIndex > 0 so that it never directly iterates the most significant digit, otherwise it will eventually try to rollover into the [-1]th digit { newTimetableOptionIndices.eventOptionIndices[eventIndex]++; // then this pass rolls it over to 0, and the next index increases by one if (newTimetableOptionIndices.eventOptionIndices[eventIndex] == events[eventIndex].options.Count()) { newTimetableOptionIndices.eventOptionIndices[eventIndex] = 0; //newTimetableOptionIndices.eventOptionIndices[eventIndex - 1]++; // no need to iterate because it will hit the normal iteration line next anyway } else // just iterating the current eventIndex was fine, no further rollovers required { return(newTimetableOptionIndices); } } return(null); }
public Timetable(TimetableOption timetableOption, Event[] events) { // calling days constructors for (int day = 0; day < days.Count(); day++) { days[day] = new Day(); } // putting all predefined events into timetable for (int eventIndex = 0; eventIndex < events.Count(); eventIndex++) { EventOption eventOption = events[eventIndex].options[timetableOption.eventOptionIndices[eventIndex]]; for (int time = eventOption.startTime; time < eventOption.endTime; time++) { if (days[(int)eventOption.day].hours[time] != null) { // then an event is already on at this time, threfore this is a clash and the timetableOption is invalid valid = false; return; } else { // timeslot is available days[(int)eventOption.day].hours[time] = eventOption; } } } EventOption bikeRack = new EventOption("Transport", "", ",,Bike Rack.0.0,Bike Rack"); bikeRack.realClass = false; EventOption library = new EventOption("Study Time", "", ",,M.3.0,Library"); library.realClass = false; // entering M block as home location for gaps in timetable, entering I block bike rack as start and end caps for (int day = 0; day < days.Count(); day++) { // finding start time, setting bike rack start cap for (int hour = 0; hour < days[day].hours.Count(); hour++) { if (days[day].hours[hour] != null) { // first filled slot days[day].startTime = hour; if (hour >= 1) { days[day].hours[hour - 1] = bikeRack; } break; } } // finding end time, setting bike rack end cap for (int hour = days[day].hours.Count() - 1; hour >= 0; hour--) { if (days[day].hours[hour] != null) { // last filled slot days[day].endTime = hour + 1; if (hour < 23) { days[day].hours[hour + 1] = bikeRack; } break; } } // filling all empty slots with the library for (int hour = days[day].startTime; hour < days[day].endTime; hour++) { if (days[day].hours[hour] == null) { days[day].hours[hour] = library; } } } valid = true; // says that this timetable encountered no clashes while being constructed and could be used }