From f6e325350072fe3ece746e70f46e87dfddb66f2c Mon Sep 17 00:00:00 2001
From: Steve Brokenshire <sbrokenshire@xestia.co.uk>
Date: Sun, 19 Jun 2016 23:25:59 +0100
Subject: [PATCH] Added code and first unit tests for the GenerateMonthGrid
 function

---
 source/common/monthviewgen.cpp                | 209 ++++++++++++++++++
 source/common/monthviewgen.h                  |  24 ++
 source/tests/xestiacalendar_commonfunctions.h | 154 +++++++++++++
 3 files changed, 387 insertions(+)

diff --git a/source/common/monthviewgen.cpp b/source/common/monthviewgen.cpp
index a80adb4..f1bd702 100644
--- a/source/common/monthviewgen.cpp
+++ b/source/common/monthviewgen.cpp
@@ -70,3 +70,212 @@ int PreviousMonthNumberofDays(int Month, int Year){
 	
 }
 
+XCCalendarMonthViewGrid GenerateMonthGrid(int Month, int Year){
+	
+	XCCalendarMonthViewGrid MonthViewOutput;
+	
+	// Work out which day of the week the first day of 
+	// the month is.
+		
+	time_t EmptyTime;
+	struct tm * FirstDay;
+	int PreviousMonthNumDays = PreviousMonthNumberofDays(Month, Year);
+	int PreviousMonthDays = 0;
+	int PreviousMonth = 0;
+	int PreviousYear = Year;
+	int DayWeekCount = 0;
+	bool ProcessGrid = true;
+	bool FirstWeekProcessing = true;
+	
+	time(&EmptyTime);
+	
+	FirstDay = localtime(&EmptyTime);
+	FirstDay->tm_year = Year - 1900;
+	FirstDay->tm_mon = Month - 1;
+	FirstDay->tm_mday = 1;
+	
+	mktime(FirstDay);
+	
+	if (FirstDay->tm_wday == 0){
+		PreviousMonthDays = 6;
+	} else {
+		PreviousMonthDays = FirstDay->tm_wday - 1;
+	}
+	
+	if (Month == 1){
+		
+		PreviousMonth = 12;
+		PreviousYear--;
+		
+	} else {
+
+		PreviousMonth = Month - 1;
+		
+	}
+	
+	// Workout the days of the previous month for the
+	// first week to be displayed.
+	
+	XCCalendarMonthViewGridDayWeek FirstWeek;
+	
+	for (int PreviousMonthDaysProcessing = 0; 
+		PreviousMonthDaysProcessing < PreviousMonthDays; 
+		PreviousMonthDaysProcessing++){
+		
+		XCCalendarMonthViewGridDayData DayItem;
+			
+		DayItem.Day = PreviousMonthNumDays - PreviousMonthDaysProcessing;
+		DayItem.Month = PreviousMonth;
+		DayItem.Year = PreviousYear;
+		DayItem.IsInMonth = false;
+			
+		FirstWeek.DayList.insert(FirstWeek.DayList.begin(), DayItem);
+			
+		DayWeekCount++;
+			
+	}
+	
+	// Process the actual days of the month.
+
+	XCCalendarMonthViewGridDayWeek MonthWeek;
+	int ProcessDay = 1;
+	
+	while (ProcessGrid == true){
+		
+		if (DayWeekCount == 7){
+			
+			// Add to the month view grid.
+			
+			if (FirstWeekProcessing == true){
+				
+				FirstWeekProcessing = false;
+				MonthViewOutput.WeekList.push_back(FirstWeek);
+				
+			} else {
+			
+				MonthViewOutput.WeekList.push_back(MonthWeek);
+				MonthWeek.DayList.clear();
+				
+			}
+			
+			DayWeekCount = 0;
+			continue;
+			
+		}
+
+		XCCalendarMonthViewGridDayData DayItem;
+		
+		DayItem.Day = ProcessDay;
+		DayItem.Month = Month;
+		DayItem.Year = Year;
+		DayItem.IsInMonth = true;
+		
+		if (FirstWeekProcessing == true){
+			
+			FirstWeek.DayList.push_back(DayItem);
+			
+		} else {
+			
+			MonthWeek.DayList.push_back(DayItem);
+			
+		}
+
+		DayWeekCount++;
+		
+		if ((Month == 1 || Month == 3 || Month == 5 || 
+			Month == 7 || Month == 8 || Month == 10 || Month == 12) && 
+			ProcessDay == 31){
+	
+			break;
+			
+		}
+	
+		if ((Month == 4 || Month == 6 || Month == 9 || Month == 11) &&
+			ProcessDay == 30){
+		
+			break;
+		
+		}
+		
+		if (Year % 4 == 0){
+		
+			if (Year % 100 == 0){
+			
+				if (Year % 400 == 0){
+			
+					if (Month == 2 && ProcessDay == 29){
+					
+						break;
+						
+					}
+				
+				} else {
+				
+					if (Month == 2 && ProcessDay == 28){
+						
+						break;
+						
+					}
+				
+				}
+			
+			}
+		
+			if (Month == 2 && ProcessDay == 28){
+			
+				break;
+				
+			}
+		
+		} else if (Month == 2 && ProcessDay == 28){
+		
+			break;
+		
+		}
+		
+		ProcessDay++;
+		
+		
+	}
+	
+	// At the end of the month add any remaining days
+	// (if required).
+	
+	int NextMonthYear = Year;
+	int NextMonth = 0;
+	int NextMonthDay = 1;
+	
+	if (Month == 12){
+		
+		NextMonth = 1;
+		NextMonthYear++;
+		
+	} else {
+		
+		NextMonth = Month + 1;
+		
+	}
+	
+	for (; DayWeekCount < 7; DayWeekCount++){
+	
+		XCCalendarMonthViewGridDayData DayItem;
+		
+		DayItem.Day = NextMonthDay;
+		DayItem.Month = NextMonth;
+		DayItem.Year = NextMonthYear;
+		DayItem.IsInMonth = false;
+
+		MonthWeek.DayList.push_back(DayItem);
+		NextMonthDay++;
+		
+	}
+	
+	if (DayWeekCount == 7){
+
+		MonthViewOutput.WeekList.push_back(MonthWeek);
+		
+	}
+	
+	return MonthViewOutput;
+	
+}
\ No newline at end of file
diff --git a/source/common/monthviewgen.h b/source/common/monthviewgen.h
index e711167..ee046ca 100644
--- a/source/common/monthviewgen.h
+++ b/source/common/monthviewgen.h
@@ -23,6 +23,30 @@
 #include <ctime>
 #include <iostream>
 
