From 5701c50a6a29debd6f6baf63cd48c2da08f7d2fb Mon Sep 17 00:00:00 2001 From: Hina Khadim Date: Thu, 15 Sep 2022 18:45:59 +0500 Subject: [PATCH 1/3] feat : Refactored and complete Task1 --- README.md | 1 - file_path_matcher_with_date.py | 10 ++-- main.py | 70 +++++++++++++++++++++------ report_generator.py | 39 +++++++++++++++ report_types.py | 8 ++++ stat.ipynb | 81 -------------------------------- weather_record.py | 5 +- weather_statistics_calculator.py | 54 +++++++++++++++++---- 8 files changed, 154 insertions(+), 114 deletions(-) create mode 100644 report_generator.py create mode 100644 report_types.py delete mode 100644 stat.ipynb diff --git a/README.md b/README.md index 6eb6055..1632ed2 100644 --- a/README.md +++ b/README.md @@ -1,2 +1 @@ ## Weather Task - diff --git a/file_path_matcher_with_date.py b/file_path_matcher_with_date.py index e076755..5455da9 100644 --- a/file_path_matcher_with_date.py +++ b/file_path_matcher_with_date.py @@ -4,11 +4,11 @@ from collections import namedtuple -months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', +Months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] -class FilePathMatcherWithDate: +class FilePathsProviderMatchedWithDate: def __init__(self, data_folder_path) -> None: self.month = None @@ -22,7 +22,7 @@ def setDate(self, date): self.month = splitted_date[1] self.year = splitted_date[0] - def get_files_path(self): + def get_matched_files_path(self): if self.month and self.year: return "" @@ -35,7 +35,7 @@ def get_specific_year_file_paths(self): file_paths_of_a_year = [] for file_name in os.listdir(self.data_folder_path): - file_year = self.get_file_month_year(file_name).year + file_year = self.get_file_month_year_from(file_name).year if self.year == file_year: file_paths_of_a_year.append( @@ -43,7 +43,7 @@ def get_specific_year_file_paths(self): return file_paths_of_a_year - def get_file_month_year(self, filename): + def get_file_month_year_from(self, filename): matched_result = list(re.finditer( r'(?P\d+)_(?P\w+)', filename)) diff --git a/main.py b/main.py index 13dc27d..72d77f5 100644 --- a/main.py +++ b/main.py @@ -1,29 +1,69 @@ import sys import os -from file_path_matcher_with_date import FilePathMatcherWithDate +from report_generator import ReportGenerator +from file_path_matcher_with_date import FilePathsProviderMatchedWithDate +from weather_statistics_calculator import WeatherStatisticsCalculator CURRENT_DIRECTORY = os.getcwd() +MIN_REQUIRED_ARGS = 4 + + +def isNotValidLengthOfARGS(arguments): + return len(arguments) < MIN_REQUIRED_ARGS + + +def isNotValidDirectoryPath(folder_path): + print(folder_path) + return not os.path.isdir(folder_path) + + +def isOdd(args): + return len(args) % 2 != 0 + + +def generate_report(flag, value, data_folder): + match flag: + case '-e': + generateReportHighLowTempHumidity(value, data_folder) + case '-a': + pass + case '-c': + pass + case _: + print("No flag sent") + + +def generateReportHighLowTempHumidity(year, data_folder): + + file_paths_provider = FilePathsProviderMatchedWithDate(data_folder) + file_paths_provider.setDate(year) + matched_file_paths_with_year = file_paths_provider.get_matched_files_path() + + statistics_calculator = WeatherStatisticsCalculator( + matched_file_paths_with_year) + report_data = statistics_calculator.calc_low_and_high_temp_and_humidity() + + generate_report = ReportGenerator() + generate_report.highest_lowest_temp_and_humidity(report_data) + if __name__ == "__main__": - if len(sys.argv) < 4: + if isNotValidLengthOfARGS(sys.argv): print("You must specify files path and the command with proper flag") sys.exit(0) - weather_data_files_path = CURRENT_DIRECTORY + sys.argv[1] - if not os.path.isdir(weather_data_files_path): - print("Invalid path to directory : ", weather_data_files_path) + weather_data_folder_path = CURRENT_DIRECTORY + sys.argv[1] + if isNotValidDirectoryPath(weather_data_folder_path): + print("Invalid path to directory : ", weather_data_folder_path) sys.exit(0) - print(weather_data_files_path) - - system_args = sys.argv[2:] + arg_flags_with_values = sys.argv[2:] - year = sys.argv[3] - - file_path_matcher = FilePathMatcherWithDate(weather_data_files_path) - file_path_matcher.setDate(year) - matched_file_paths_with_year = file_path_matcher.get_files_path() + if isOdd(arg_flags_with_values): + print("All flags must have values") + sys.exit(0) - # for index, argument in enumerate(system_args): - # pass + for i in range(0, len(arg_flags_with_values) // 2, 2): + flag, value = arg_flags_with_values[i], arg_flags_with_values[i + 1] + generate_report(flag, value, weather_data_folder_path) diff --git a/report_generator.py b/report_generator.py new file mode 100644 index 0000000..ce18adb --- /dev/null +++ b/report_generator.py @@ -0,0 +1,39 @@ + + +from typing import Optional +from report_types import HighLowTempHumidityReportType + + +Months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] + + +class ReportGenerator: + + def highest_lowest_temp_and_humidity(self, report_data: + Optional[ + HighLowTempHumidityReportType + ]): + + print("\n================== Report =================") + + if not report_data: + print("There is no data for generating a report") + + highest_temp = report_data.highest_temperature + lowest_temp = report_data.lowest_temperature + high_humid = report_data.high_humidity + + print( + f"Highest Temperature: {highest_temp.max_temp}°C on " + f"{self.format_date_from(highest_temp.date)}") + print( + f"Lowest Temperature: {lowest_temp.max_temp}°C on " + f"{self.format_date_from(lowest_temp.date)}") + print( + f"Highest Humidity: {high_humid.max_humidity}°C on " + f"{self.format_date_from(high_humid.date)}\n") + + def format_date_from(self, date): + year, month, day = date.split("-") + return f"{Months[int(month) - 1]} {day}, {year}" diff --git a/report_types.py b/report_types.py new file mode 100644 index 0000000..c26b055 --- /dev/null +++ b/report_types.py @@ -0,0 +1,8 @@ +from collections import namedtuple + +HighLowTempHumidityReportType = namedtuple( + "HighestLowestTemperatureHumidityReport", [ + 'highest_temperature', + 'lowest_temperature', + 'high_humidity'], + defaults=['', '', '']) diff --git a/stat.ipynb b/stat.ipynb deleted file mode 100644 index 1942c2d..0000000 --- a/stat.ipynb +++ /dev/null @@ -1,81 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import csv\n", - "\n", - "import pandas as pd\n", - "\n", - "# reading csv file\n", - "pd.read_csv(\"weatherfiles/Murree_weather_2004_Aug.txt\")\n", - "# with open(\"weatherfiles/Murree_weather_2004_Aug\")" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'csv' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m/Users/hinakhadim/Documents/Arbisoft/Python/weather_task/stat.ipynb Cell 2\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[39mwith\u001b[39;00m \u001b[39mopen\u001b[39m(\u001b[39m'\u001b[39m\u001b[39mweatherfiles/Murree_weather_2004_Aug.txt\u001b[39m\u001b[39m'\u001b[39m, \u001b[39m'\u001b[39m\u001b[39mr\u001b[39m\u001b[39m'\u001b[39m) \u001b[39mas\u001b[39;00m file:\n\u001b[0;32m----> 3\u001b[0m csv_file \u001b[39m=\u001b[39m csv\u001b[39m.\u001b[39mDictReader()\n\u001b[1;32m 5\u001b[0m \u001b[39mfor\u001b[39;00m row \u001b[39min\u001b[39;00m csv_file:\n\u001b[1;32m 6\u001b[0m \u001b[39mprint\u001b[39m(row)\n", - "\u001b[0;31mNameError\u001b[0m: name 'csv' is not defined" - ] - } - ], - "source": [ - "import csv\n", - "\n", - "with open('weatherfiles/Murree_weather_2004_Aug.txt', 'r') as file:\n", - "\n", - " csv_file = csv.DictReader()\n", - "\n", - " for row in csv_file:\n", - " print(row)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3.10.6 64-bit", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.6" - }, - "orig_nbformat": 4, - "vscode": { - "interpreter": { - "hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49" - } - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/weather_record.py b/weather_record.py index e150b47..12f6faf 100644 --- a/weather_record.py +++ b/weather_record.py @@ -5,10 +5,7 @@ def __init__(self, record_item) -> None: self.date = record_item['PKT'] self.min_temp = record_item['Mean TemperatureC'] self.max_temp = record_item['Max TemperatureC'] - self.avg_temp = record_item['Min Temperature'] + self.avg_temp = record_item['Min TemperatureC'] self.min_humidity = record_item[' Min Humidity'] self.max_humidity = record_item['Max Humidity'] self.avg_humidity = record_item[' Mean Humidity'] - - def __lt__(self, nxt): - return self.avg_temp < nxt.avg_temp diff --git a/weather_statistics_calculator.py b/weather_statistics_calculator.py index 778ede1..18cb0e6 100644 --- a/weather_statistics_calculator.py +++ b/weather_statistics_calculator.py @@ -1,6 +1,7 @@ import csv - +import sys from weather_record import WeatherRecord +from report_types import HighLowTempHumidityReportType class WeatherStatisticsCalculator: @@ -10,19 +11,56 @@ def __init__(self, filepaths) -> None: self.file_records = [] for filepath in filepaths: - self.file_data_reader(filepath) + self.file_data_reader_and_add_to_file_records(filepath) - def file_data_reader(self, filepath): + def file_data_reader_and_add_to_file_records(self, filepath): with open(filepath, 'r') as file: records_list = csv.DictReader(file) for row in records_list: record = WeatherRecord(row) - self.file_records.push(record) + self.file_records.append(record) + + def calc_low_and_high_temp_and_humidity(self): + + if len(self.file_records) == 0: + return None + + highest_temperature = self.get_highest_max_temperature() + lowest_temperature = self.get_lowest_min_temperature() + high_humidity = self.get_highest_max_humidity() + + report = HighLowTempHumidityReportType( + highest_temperature=highest_temperature, + lowest_temperature=lowest_temperature, + high_humidity=high_humidity + ) + + return report + + def get_highest_max_temperature(self): + return sorted(self.file_records, + key=self.max_temperature_sorter, reverse=True)[0] + + def max_temperature_sorter(self, record): + if record.max_temp: + return int(record.max_temp) + return -sys.maxsize + + def get_lowest_min_temperature(self): + return sorted(self.file_records, key=self.min_temperature_sorter)[0] + + def min_temperature_sorter(self, record): + if record.min_temp: + return int(record.min_temp) + return sys.maxsize - def display_low_and_high_temp_and_humidity(self): + def get_highest_max_humidity(self): + return sorted(self.file_records, + key=self.max_humidity_sorter, reverse=True)[0] - low_temp_heap = [] - high_temp_heap = [] - high_humidity_heap = [] + def max_humidity_sorter(self, record): + if record.max_humidity: + return int(record.max_humidity) + return -sys.maxsize From e0f7285c8dc6c14ff6e9291a0c11eb7147d99eb5 Mon Sep 17 00:00:00 2001 From: Hina Khadim Date: Thu, 15 Sep 2022 19:45:33 +0500 Subject: [PATCH 2/3] feat : generate average temperature and humidity report --- file_path_matcher_with_date.py | 19 +++++++++-- main.py | 15 ++++++++- report_generator.py | 31 ++++++++++++++++-- report_types.py | 8 +++++ weather_record.py | 4 +-- weather_statistics_calculator.py | 56 +++++++++++++++++++++++++++----- 6 files changed, 118 insertions(+), 15 deletions(-) diff --git a/file_path_matcher_with_date.py b/file_path_matcher_with_date.py index 5455da9..520707a 100644 --- a/file_path_matcher_with_date.py +++ b/file_path_matcher_with_date.py @@ -19,13 +19,13 @@ def setDate(self, date): splitted_date = date.split("/") # date = yyyy/m if len(splitted_date) > 1: - self.month = splitted_date[1] + self.month = Months[int(splitted_date[1]) - 1] self.year = splitted_date[0] def get_matched_files_path(self): if self.month and self.year: - return "" + return self.get_specific_month_year_file_paths() elif self.year: return self.get_specific_year_file_paths() else: @@ -56,3 +56,18 @@ def get_file_month_year_from(self, filename): return date_object return DateObj() + + def get_specific_month_year_file_paths(self): + file_paths_of_a_month_in_year = [] + + for file_name in os.listdir(self.data_folder_path): + file_date = self.get_file_month_year_from(file_name) + file_month, file_year = file_date.month, file_date.year + + if self.month == file_month and self.year == file_year: + file_paths_of_a_month_in_year.append( + os.path.join(self.data_folder_path, file_name)) + break + # since the given month of the given year has only 1 file + + return file_paths_of_a_month_in_year diff --git a/main.py b/main.py index 72d77f5..3716854 100644 --- a/main.py +++ b/main.py @@ -26,7 +26,7 @@ def generate_report(flag, value, data_folder): case '-e': generateReportHighLowTempHumidity(value, data_folder) case '-a': - pass + generateReportAverageTempHumidity(value, data_folder) case '-c': pass case _: @@ -47,6 +47,19 @@ def generateReportHighLowTempHumidity(year, data_folder): generate_report.highest_lowest_temp_and_humidity(report_data) +def generateReportAverageTempHumidity(date, data_folder): # date = year/month + file_paths_provider = FilePathsProviderMatchedWithDate(data_folder) + file_paths_provider.setDate(date) + matched_file_paths_with_date = file_paths_provider.get_matched_files_path() + + statistics_calculator = WeatherStatisticsCalculator( + matched_file_paths_with_date) + report_data = statistics_calculator.calc_average_temp_and_humidity() + + generate_report = ReportGenerator() + generate_report.average_max_min_temp_and_mean_humidity(report_data) + + if __name__ == "__main__": if isNotValidLengthOfARGS(sys.argv): diff --git a/report_generator.py b/report_generator.py index ce18adb..fda089d 100644 --- a/report_generator.py +++ b/report_generator.py @@ -1,6 +1,7 @@ from typing import Optional +from report_types import AverageTempHumidReportType from report_types import HighLowTempHumidityReportType @@ -16,9 +17,12 @@ def highest_lowest_temp_and_humidity(self, report_data: ]): print("\n================== Report =================") + print("================== Highest and Lowest Temperature and Maximum" + "Humidity =================") if not report_data: - print("There is no data for generating a report") + print("\nThere is no data for generating a report\n") + return highest_temp = report_data.highest_temperature lowest_temp = report_data.lowest_temperature @@ -31,9 +35,32 @@ def highest_lowest_temp_and_humidity(self, report_data: f"Lowest Temperature: {lowest_temp.max_temp}°C on " f"{self.format_date_from(lowest_temp.date)}") print( - f"Highest Humidity: {high_humid.max_humidity}°C on " + f"Highest Humidity: {high_humid.max_humidity}% on " f"{self.format_date_from(high_humid.date)}\n") def format_date_from(self, date): year, month, day = date.split("-") return f"{Months[int(month) - 1]} {day}, {year}" + + def average_max_min_temp_and_mean_humidity(self, report_data: + Optional[ + AverageTempHumidReportType + ]): + print("\n================== Report =================") + print("================== Average Highest and Lowest Temperature and" + "Mean Humidity =================") + + if not report_data: + print("\nThere is no data for generating a report\n") + return + + average_highest_temp = report_data.average_max_temperature + average_low_temp = report_data.average_min_temperature + average_humid = report_data.average_mean_humidity + + print( + f"Highest Average Temperature: {average_highest_temp}°C") + print( + f"Lowest Average Temperature: {average_low_temp}°C") + print( + f"Average Mean Humidity: {average_humid}%\n") diff --git a/report_types.py b/report_types.py index c26b055..27a8e5c 100644 --- a/report_types.py +++ b/report_types.py @@ -6,3 +6,11 @@ 'lowest_temperature', 'high_humidity'], defaults=['', '', '']) + + +AverageTempHumidReportType = namedtuple( + "AverageTempHumidityReportType", [ + 'average_max_temperature', + 'average_min_temperature', + 'average_mean_humidity'], + defaults=['', '', '']) diff --git a/weather_record.py b/weather_record.py index 12f6faf..044a997 100644 --- a/weather_record.py +++ b/weather_record.py @@ -5,7 +5,7 @@ def __init__(self, record_item) -> None: self.date = record_item['PKT'] self.min_temp = record_item['Mean TemperatureC'] self.max_temp = record_item['Max TemperatureC'] - self.avg_temp = record_item['Min TemperatureC'] + self.mean_temp = record_item['Min TemperatureC'] self.min_humidity = record_item[' Min Humidity'] self.max_humidity = record_item['Max Humidity'] - self.avg_humidity = record_item[' Mean Humidity'] + self.mean_humidity = record_item[' Mean Humidity'] diff --git a/weather_statistics_calculator.py b/weather_statistics_calculator.py index 18cb0e6..f6add37 100644 --- a/weather_statistics_calculator.py +++ b/weather_statistics_calculator.py @@ -1,6 +1,7 @@ import csv import sys from weather_record import WeatherRecord +from report_types import AverageTempHumidReportType from report_types import HighLowTempHumidityReportType @@ -14,7 +15,7 @@ def __init__(self, filepaths) -> None: self.file_data_reader_and_add_to_file_records(filepath) def file_data_reader_and_add_to_file_records(self, filepath): - + print(filepath) with open(filepath, 'r') as file: records_list = csv.DictReader(file) @@ -27,14 +28,10 @@ def calc_low_and_high_temp_and_humidity(self): if len(self.file_records) == 0: return None - highest_temperature = self.get_highest_max_temperature() - lowest_temperature = self.get_lowest_min_temperature() - high_humidity = self.get_highest_max_humidity() - report = HighLowTempHumidityReportType( - highest_temperature=highest_temperature, - lowest_temperature=lowest_temperature, - high_humidity=high_humidity + highest_temperature=self.get_highest_max_temperature(), + lowest_temperature=self.get_lowest_min_temperature, + high_humidity=self.get_highest_max_humidity() ) return report @@ -64,3 +61,46 @@ def max_humidity_sorter(self, record): if record.max_humidity: return int(record.max_humidity) return -sys.maxsize + + def calc_average_temp_and_humidity(self): + if len(self.file_records) == 0: + return None + + report = AverageTempHumidReportType( + average_max_temperature=self.get_average_max_temperature(), + average_min_temperature=self.get_average_min_temperature(), + average_mean_humidity=self.get_average_mean_humidity() + ) + + return report + + def get_average_max_temperature(self): + total_sum_of_max_temp = 0 + for record in self.file_records: + + if record.max_temp: + total_sum_of_max_temp += int(record.max_temp) + # else : assume max_temp to zero + + return total_sum_of_max_temp / len(self.file_records) + + def get_average_min_temperature(self): + total_sum_of_min_temp = 0 + for record in self.file_records: + + if record.min_temp: + total_sum_of_min_temp += int(record.min_temp) + # else : assume max_temp to zero + + return total_sum_of_min_temp / len(self.file_records) + + def get_average_mean_humidity(self): + total_sum_of_mean_humid = 0 + + for record in self.file_records: + + if record.mean_humidity: + total_sum_of_mean_humid += int(record.mean_humidity) + # else : assume max_temp to zero + + return total_sum_of_mean_humid / len(self.file_records) From 14f6530036b1348da70d70c63e3253c32b24b402 Mon Sep 17 00:00:00 2001 From: Hina Khadim Date: Thu, 15 Sep 2022 20:06:17 +0500 Subject: [PATCH 3/3] refactor : Refactor main.py --- main.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/main.py b/main.py index 3716854..fbd28a4 100644 --- a/main.py +++ b/main.py @@ -33,14 +33,20 @@ def generate_report(flag, value, data_folder): print("No flag sent") -def generateReportHighLowTempHumidity(year, data_folder): +def get_statistics_calculator_instance(date, data_folder): file_paths_provider = FilePathsProviderMatchedWithDate(data_folder) - file_paths_provider.setDate(year) + file_paths_provider.setDate(date) matched_file_paths_with_year = file_paths_provider.get_matched_files_path() statistics_calculator = WeatherStatisticsCalculator( matched_file_paths_with_year) + return statistics_calculator + + +def generateReportHighLowTempHumidity(year, data_folder): + + statistics_calculator = get_statistics_calculator_instance() report_data = statistics_calculator.calc_low_and_high_temp_and_humidity() generate_report = ReportGenerator() @@ -52,8 +58,7 @@ def generateReportAverageTempHumidity(date, data_folder): # date = year/month file_paths_provider.setDate(date) matched_file_paths_with_date = file_paths_provider.get_matched_files_path() - statistics_calculator = WeatherStatisticsCalculator( - matched_file_paths_with_date) + statistics_calculator = get_statistics_calculator_instance report_data = statistics_calculator.calc_average_temp_and_humidity() generate_report = ReportGenerator()