diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1f06bff
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+/images/
+/__pycache__/
+/weatherfiles/
+/.git/
+/Weatherman.pdf
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5da473e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,140 @@
+# Weather Man
+weatherfiles.zip contains weather data files for Murree in multiple formats. Write an application that generates the following reports. The user can specify more than one report at the same time.
+The program should have the following components:
+* It should extract the files into a destination folder and execute further tasks as described below.
+* A data structure for holding each weather reading.
+* A parser for parsing the files and populating the reading data structure with correct data types.
+* A data structure for holding the calculations results.
+* A module for computing the calculations given the readings.
+* A report generator for creating the reports given the computation results.
+* PEP-8 conventions should be followed in the code.
+* Your code should be concise and self-explanatory and understandable.
+
+## 1. For a given year display the highest temperature, the lowest temperature and humidity.
+#### Command to execute:
+
+_weatherman.py /path/to/files-dir -e 2002_
+
+#### Example Output:
+
+Highest: 45C on June 23
+
+Lowest: 01C on December 22
+
+Humidity: 95% on August 14
+
+## 2. For a given month display the average highest temperature, average lowest temperature, average mean humidity.
+#### Command to execute:
+
+_weatherman.py /path/to/files-dir -a 2005/6_
+
+#### Example Output:
+
+Highest Average: 39C
+
+Lowest Average: 18C
+
+Average Mean Humidity: 71%
+
+## 3. For a given month draw horizontal bar charts on the console for the highest and lowest temperature on each day. Highest in red and lowest in blue.
+#### Command to execute:
+
+_weatherman.py /path/to/files-dir -c 2011/03_
+
+
+#### Example Output:
+
+March 2011
+
+01 +++++++++++++++++++++++++ 25C
+
+01 +++++++++++ 11C
+
+02 ++++++++++++++++++++++ 22C
+
+02 ++++++++ 08C
+
+## 4. Multiple Reports should be generated if multiple available options are passed to application
+#### Command to execute:
+_weatherman.py /path/to/files-dir -c 2011/03 -a 2011/3 -e 2011_
+
+## 5. BONUS TASK. For a given month draw one horizontal bar chart on the console for the highest and lowest temperature on each day. Highest in red and lowest in blue.
+#### Command to execute:
+_weatherman.py /path/to/files-dir -b 2011/3_
+#### Example output:
+March 2011
+
+01 ++++++++++++++++++++++++++++++++++++ 11C - 25C
+
+02 ++++++++++++++++++++++++++++++ 08C - 22C
+
+
+# Virtual Environment
+### Install virtualenv and virtualenvwrapper
+_pip install virtualenv_
+
+_pip install virtualenvwrapper_
+### Add variables to path (Recommended)
+
+export WORKON_HOME=$HOME/.virtualenv
+
+export PROJECT_HOME=$HOME/projects
+### Find virtualenvwrapper and run it
+_which virtualenvwrapper.sh_
+
+_The command will output a path similar to this "/usr/local/bin/virtualenvwrapper.sh"_
+
+Enter the following command to run this file
+
+_source /usr/local/bin/virtualenvwrapper.sh_
+
+### Reload startup file ".bashrc"
+_source ~/.bashrc_
+
+### Create a new virtual environment
+_mkvirtualenv env-name_
+
+This environment will be loaded automatically after successful creation, if it is not loaded use
+
+_workon env-name_
+
+### Installing requirements
+Run the following command in the environment to install the requirements
+
+_pip install -r requirements.txt_
+
+# Usage
+
+
+### - For yearly report, execute
+python3 weatherman.py path/to/all/files -e year
+#### Example
+python3 weatherman.py weatherfiles/ -e 2015
+
+
+
+
+### - For monthly report, execute
+python3 weatherman.py path/to/all/files -a year/month
+#### Example
+python3 weatherman.py weatherfiles/ -a 2015/02
+
+
+
+
+### - For monthly graph (two lines), execute
+python3 weatherman.py path/to/all/files -c year/month
+#### Example
+python3 weatherman.py weatherfiles/ -c 2015/02
+
+ output")
+
+
+### - For monthly graph (single line), execute
+python3 weatherman.py path/to/all/files -b year/month
+#### Example
+python3 weatherman.py weatherfiles/ -b 2015/02
+
+ output")
+
+
diff --git a/WeatherData.py b/WeatherData.py
new file mode 100644
index 0000000..4dbebfb
--- /dev/null
+++ b/WeatherData.py
@@ -0,0 +1,115 @@
+class WeatherData:
+ """This class holds all the data of the weather.
+
+ Methods:
+ To add data in the structure, use method add_month_data
+ To get data use "get_column_data" method with month and year
+ To get the column name use method get_column_name_from_alias.
+ Valid aliases are
+ max_temperature
+ min_temperature
+ max_humidity
+ min_humidity
+ mean_humidity
+
+ Data Structure:
+ It contains a single dict whose all values are also dict
+ complete_data (data)
+ year 1 (dict)
+ month 1 (dict)
+ Weather Attribute 1 (dict)
+ weather_attribute_of_month (list)
+ Weather Attribute 2 (dict)
+ ...
+ month 2 (dict)
+ ...
+ year 2 (dict)
+ ...
+ To get an attribute for a month, we would use
+ complete_data[year][month][weather_attribute]
+ It will return a list
+ """
+
+ def __init__(self):
+ self.__complete_data = {}
+ # column names mapping from text to variables
+ self.__max_temp_c = "Max TemperatureC"
+ self.__min_temp_c = "Min TemperatureC"
+ self.__max_humidity = "Max Humidity"
+ self.__min_humidity = "Min Humidity"
+ self.__mean_humidity = "Mean Humidity"
+
+ def add_month_data(self, month: int, year: int, month_data):
+ """Stores month weather information in data structure
+
+ Arguments:
+ month: int:
+ integer range(1-12)
+ year: int:
+ integer representing year
+ month_data: dict:
+ dictionary having data of all days
+ """
+
+ if not (0 < month < 13):
+ print("Invalid month ", month, ". Data not added")
+ return
+ month = str(month)
+ year = str(year)
+ if year not in self.__complete_data:
+ self.__complete_data[year] = {}
+ if month not in self.__complete_data[year]:
+ self.__complete_data[year][month] = {}
+ self.__complete_data[year][month] = month_data
+ return
+
+ def get_column_name_from_alias(self, string):
+ """Returns column name from alias
+
+ Arguments:
+ string: str:
+ Pass alias to get column name
+ Valid aliases are
+ max_temperature
+ min_temperature
+ max_humidity
+ min_humidity
+ mean_humidity
+ """
+
+ string = string.lower()
+ alias_name_mapping_dictionary = {
+ "max_temperature": self.__max_temp_c,
+ "min_temperature": self.__min_temp_c,
+ "max_humidity": self.__max_humidity,
+ "min_humidity": self.__min_humidity,
+ "mean_humidity": self.__mean_humidity
+ }
+ return alias_name_mapping_dictionary.get(string, None)
+
+ def get_column_data(self, column_name, month: int, year: int):
+ """Returns column data from column name, month and year
+
+ Arguments:
+ column_name: str:
+ column name whose data is required
+ month: int:
+ month in integer range(1-12)
+ year: int:
+ integer representing year
+
+ Returns:
+ column_data: list:
+ list that contains the whole month data
+ """
+
+ if not (0 < month < 13):
+ print("Invalid month", month)
+ return []
+ month = str(month)
+ year = str(year)
+ try:
+ return self.__complete_data[year][month][column_name]
+ except Exception:
+ print("Data not found for " + year + "/" + month)
+ return []
diff --git a/common.py b/common.py
new file mode 100644
index 0000000..a8abd3e
--- /dev/null
+++ b/common.py
@@ -0,0 +1,86 @@
+from constants import MONTH_NUMBER_STRING_MAPPING
+
+
+def get_month_year_from_string(month_year_string):
+ """Returns month and year from combined string
+ month and year should be numbers and separated with "/"
+
+ Arguments:
+ month_year_string: str
+ String containing month year in format mm/yyyy
+
+ Returns:
+ month: int, year: int
+ Month and year separated in integer
+ """
+
+ try:
+ month, year = month_year_string.split('/')
+ month = int(month)
+ year = int(year)
+ except ValueError:
+ print("Invalid month/year. Input must be of format yyyy/mm")
+ return None, None
+ return month, year
+
+
+def get_month_number_from_string(month_string):
+ """
+ Converts 3 characters month name to month number
+
+ Arguments:
+ month_string: str
+ String containing month
+
+ Returns:
+ month: int
+ Returns month as number from string
+ """
+
+ month_string = str(month_string).lower()
+ month_key_list = list(MONTH_NUMBER_STRING_MAPPING.keys())
+ month_values_list = list(MONTH_NUMBER_STRING_MAPPING.values())
+ month_values_list = [value.lower() for value in month_values_list]
+
+ try:
+ index_to_retrieve = month_values_list.index(month_string)
+ except ValueError:
+ return None
+ return month_key_list[index_to_retrieve]
+
+
+def get_month_string_from_number(month_number: int):
+ """Converts integer number to 3 character month name
+
+ Argument:
+ number: int
+
+ Returns:
+ string: str:
+ String of length 3 that represents month
+ """
+
+ return MONTH_NUMBER_STRING_MAPPING.get(month_number, "")
+
+
+def get_column_data_from_alias(weather_data, alias, month, year):
+ """Returns column data from alias
+
+ Arguments:
+ weather_data: dict:
+ Contains complete weather data
+ alias: str:
+ Alias of column
+ month: int:
+ Month whose data is required
+ year: int:
+ Year whose data is required
+
+ Returns:
+ list_: list:
+ Complete column data from alias
+ """
+ attrib_name = weather_data.get_column_name_from_alias(alias)
+ if attrib_name is None:
+ return []
+ return weather_data.get_column_data(attrib_name, month, year)
diff --git a/constants.py b/constants.py
new file mode 100644
index 0000000..0554094
--- /dev/null
+++ b/constants.py
@@ -0,0 +1,40 @@
+TEXT_STYLE_NORMAL = 0
+TEXT_STYLE_BOLD = 1
+TEXT_STYLE_LIGHT = 2
+TEXT_STYLE_ITALICIZED = 3
+TEXT_STYLE_UNDERLINED = 4
+TEXT_STYLE_BLINK = 5
+
+TEXT_COLOR_BLACK = 30
+TEXT_COLOR_RED = 31
+TEXT_COLOR_GREEN = 32
+TEXT_COLOR_YELLOW = 33
+TEXT_COLOR_BLUE = 34
+TEXT_COLOR_PURPLE = 35
+TEXT_COLOR_CYAN = 36
+TEXT_COLOR_WHITE = 37
+
+BACKGROUND_COLOR_BLACK = 40
+BACKGROUND_COLOR_RED = 41
+BACKGROUND_COLOR_GREEN = 42
+BACKGROUND_COLOR_YELLOW = 43
+BACKGROUND_COLOR_BLUE = 44
+BACKGROUND_COLOR_PURPLE = 45
+BACKGROUND_COLOR_CYAN = 46
+BACKGROUND_COLOR_WHITE = 47
+
+
+MONTH_NUMBER_STRING_MAPPING = {
+ 1: "Jan",
+ 2: "Feb",
+ 3: "Mar",
+ 4: "Apr",
+ 5: "May",
+ 6: "Jun",
+ 7: "Jul",
+ 8: "Aug",
+ 9: "Sep",
+ 10: "Oct",
+ 11: "Nov",
+ 12: "Dec"
+}
diff --git a/generate_reports.py b/generate_reports.py
new file mode 100644
index 0000000..b485823
--- /dev/null
+++ b/generate_reports.py
@@ -0,0 +1,331 @@
+from common import get_column_data_from_alias
+from common import get_month_string_from_number
+from constants import TEXT_STYLE_NORMAL, TEXT_STYLE_BOLD
+from constants import TEXT_COLOR_RED, TEXT_COLOR_BLUE
+from constants import TEXT_COLOR_WHITE
+from load_data_from_file import load_month_data, load_year_data
+from WeatherData import WeatherData
+
+
+def change_text_color(text, style=0, color=37, background_color=40):
+ """This functions returns a string whose color is changed
+
+ Arguments:
+ text: str:
+ Text data whose color you want to change
+ style: int:
+ Changes style, default style "Normal"
+ color: int:
+ Changes text color, default color "White"
+ background_color: int:
+ Changes background color, default "Black"
+
+ Returns:
+ Returns the string with colored text
+ """
+
+ try:
+ style = int(style)
+ color = int(color)
+ background_color = int(background_color)
+ except ValueError:
+ return ""
+ color_string = "\033[" + str(style) + ";" + str(color) + ";"\
+ + str(background_color) + "m" + str(text)
+ return color_string
+
+
+def get_boundary_element(year_data_list, get_maximum=True, key_index=0):
+ """Returns the maximum or minimum element of a 2D-array.
+
+ Arguments:
+ year_data_list: list:
+ Input 2D list whose boundary element is required.
+ get_maximum: Bool:
+ Maximum or minimum value.
+ True for maximum and False for minimum
+ default: True
+ key_index: int:
+ Key of 2nd dimension of array for sorting
+ default: 0
+
+ Returns:
+ value: int:
+ boundary value
+ """
+
+ year_data_list = sorted(year_data_list, reverse=get_maximum,
+ key=lambda x: x[key_index])
+ temperature = year_data_list[0][0]
+ month = get_month_string_from_number(year_data_list[0][2])
+ year = year_data_list[0][1]
+ return temperature, month, year
+
+
+def get_monthly_graph_data(weather_data, path, month, year):
+ """Loads the month data and returns max temperature,
+ min temperature and len to iterate list
+
+ Arguments:
+ weather_data: dict:
+ Object of class WeatherData
+ path: str:
+ Folder consisting of all data files
+ month: int:
+ Representing month range(1-12)
+ year: int:
+ Representing year
+
+ Returns:
+ maximum_temperature_list: list:
+ List that contains maximum temperature of month
+ minimum_temperature_list: list:
+ List that contains minimum temperature of month
+ len_: int:
+ Returns the length of the list
+ """
+
+ load_month_data(weather_data, path, month, year)
+
+ # Getting maximum temperature column
+ max_temp_column = get_column_data_from_alias(weather_data,
+ "max_temperature",
+ month, year)
+
+ # Getting minimum temperature column
+ min_temp_column = get_column_data_from_alias(weather_data,
+ "min_temperature",
+ month, year)
+
+ max_temp_col_len = len(max_temp_column)
+ min_temp_col_len = len(min_temp_column)
+ len_ = max_temp_col_len
+ if max_temp_col_len != min_temp_col_len:
+ if min_temp_col_len < max_temp_col_len:
+ len_ = min_temp_col_len
+ # change color variables
+ print_str = "\033[1;31;40m Note: Unequal data of maximum"
+ print_str += " and minimum temperature"
+ print(print_str)
+ return max_temp_column, min_temp_column, len_
+
+
+def compute_yearly_weather_report(weather_data: WeatherData,
+ path, year: int):
+ """Generate yearly weather report
+
+ Arguments:
+ weather_data: dict:
+ Object of class WeatherData
+ path: str:
+ Folder consisting of all data files
+ year: int:
+ Representing year
+ """
+
+ max_temp_list = []
+ min_temp_list = []
+ max_humidity_list = []
+ min_humidity_list = []
+
+ load_year_data(weather_data, path, year)
+
+ # Checking data of all 12 months
+ for month in range(1, 13):
+ # Max temperature
+ max_temp_column = get_column_data_from_alias(weather_data,
+ "max_temperature",
+ month, year)
+ if max_temp_column:
+ max_temperature_index = max_temp_column.index(max(
+ max_temp_column))
+ max_temp_of_month = max_temp_column[max_temperature_index]
+ day = max_temperature_index + 1
+ max_temp_list.append([max_temp_of_month, day, month])
+
+ # Min temperature
+ min_temp_column = get_column_data_from_alias(weather_data,
+ "min_temperature",
+ month, year)
+ if min_temp_column:
+ min_temperature_index = min_temp_column.index(min(
+ min_temp_column))
+ min_temp_of_month = min_temp_column[min_temperature_index]
+ day = min_temperature_index + 1
+ min_temp_list.append([min_temp_of_month, day, month])
+
+ # Max humidity
+ max_humidity_column = get_column_data_from_alias(weather_data,
+ "max_humidity",
+ month, year)
+ if max_humidity_column:
+ max_humidity_index = max_humidity_column.index(max(
+ max_humidity_column))
+ max_humidity_of_month = max_humidity_column[
+ max_humidity_index]
+ day = max_humidity_index + 1
+ max_humidity_list.append([max_humidity_of_month, day,
+ month])
+
+ # Min humidity
+ min_humidity_column = get_column_data_from_alias(weather_data,
+ "min_humidity",
+ month, year)
+ if min_humidity_column:
+ min_humidity_index = min_humidity_column.index(min(
+ min_humidity_column))
+ min_humidity_of_month = min_humidity_column[
+ min_humidity_index]
+ day = min_humidity_index + 1
+ min_humidity_list.append([min_humidity_of_month, day,
+ month])
+
+ # Checking largest/smallest in each of the lists
+ if len(max_temp_list) > 1:
+ temperature, month, year = get_boundary_element(max_temp_list,
+ get_maximum=True)
+ print("Maximum Temperature:", temperature, "C on", month, year)
+
+ if len(min_temp_list) > 1:
+ temperature, month, year = get_boundary_element(min_temp_list,
+ get_maximum=False)
+ print("Minimum Temperature:", temperature, "C on", month, year)
+
+ if len(max_humidity_list) > 1:
+ humidity, month, year = get_boundary_element(max_humidity_list,
+ get_maximum=True)
+ print("Maximum Humidity:", humidity, "% on", month, year)
+
+ if len(min_humidity_list) > 1:
+ humidity, month, year = get_boundary_element(min_humidity_list,
+ get_maximum=False)
+ print("Minimum Humidity:", humidity, "% on", month, year)
+ return
+
+
+def compute_monthly_weather_report(weather_data: WeatherData,
+ path, month: int,
+ year: int):
+ """Generates monthly weather report
+
+ Arguments:
+ weather_data: dict:
+ Object of class WeatherData
+ path: str:
+ Folder consisting of all data files
+ month: int:
+ Representing month range(1-12)
+ year: int:
+ Representing year
+ """
+
+ load_month_data(weather_data, path, month, year)
+ # Getting maximum temperature column
+ max_temp_column = get_column_data_from_alias(weather_data,
+ "max_temperature",
+ month, year)
+ if max_temp_column:
+ print("Highest Average:", round(sum(max_temp_column)
+ / len(max_temp_column), 2), "C")
+
+ # Getting minimum temperature column
+ min_temp_column = get_column_data_from_alias(weather_data,
+ "min_temperature",
+ month, year)
+ if min_temp_column:
+ print("Lowest Average:", round(sum(min_temp_column)
+ / len(min_temp_column), 2), "C")
+
+ # Getting mean humidity column
+ mean_humidity_column = get_column_data_from_alias(weather_data,
+ "mean_humidity",
+ month, year)
+ if mean_humidity_column:
+ print("Average Mean Humidity:", round(sum(mean_humidity_column)
+ / len(mean_humidity_column),
+ 2), "%")
+ return
+
+
+# Shows a graph of highest and lowest weather of a month
+def compute_monthly_weather_graph_same_line(weather_data: WeatherData,
+ path, month: int,
+ year: int):
+ """Generates monthly weather graph on same line
+
+ Arguments:
+ weather_data: dict:
+ Object of class WeatherData
+ path: str:
+ Folder consisting of all data files
+ month: int:
+ Representing month range(1-12)
+ year: int:
+ Representing year
+ """
+
+ max_temp_column, min_temp_column, len_ = get_monthly_graph_data(
+ weather_data, path, month, year)
+ for i in range(0, len_):
+ print_str = change_text_color(str("%.2d) " % (i + 1)),
+ style=TEXT_STYLE_BOLD,
+ color=TEXT_COLOR_WHITE)
+ print_str += change_text_color("+" * abs(int(min_temp_column[i])),
+ style=TEXT_STYLE_NORMAL,
+ color=TEXT_COLOR_BLUE)
+ print_str += change_text_color("+" * abs(int(max_temp_column[i])),
+ color=TEXT_COLOR_RED)
+ print_str += change_text_color(" " + str(min_temp_column[i]) + "C",
+ color=TEXT_COLOR_BLUE)
+ print_str += change_text_color("-",
+ style=TEXT_STYLE_BOLD,
+ color=TEXT_COLOR_WHITE)
+ print_str += change_text_color(str(max_temp_column[i]) + "C",
+ style=TEXT_STYLE_NORMAL,
+ color=TEXT_COLOR_RED)
+ print(print_str)
+ return
+
+
+def compute_monthly_weather_graph_two_lines(weather_data: WeatherData,
+ path, month: int, year: int):
+ """Generates monthly weather graph on two lines
+
+ Arguments:
+ weather_data: dict:
+ Object of class WeatherData
+ path: str:
+ Folder consisting of all data files
+ month: int:
+ Representing month range(1-12)
+ year: int:
+ Representing year
+ """
+
+ max_temp_column, min_temp_column, len_ = get_monthly_graph_data(
+ weather_data, path, month, year)
+ for i in range(0, len_):
+ print_str = change_text_color(str("%.2d) " % (i + 1)),
+ style=TEXT_STYLE_BOLD,
+ color=TEXT_COLOR_WHITE)
+ print_str += change_text_color(str("+"
+ * abs(int(max_temp_column[i]))),
+ style=TEXT_STYLE_NORMAL,
+ color=TEXT_COLOR_RED)
+ print_str += change_text_color(" "
+ + str(int(max_temp_column[i])) + " C\n",
+ style=TEXT_STYLE_NORMAL,
+ color=TEXT_COLOR_RED)
+ print_str += change_text_color(str("%.2d) " % (i + 1)),
+ style=TEXT_STYLE_BOLD,
+ color=TEXT_COLOR_WHITE)
+ print_str += change_text_color(str("+"
+ * abs(int(min_temp_column[i]))),
+ style=TEXT_STYLE_NORMAL,
+ color=TEXT_COLOR_BLUE)
+ print_str += change_text_color(" "
+ + str(int(min_temp_column[i])) + " C",
+ style=TEXT_STYLE_NORMAL,
+ color=TEXT_COLOR_BLUE)
+ print(print_str)
+ return
diff --git a/load_data_from_file.py b/load_data_from_file.py
new file mode 100644
index 0000000..0c2b0bd
--- /dev/null
+++ b/load_data_from_file.py
@@ -0,0 +1,166 @@
+import os
+import sys
+
+from common import get_month_string_from_number
+
+
+def clean_file_and_structure_data(param_filename, separator):
+ """Cleans the file and return required structure data
+
+ Arguments:
+ param_filename: str:
+ filename that is to be cleaned
+ separator: str:
+ used to differentiate between two columns
+
+ Returns:
+ file_data_cleaned: list:
+ List that contains clean structured data
+ column_names: list:
+ List that contains all column names
+ """
+
+ file_data_cleaned = []
+ column_names = []
+
+ # Load and clean the file data
+ with open(param_filename, "r") as file:
+ file_data = file.readlines()
+ if not file_data:
+ return [], []
+ for line_num in range(0, len(file_data)):
+ # Removing useless characters from line
+ line = file_data[line_num]
+ line = line.replace("\n", '')
+ line = line.replace("\t", '')
+ line = line.replace("\r", '')
+
+ # Checking if line is empty
+ empty_line_flag = True
+ for each_character in line:
+ if each_character not in ["", "\t", " ", "\n", "\r"]:
+ empty_line_flag = False
+ break
+ if empty_line_flag:
+ continue
+
+ line_data = line.split(separator)
+ if line_num == 0:
+ # Creating indexes in dictionary for each column
+ # It will be used in the end
+ for each in line_data:
+ column_names.append(str(each).strip())
+ else:
+ # Changing data from string to integer/float
+ # Starting loop from 1 to skip the date column
+ for list_index in range(1, len(line_data)):
+ # Column that has text values
+ if list_index == 21:
+ continue
+ if line_data[list_index] == "":
+ line_data[list_index] = 0
+ else:
+ try:
+ line_data[list_index] = float(
+ line_data[list_index])
+ except ValueError:
+ print("Invalid data in ", param_filename)
+ sys.exit()
+
+ # Entering clean line data into list
+ file_data_cleaned.append(line_data)
+ return column_names, file_data_cleaned
+
+
+def load_data_from_file(param_filename):
+ """Create a dictionary from file data
+
+ Arguments:
+ param_filename: str:
+ filename that contains data
+ uses '.csv', '.tsv' and '.txt'
+ '.txt' file must have data similar to .csv
+
+ Returns:
+ month_data: dict:
+ Dictionary that contains complete data
+ """
+
+ filename, file_ext = os.path.splitext(param_filename)
+ file_ext = str(file_ext).lower()
+ if file_ext == ".csv" or file_ext == ".txt":
+ separator = ","
+ elif file_ext == ".tsv":
+ separator = "\t"
+ else:
+ print(file_ext + " Invalid input file found")
+ return
+ if not os.path.exists(param_filename):
+ print("Data file not found")
+ sys.exit()
+
+ month_dictionary = {}
+ column_names, file_data_cleaned = clean_file_and_structure_data(
+ param_filename, separator)
+
+ if not column_names:
+ return month_dictionary
+
+ if not file_data_cleaned:
+ return month_dictionary
+
+ for column in column_names:
+ month_dictionary[column] = []
+
+ # Appending clean data in month dictionary
+ for i in range(1, len(file_data_cleaned)):
+ for j in range(0, len(file_data_cleaned[i])):
+ month_dictionary[column_names[j]].append(
+ file_data_cleaned[i][j])
+ return month_dictionary
+
+
+def load_month_data(weather_data, path, month: int, year: int):
+ """Loads passed month data into weather data class
+
+ Arguments:
+ weather_data: WeatherData:
+ object of class WeatherData
+ path: str:
+ path of the dir where all files are located
+ month: int:
+ Represents month. range(1-12)
+ year: int:
+ Represents year
+ """
+
+ if not (0 < month < 13):
+ print("Invalid month")
+ sys.exit()
+ filename_prefix = "Murree_weather_"
+ filename = path + "/" + filename_prefix + str(year) + "_"\
+ + get_month_string_from_number(month)
+ extension_list = [".txt", ".csv", ".tsv", ".xlsx", ".xls"]
+ for extension in extension_list:
+ if os.path.exists(filename + extension):
+ filename += extension
+ month_data = load_data_from_file(filename)
+ weather_data.add_month_data(month, year, month_data)
+ return
+
+
+def load_year_data(weather_data, path, year: int):
+ """Loads passed year data into weather data class
+
+ Arguments:
+ weather_data: WeatherData:
+ object of class WeatherData
+ path: str:
+ path of the dir where all files are located
+ year: int:
+ Represents year
+ """
+
+ for i in range(1, 13):
+ load_month_data(weather_data, path, i, year)
+ return
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..a8e7b5b
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1 @@
+pycodestyle
\ No newline at end of file
diff --git a/weatherfiles.zip b/weatherfiles.zip
new file mode 100644
index 0000000..4f020bd
Binary files /dev/null and b/weatherfiles.zip differ
diff --git a/weatherman.py b/weatherman.py
new file mode 100644
index 0000000..bfde0a4
--- /dev/null
+++ b/weatherman.py
@@ -0,0 +1,81 @@
+import argparse
+import os
+import sys
+
+from common import get_month_year_from_string
+from generate_reports import compute_monthly_weather_report
+from generate_reports import compute_monthly_weather_graph_two_lines
+from generate_reports import compute_monthly_weather_graph_same_line
+from generate_reports import compute_yearly_weather_report
+from WeatherData import WeatherData
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser()
+ parser.add_argument('path', metavar="path", type=str,
+ help="Path to list")
+ parser.add_argument('-e', action='append', type=str,
+ help="""Displays highest temperature,
+ lowest temperature and humidity of a
+ year""")
+ parser.add_argument('-a', action='append', type=str,
+ help="""Displays average highest
+ temperature, average lowest temperature
+ and average humidity of a month""")
+ parser.add_argument('-c', action='append', type=str,
+ help="""Draws highest and lowest
+ temperature of a month in two lines""")
+ parser.add_argument('-b', action='append', type=str,
+ help="""Draws highest and lowest
+ temperature of a month in same line""")
+
+ args = parser.parse_args()
+ os.system("clear")
+ if len(sys.argv) < 3:
+ print("No argument given for reports output")
+ sys.exit()
+ if not os.path.isdir(args.path):
+ raise "Invalid path to dir given"
+
+ weather_data = WeatherData()
+ path = args.path
+ if weather_data is None:
+ raise "Weather Data doesn't exist"
+
+ if args.e is not None:
+ for each in args.e:
+ print("\n====================> Year Report ", each)
+ try:
+ year = int(each)
+ except Exception:
+ raise "Invalid year \"" + str(each) + "\""
+ compute_yearly_weather_report(weather_data, path, year)
+
+ if args.a is not None:
+ for each in args.a:
+ print("\n====================> Month Report ", each)
+ try:
+ year, month = get_month_year_from_string(each)
+ except Exception:
+ raise "Invalid month/year \"" + str(each) + "\""
+ compute_monthly_weather_report(weather_data, path, month,
+ year)
+
+ if args.c is not None:
+ for each in args.c:
+ print("\n====================> Month Graph ", each)
+ try:
+ year, month = get_month_year_from_string(each)
+ except Exception:
+ raise "Invalid month/year \"" + str(each) + "\""
+ compute_monthly_weather_graph_two_lines(weather_data,
+ path, month, year)
+
+ if args.b is not None:
+ for each in args.b:
+ print("\n====================> Month Graph", each)
+ try:
+ year, month = get_month_year_from_string(each)
+ except Exception:
+ raise "Invalid month/year \"" + str(each) + "\""
+ compute_monthly_weather_graph_same_line(weather_data,
+ path, month, year)