+using namespace std;
+
+struct XCCalendarMonthViewGridDayData{
+	
+	int Day = 1;
+	int Month = 1;
+	int Year = 1;
+	bool IsInMonth = false;
+	
+};
+
+struct XCCalendarMonthViewGridDayWeek{
+	
+	vector<XCCalendarMonthViewGridDayData> DayList;
+	
+};
+
+struct XCCalendarMonthViewGrid{
+	
+	vector<XCCalendarMonthViewGridDayWeek> WeekList;
+	
+};
+
+XCCalendarMonthViewGrid GenerateMonthGrid(int Month, int Year);
 int PreviousMonthNumberofDays(int Month, int Year);
 
 #endif
\ No newline at end of file
diff --git a/source/tests/xestiacalendar_commonfunctions.h b/source/tests/xestiacalendar_commonfunctions.h
index 225d0a4..3bdc14c 100644
--- a/source/tests/xestiacalendar_commonfunctions.h
+++ b/source/tests/xestiacalendar_commonfunctions.h
@@ -462,4 +462,158 @@ TEST(CommonFunctions, PreviousMonthNumberofDays){
 	
 }
 
+TEST(CommonFunctions, MonthViewGenerator){
+	
+	XCCalendarMonthViewGrid MonthView = GenerateMonthGrid(6, 2016);
+
+	// First week.
+	
+	ASSERT_EQ(30, MonthView.WeekList[0].DayList[0].Day);
+	ASSERT_EQ(5, MonthView.WeekList[0].DayList[0].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[0].DayList[0].Year);
+
+	ASSERT_EQ(31, MonthView.WeekList[0].DayList[1].Day);
+	ASSERT_EQ(5, MonthView.WeekList[0].DayList[1].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[0].DayList[1].Year);
+
+	ASSERT_EQ(1, MonthView.WeekList[0].DayList[2].Day);
+	ASSERT_EQ(6, MonthView.WeekList[0].DayList[2].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[0].DayList[2].Year);
+
+	ASSERT_EQ(2, MonthView.WeekList[0].DayList[3].Day);
+	ASSERT_EQ(6, MonthView.WeekList[0].DayList[3].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[0].DayList[3].Year);
+
+	ASSERT_EQ(3, MonthView.WeekList[0].DayList[4].Day);
+	ASSERT_EQ(6, MonthView.WeekList[0].DayList[4].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[0].DayList[4].Year);
+
+	ASSERT_EQ(4, MonthView.WeekList[0].DayList[5].Day);
+	ASSERT_EQ(6, MonthView.WeekList[0].DayList[5].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[0].DayList[5].Year);
+
+	ASSERT_EQ(5, MonthView.WeekList[0].DayList[6].Day);
+	ASSERT_EQ(6, MonthView.WeekList[0].DayList[6].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[0].DayList[6].Year);
+
+	// Second week.
+	
+	ASSERT_EQ(6, MonthView.WeekList[1].DayList[0].Day);
+	ASSERT_EQ(6, MonthView.WeekList[1].DayList[0].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[1].DayList[0].Year);
+
+	ASSERT_EQ(7, MonthView.WeekList[1].DayList[1].Day);
+	ASSERT_EQ(6, MonthView.WeekList[1].DayList[1].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[1].DayList[1].Year);
+
+	ASSERT_EQ(8, MonthView.WeekList[1].DayList[2].Day);
+	ASSERT_EQ(6, MonthView.WeekList[1].DayList[2].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[1].DayList[2].Year);
+
+	ASSERT_EQ(9, MonthView.WeekList[1].DayList[3].Day);
+	ASSERT_EQ(6, MonthView.WeekList[1].DayList[3].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[1].DayList[3].Year);
+
+	ASSERT_EQ(10, MonthView.WeekList[1].DayList[4].Day);
+	ASSERT_EQ(6, MonthView.WeekList[1].DayList[4].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[1].DayList[4].Year);
+
+	ASSERT_EQ(11, MonthView.WeekList[1].DayList[5].Day);
+	ASSERT_EQ(6, MonthView.WeekList[1].DayList[5].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[1].DayList[5].Year);
+
+	ASSERT_EQ(12, MonthView.WeekList[1].DayList[6].Day);
+	ASSERT_EQ(6, MonthView.WeekList[1].DayList[6].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[1].DayList[6].Year);
+	
+	// Third Week.
+	
+	ASSERT_EQ(13, MonthView.WeekList[2].DayList[0].Day);
+	ASSERT_EQ(6, MonthView.WeekList[2].DayList[0].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[2].DayList[0].Year);
+
+	ASSERT_EQ(14, MonthView.WeekList[2].DayList[1].Day);
+	ASSERT_EQ(6, MonthView.WeekList[2].DayList[1].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[2].DayList[1].Year);
+
+	ASSERT_EQ(15, MonthView.WeekList[2].DayList[2].Day);
+	ASSERT_EQ(6, MonthView.WeekList[2].DayList[2].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[2].DayList[2].Year);
+
+	ASSERT_EQ(16, MonthView.WeekList[2].DayList[3].Day);
+	ASSERT_EQ(6, MonthView.WeekList[2].DayList[3].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[2].DayList[3].Year);
+
+	ASSERT_EQ(17, MonthView.WeekList[2].DayList[4].Day);
+	ASSERT_EQ(6, MonthView.WeekList[2].DayList[4].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[2].DayList[4].Year);
+
+	ASSERT_EQ(18, MonthView.WeekList[2].DayList[5].Day);
+	ASSERT_EQ(6, MonthView.WeekList[2].DayList[5].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[2].DayList[5].Year);
+
+	ASSERT_EQ(19, MonthView.WeekList[2].DayList[6].Day);
+	ASSERT_EQ(6, MonthView.WeekList[2].DayList[6].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[2].DayList[6].Year);
+	
+	// Fourth week.
+	
+	ASSERT_EQ(20, MonthView.WeekList[3].DayList[0].Day);
+	ASSERT_EQ(6, MonthView.WeekList[3].DayList[0].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[3].DayList[0].Year);
+
+	ASSERT_EQ(21, MonthView.WeekList[3].DayList[1].Day);
+	ASSERT_EQ(6, MonthView.WeekList[3].DayList[1].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[3].DayList[1].Year);
+
+	ASSERT_EQ(22, MonthView.WeekList[3].DayList[2].Day);
+	ASSERT_EQ(6, MonthView.WeekList[3].DayList[2].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[3].DayList[2].Year);
+
+	ASSERT_EQ(23, MonthView.WeekList[3].DayList[3].Day);
+	ASSERT_EQ(6, MonthView.WeekList[3].DayList[3].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[3].DayList[3].Year);
+
+	ASSERT_EQ(24, MonthView.WeekList[3].DayList[4].Day);
+	ASSERT_EQ(6, MonthView.WeekList[3].DayList[4].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[3].DayList[4].Year);
+
+	ASSERT_EQ(25, MonthView.WeekList[3].DayList[5].Day);
+	ASSERT_EQ(6, MonthView.WeekList[3].DayList[5].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[3].DayList[5].Year);
+
+	ASSERT_EQ(26, MonthView.WeekList[3].DayList[6].Day);
+	ASSERT_EQ(6, MonthView.WeekList[3].DayList[6].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[3].DayList[6].Year);	
+
+	// Fifth week.
+	
+	ASSERT_EQ(27, MonthView.WeekList[4].DayList[0].Day);
+	ASSERT_EQ(6, MonthView.WeekList[4].DayList[0].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[4].DayList[0].Year);
+
+	ASSERT_EQ(28, MonthView.WeekList[4].DayList[1].Day);
+	ASSERT_EQ(6, MonthView.WeekList[4].DayList[1].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[4].DayList[1].Year);
+
+	ASSERT_EQ(29, MonthView.WeekList[4].DayList[2].Day);
+	ASSERT_EQ(6, MonthView.WeekList[4].DayList[2].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[4].DayList[2].Year);
+
+	ASSERT_EQ(30, MonthView.WeekList[4].DayList[3].Day);
+	ASSERT_EQ(6, MonthView.WeekList[4].DayList[3].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[4].DayList[3].Year);
+
+	ASSERT_EQ(1, MonthView.WeekList[4].DayList[4].Day);
+	ASSERT_EQ(7, MonthView.WeekList[4].DayList[4].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[4].DayList[4].Year);
+
+	ASSERT_EQ(2, MonthView.WeekList[4].DayList[5].Day);
+	ASSERT_EQ(7, MonthView.WeekList[4].DayList[5].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[4].DayList[5].Year);
+
+	ASSERT_EQ(3, MonthView.WeekList[4].DayList[6].Day);
+	ASSERT_EQ(7, MonthView.WeekList[4].DayList[6].Month);
+	ASSERT_EQ(2016, MonthView.WeekList[4].DayList[6].Year);
+
 }
\ No newline at end of file
-- 
2.39.5