diff --git a/FEEDBACK.md b/FEEDBACK.md index 010fecd..bbe32eb 100644 --- a/FEEDBACK.md +++ b/FEEDBACK.md @@ -1,13 +1,16 @@ # Feedback -1. Your team: -2. Name of each individual participating: -3. How many unit tests were you able to pass? +1. Your team: GCU_CS +2. Name of each individual participating: Kyungchan Im and Gabriel Teixeira Lima Aracena +3. How many unit tests were you able to pass? 13 4. Document and describe any enhancements included to help the judges properly grade your submission. - - Example One - - Example Two - - Example Three + - We created a new function in the simple_data_tool.py file to map the regional disaster type. We saw the definitions of the region on top of the page that were not being utilized to we thought it would be a good idea to use it for something. + - We created a new function in the simple_data_tool.py file to map the regional total claim. We wanted to do further data analysis project for this competition, so we added extra function that we needed to calculate. + - We then created a jupyter notabook that enables the visualization of that data and implements some data analysis to our dataset. We initially thought about creating a neural network and implementing a deep learning program but the dataset is too small for that. + - We implemented a REST API in the application.py file that can be used to interact and access the data. We used it locally but one could use Postman to interact with it (that's what's more common in the industry) + 5. Any feedback for the coding competition? Things you would like to see in future events? +We had a lot of fun completing it! I just think the project itself would be more descriptive, it took us the first hour just to understand what we were supposed to accomplish. This form can also be emailed to [codingcompetition@statefarm.com](mailto:codingcompetition@statefarm.com). Just make sure that you include a link to your GitHub pull requests. diff --git a/python/application.py b/python/application.py index 50cb38a..544ad3b 100644 --- a/python/application.py +++ b/python/application.py @@ -1 +1,148 @@ -print("I'm working") \ No newline at end of file +# This is the implementation of our simple API to interact with the JSON data files +# We enabled GET for every JSON. 1 to access all the data e.g: '/claims' (this can be used when displaying a list) +# and another one to see one sepcific data e.g: 'claim/claim_id' (this can be used when searching for a data and looking for details) +# We also created PUT and POST for disasters and claims, we thought it would make sense to enable the creation and update of those +# One could use '/disasters' as a POST to create a new disaster and '/disaster/disaster_id' as a PUT to update an existing one + +from flask import Flask, jsonify, request +import json + +app = Flask(__name__) + +# File paths +AGENTS_FILEPATH = 'data/sfcc_2023_agents.json' +CLAIM_HANDLERS_FILEPATH = 'data/sfcc_2023_claim_handlers.json' +CLAIMS_FILEPATH = 'data/sfcc_2023_claims.json' +DISASTERS_FILEPATH = 'data/sfcc_2023_disasters.json' + +# Utility function to load data from a given filepath +def load_data(filepath): + with open(filepath, 'r') as file: + return json.load(file) + +# Utility function to save data to a given filepath +def save_data(filepath, data): + with open(filepath, 'w') as file: + json.dump(data, file) + +@app.route('/claims', methods=['GET']) +def get_claims(): + return jsonify(load_data(CLAIMS_FILEPATH)) + +@app.route('/claim/', methods=['GET']) +def get_claim_by_id(claim_id): + claims = load_data(CLAIMS_FILEPATH) + claim = next((claim for claim in claims if claim["id"] == claim_id), None) + + if claim: + return jsonify(claim) + else: + return jsonify({"error": f"No claim found with ID {claim_id}"}), 404 + +@app.route('/claims', methods=['POST']) +def add_claim(): + claims = load_data(CLAIMS_FILEPATH) + new_claim = request.json + claims.append(new_claim) + save_data(CLAIMS_FILEPATH, claims) + return jsonify({"message": "New claim added successfully!"}) + +@app.route('/claims/', methods=['PUT']) +def update_claim(claim_id): + claims = load_data(CLAIMS_FILEPATH) + claim_to_update = next((claim for claim in claims if claim["id"] == claim_id), None) + + if claim_to_update: + updated_data = request.json + for key, value in updated_data.items(): + claim_to_update[key] = value + save_data(CLAIMS_FILEPATH, claims) + return jsonify({"message": f"Claim with ID {claim_id} updated successfully!"}) + else: + return jsonify({"error": f"No claim found with ID {claim_id}"}), 404 + +@app.route('/claim_handlers', methods=['GET']) +def get_claim_handlers(): + return jsonify(load_data(CLAIM_HANDLERS_FILEPATH)) + +@app.route('/claim_handler/', methods=['GET']) +def get_claim_handler_by_id(handler_id): + claim_handlers = load_data(CLAIM_HANDLERS_FILEPATH) + handler = next((handler for handler in claim_handlers if handler["id"] == handler_id), None) + + if handler: + return jsonify(handler) + else: + return jsonify({"error": f"No claim handler found with ID {handler_id}"}), 404 + +@app.route('/agents', methods=['GET']) +def get_agents(): + return jsonify(load_data(AGENTS_FILEPATH)) + +@app.route('/agent/', methods=['GET']) +def get_agent_by_id(agent_id): + agents = load_data(AGENTS_FILEPATH) + agent = next((agent for agent in agents if agent["id"] == agent_id), None) + + if agent: + return jsonify(agent) + else: + return jsonify({"error": f"No agent found with ID {agent_id}"}), 404 + +@app.route('/disasters', methods=['GET']) +def get_disasters(): + return jsonify(load_data(DISASTERS_FILEPATH)) + +@app.route('/disaster/', methods=['GET']) +def get_disaster_by_id(disaster_id): + # Load existing disasters + disasters = load_data(DISASTERS_FILEPATH) + + # Find the disaster with the specified ID + disaster = next((disaster for disaster in disasters if disaster["id"] == disaster_id), None) + + if disaster: + return jsonify(disaster) + else: + return jsonify({"error": f"No disaster found with ID {disaster_id}"}), 404 + +@app.route('/disasters', methods=['POST']) +def add_disaster(): + # Load existing disasters + disasters = load_data(DISASTERS_FILEPATH) + + # Retrieve the new disaster data from the request + new_disaster = request.json + + # Add the new disaster to the existing list + disasters.append(new_disaster) + + # Save the updated disasters list back to the file + save_data(DISASTERS_FILEPATH, disasters) + + return jsonify({"message": "New disaster added successfully!"}) + +@app.route('/disasters/', methods=['PUT']) +def update_disaster(disaster_id): + # Load existing disasters + disasters = load_data(DISASTERS_FILEPATH) + + # Find the disaster to update + disaster_to_update = next((disaster for disaster in disasters if disaster["id"] == disaster_id), None) + + if disaster_to_update: + # Update the found disaster with data from the request + updated_data = request.json + for key, value in updated_data.items(): + disaster_to_update[key] = value + + # Save the updated disasters list back to the file + save_data(DISASTERS_FILEPATH, disasters) + + return jsonify({"message": f"Disaster with ID {disaster_id} updated successfully!"}) + else: + return jsonify({"error": f"No disaster found with ID {disaster_id}"}), 404 + + +if __name__ == '__main__': + app.run(debug=True) diff --git a/round 1/sfcc_2023_agents.json b/python/data/sfcc_2023_agents.json similarity index 100% rename from round 1/sfcc_2023_agents.json rename to python/data/sfcc_2023_agents.json diff --git a/round 1/sfcc_2023_claim_handlers.json b/python/data/sfcc_2023_claim_handlers.json similarity index 100% rename from round 1/sfcc_2023_claim_handlers.json rename to python/data/sfcc_2023_claim_handlers.json diff --git a/round 1/sfcc_2023_claims.json b/python/data/sfcc_2023_claims.json similarity index 100% rename from round 1/sfcc_2023_claims.json rename to python/data/sfcc_2023_claims.json diff --git a/round 1/sfcc_2023_disasters.json b/python/data/sfcc_2023_disasters.json similarity index 100% rename from round 1/sfcc_2023_disasters.json rename to python/data/sfcc_2023_disasters.json diff --git a/python/data_analysis.ipynb b/python/data_analysis.ipynb new file mode 100644 index 0000000..5900e95 --- /dev/null +++ b/python/data_analysis.ipynb @@ -0,0 +1,921 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Data Anaysis Section\n", + "---\n", + "This section is for \"Nice to Have\" purpose for 2023-StateFarm-CodingCompetition.
\n", + "The purpose of this documentation is to find insight from given dataset and scrutinize it." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Preparation" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [], + "source": [ + "## Import libraries\n", + "from simple_data_tool import SimpleDataTool\n", + "\n", + "# For Data Analysis\n", + "import pandas as pd\n", + "import numpy as np\n", + "\n", + "# For Visualization\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Data Load\n", + "Import JSON dataset into DataFrame in order to work with Python Packages" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [], + "source": [ + "# Load Agent JSON data\n", + "agents = pd.read_json(\"data/sfcc_2023_agents.json\")\n", + "agents.set_index('id', inplace=True) # Set the 'id' column as the index\n", + "df_agents = pd.json_normalize(agents.to_dict(orient='records')) # Normalize the columns\n", + "\n", + "# Load Claim JSON data\n", + "claims = pd.read_json(\"data/sfcc_2023_claims.json\")\n", + "claims.set_index('id', inplace=True) # Set the 'id' column as the index\n", + "df_claims = pd.json_normalize(claims.to_dict(orient='records')) # Normalize the columns\n", + "\n", + "# Load Claim Handler JSON data\n", + "claim_handlers = pd.read_json(\"data/sfcc_2023_claim_handlers.json\")\n", + "claim_handlers.set_index('id', inplace=True) # Set the 'id' column as the index\n", + "df_claim_handlers = pd.json_normalize(claim_handlers.to_dict(orient='records')) # Normalize the columns\n", + "\n", + "# Load Disaster JSON data\n", + "disasters = pd.read_json(\"data/sfcc_2023_disasters.json\")\n", + "disasters.set_index('id', inplace=True) # Set the 'id' column as the index\n", + "df_disasters = pd.json_normalize(disasters.to_dict(orient='records')) # Normalize the columns" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Check the info for each individual dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "first_name 100\n", + "last_name 100\n", + "state 100\n", + "region 100\n", + "primary_language 100\n", + "secondary_language 59\n", + "years_active 100\n", + "dtype: int64" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "agents.count() # count the number of each columns and missing values." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
first_namelast_namestateregionprimary_languagesecondary_languageyears_active
id
1CathaAbrahmerMinnesotaMidwestEnglishGerman10
2YettaEasonOregonWestEnglishKorean12
3JanetaD'AvauxConnecticutNortheastEnglishNone47
4KalieTomkinsVirginiaSouthEnglishNone33
5TeddyDennittsIllinoisMidwestEnglishChinese48
\n", + "
" + ], + "text/plain": [ + " first_name last_name state region primary_language \\\n", + "id \n", + "1 Catha Abrahmer Minnesota Midwest English \n", + "2 Yetta Eason Oregon West English \n", + "3 Janeta D'Avaux Connecticut Northeast English \n", + "4 Kalie Tomkins Virginia South English \n", + "5 Teddy Dennitts Illinois Midwest English \n", + "\n", + " secondary_language years_active \n", + "id \n", + "1 German 10 \n", + "2 Korean 12 \n", + "3 None 47 \n", + "4 None 33 \n", + "5 Chinese 48 " + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "agents.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "disaster_id 1000\n", + "status 1000\n", + "total_loss 1000\n", + "loss_of_life 1000\n", + "type 1000\n", + "severity_rating 1000\n", + "estimate_cost 1000\n", + "agent_assigned_id 1000\n", + "claim_handler_assigned_id 1000\n", + "dtype: int64" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "claims.count() # count the number of each columns and missing values." + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
disaster_idstatustotal_lossloss_of_lifetypeseverity_ratingestimate_costagent_assigned_idclaim_handler_assigned_id
id
115ReceivedFalseFalseAuto43580.029750
224In ReviewFalseFalseAuto61741.323692
331ReceivedTrueFalseAuto415224.3094133
414ReceivedFalseTrueAuto86542.469239
530ClosedFalseFalseAuto1979.8186103
\n", + "
" + ], + "text/plain": [ + " disaster_id status total_loss loss_of_life type severity_rating \\\n", + "id \n", + "1 15 Received False False Auto 4 \n", + "2 24 In Review False False Auto 6 \n", + "3 31 Received True False Auto 4 \n", + "4 14 Received False True Auto 8 \n", + "5 30 Closed False False Auto 1 \n", + "\n", + " estimate_cost agent_assigned_id claim_handler_assigned_id \n", + "id \n", + "1 3580.02 97 50 \n", + "2 1741.32 36 92 \n", + "3 15224.30 94 133 \n", + "4 6542.46 92 39 \n", + "5 979.81 86 103 " + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "claims.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "first_name 156\n", + "last_name 156\n", + "dtype: int64" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "claim_handlers.count() # count the number of each columns and missing values." + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
first_namelast_name
id
1BarnabeClynman
2ValdemarSize
3EditheBleakley
4SonjaDiamant
5ElseySreenan
\n", + "
" + ], + "text/plain": [ + " first_name last_name\n", + "id \n", + "1 Barnabe Clynman\n", + "2 Valdemar Size\n", + "3 Edithe Bleakley\n", + "4 Sonja Diamant\n", + "5 Elsey Sreenan" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "claim_handlers.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "type 100\n", + "state 100\n", + "name 100\n", + "description 100\n", + "start_date 100\n", + "end_date 100\n", + "declared_date 100\n", + "lat 100\n", + "long 100\n", + "radius_miles 100\n", + "dtype: int64" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "disasters.count() # count the number of each columns and missing values." + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
typestatenamedescriptionstart_dateend_datedeclared_datelatlongradius_miles
id
1FloodAlaskaAlaska FloodFusce consequat. Nulla nisl. Nunc nisl.\\n\\nDui...2023-06-132023-06-202023-06-1758.3271-134.4742168
2WildfireTexasTexas WildfireDuis consequat dui nec nisi volutpat eleifend....2023-04-112023-04-192023-04-1233.5693-101.8904235
3TornadoVirginiaVirginia TornadoNullam sit amet turpis elementum ligula vehicu...2023-04-292023-05-072023-05-0638.9776-77.3860273
4EarthquakeConnecticutConnecticut EarthquakeFusce consequat. Nulla nisl. Nunc nisl.2023-04-242023-05-092023-04-2841.3657-72.9275120
5Winter StormMissouriMissouri Winter StormSuspendisse potenti. In eleifend quam a odio. ...2023-03-112023-03-212023-03-1439.0663-94.5674155
\n", + "
" + ], + "text/plain": [ + " type state name \\\n", + "id \n", + "1 Flood Alaska Alaska Flood \n", + "2 Wildfire Texas Texas Wildfire \n", + "3 Tornado Virginia Virginia Tornado \n", + "4 Earthquake Connecticut Connecticut Earthquake \n", + "5 Winter Storm Missouri Missouri Winter Storm \n", + "\n", + " description start_date end_date \\\n", + "id \n", + "1 Fusce consequat. Nulla nisl. Nunc nisl.\\n\\nDui... 2023-06-13 2023-06-20 \n", + "2 Duis consequat dui nec nisi volutpat eleifend.... 2023-04-11 2023-04-19 \n", + "3 Nullam sit amet turpis elementum ligula vehicu... 2023-04-29 2023-05-07 \n", + "4 Fusce consequat. Nulla nisl. Nunc nisl. 2023-04-24 2023-05-09 \n", + "5 Suspendisse potenti. In eleifend quam a odio. ... 2023-03-11 2023-03-21 \n", + "\n", + " declared_date lat long radius_miles \n", + "id \n", + "1 2023-06-17 58.3271 -134.4742 168 \n", + "2 2023-04-12 33.5693 -101.8904 235 \n", + "3 2023-05-06 38.9776 -77.3860 273 \n", + "4 2023-04-28 41.3657 -72.9275 120 \n", + "5 2023-03-14 39.0663 -94.5674 155 " + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "disasters.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Find some insight from the dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [], + "source": [ + "# Create a SimpleDataTool object for use calculation functions inside the class\n", + "data = SimpleDataTool()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Find Regional Disaster Counts #####" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [], + "source": [ + "# Get the total number of disaster occurrend in the simulation\n", + "regional_disaster_map = data.get_regional_disaster_map()" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Count\n", + "Region \n", + "south 36\n", + "midwest 25\n", + "northeast 20\n", + "west 19\n" + ] + } + ], + "source": [ + "# Initialize lists to store the data\n", + "disaster_regions = []\n", + "disaster_types = []\n", + "disaster_counts = []\n", + "\n", + "# Populate the lists with data\n", + "for region, disasters in regional_disaster_map.items():\n", + " for disaster_type, count in disasters.items():\n", + " disaster_regions.append(region)\n", + " disaster_types.append(disaster_type)\n", + " disaster_counts.append(count)\n", + "\n", + "# Create a DataFrame\n", + "disaster_map = pd.DataFrame({\n", + " 'Region': disaster_regions,\n", + " 'Disaster Type': disaster_types,\n", + " 'Count': disaster_counts\n", + "})\n", + "\n", + "# Print the sum of the disaster regionally.\n", + "print(disaster_map.groupby(['Region']).sum().sort_values(by='Count', ascending=False))" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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P/9UtWrV5OXlpX379pmnff3116pfv76efPLJfMv556n5L730kpycnMzvH3nkEUnSL7/8Uuh1uap48eI3fHrA1W+eV65ced072zs6Oprry8vL07lz55STk6MmTZpYrLOXl5cuXbqk77//vsB1fv/997pw4YKeffZZ/fHHH+aXo6OjHnzwwWtehvD6668XaBn9+vWzeP/GG29I+v/Pv6enpzp16qQvvvjCfJlJbm6uli1bps6dO9/UPQiOHDmiMmXKqEyZMqpZs6beffddPfHEExan7H/zzTfKy8tT9+7dLdbV29tb1atXN6/rnj179Oeff6pPnz4W93V4/vnnVaJEiRvWkZycrLi4OIWFhalkyZLm9nr16umxxx4zr/PfvfbaaxbvH3nkEf3555/m/58AAGDvuDQAwF3Nw8NDkm768XEnT56Ug4ODqlWrZtHu7e0tLy+vQh+0S1KlSpUs3l89gDl//nyhxjt58qTKly+fL+S4enr5rdTq5uam1q1b37DPlStXNHnyZC1evFi//vqr+YBRklJTU80/nzhxQk899dRNLdfa2+jv0tPTVbZs2etOf/rpp7Vo0SL17t1bI0aMUKtWrdSlSxd17dpVDg7/n3svWbJE06dP15EjR5SdnW1u9/f3N//ct29fffnll2rbtq0qVKigxx9/XN27d1ebNm3+tc5jx45J+uveBtdy9TN9VZEiRf711Ph/ql69usX7qlWrysHBweL+Di+++KKWLVumbdu26dFHH9XGjRv1+++/q0ePHje1DD8/Py1cuFB5eXk6ceKEJk6cqLNnz1rcyO/YsWMyDCNfPVddvfP/1c/yP/fLIkWK/OsTF67OGxAQkG9aYGCg1q9fn+8Gizf6HP5z+wMAYI8IAgDc1Tw8PFS+fHkdOHCgQPP985vqgsjNzb1m+/Xukv73A+h7yRtvvKHFixcrPDxczZo1k6enp0wmk5555plCPyv+dm2j//3vf0pNTc13IPl3rq6u2rp1q6Kjo7VmzRqtW7dOy5YtU8uWLbVhwwY5Ojrqs88+U1hYmDp37qyhQ4eqbNmycnR01OTJk3XixAnzWGXLllVcXJzWr1+vtWvXau3atVq8eLFefPFFLVmy5Ia1Xt12n376qby9vfNN/+eTDpydnS2CisK41uc9NDRU5cqV02effaZHH31Un332mby9vf81ILrqn2FSixYt1KhRI40aNUqzZ8+W9Ne6mkwmrV279pq/++LFixdyjW7N/bavAgBgbQQBAO56HTp00IcffqgdO3aoWbNmN+xbuXJl5eXl6dixYxY31Pv999914cIFVa5c2dxWokQJXbhwwWL+rKwsJScnF7rWggQQlStX1saNG3Xx4kWLswKOHDlinn47LV++XD179tT06dPNbRkZGfm2SdWqVQscxFjbp59+Kkn/erd7BwcHtWrVSq1atdKMGTM0adIkvfXWW4qOjlbr1q21fPlyValSRd98843F72rs2LH5xnJyclLHjh3VsWNH5eXlqW/fvvrggw80evRoVatW7bq/66pVq0r6K0y42YPugjp27JjFGQzHjx9XXl6exbfrjo6Oeu655xQVFaUpU6ZoxYoV6tOnT6Ef+1evXj298MIL+uCDDzRkyBBVqlRJVatWlWEY8vf3V40aNa4779XP8vHjxxUSEmJuz8nJUVJSkurVq/ev8yYkJOSbduTIEZUuXfqueNwiAAD3Eu4RAOCuN2zYMLm5ual37976/fff800/ceKE+bFu7dq1k/TXHfz/bsaMGZKk9u3bm9uqVq2qrVu3WvT78MMPr3tGwM1wc3PLdyB9Pe3atVNubq7ef/99i/b33ntPJpNJbdu2LXQdN8PR0THfN6Rz5szJt/5PPfWU4uPjr/nEhTvxDevmzZs1fvx4+fv73/DReufOncvXdvUpAFcfHXn1IPjvde/atUs7duywmO/PP/+0eO/g4GA+WL061tWDz3/+vkNDQ+Xh4aFJkyZZXHpw1d8fOVlYc+fOtXg/Z84cScr3menRo4fOnz+vV199Venp6XrhhRduabnDhg1Tdna2eX/q0qWLHB0dFRkZme+zYBiGeTs2adJEpUqV0sKFC5WTk2Pus3Tp0n+9bMTHx0cNGjTQkiVLLLb1gQMHtGHDBvM+DwAAbh5nBAC461WtWlWff/65nn76aQUGBurFF19UnTp1lJWVpR9++EFfffWVwsLCJEn169dXz5499eGHH+rChQsKCgrSjz/+qCVLlqhz584W30b27t1br732mp566ik99thjio+P1/r16y0eh1dQjRs31vz58zVhwgRVq1ZNZcuWve614h07dlRISIjeeustJSUlqX79+tqwYYNWrlyp8PBw8zfLhZGamqrPPvvsmtOuHgx26NBBn376qTw9PVWrVi3t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evfurV9++UU9evTQ/v371aRJE82ZM+e6tVy9v8CaNWsUFxdnfh06dMjiPgGS5ObmVuh1btiwoerXr69PPvlEe/fu1cGDB833KLgZV+tcuHChRZ0HDhzQzp07C13X7cQZAQAAAAAAbd68Wfv379egQYOu28fDw0NPP/20nn76aXXt2lVt2rTRuXPntHfvXuXl5Wn69OlycPjr++Yvv/wy3/y+vr567bXX9Nprr2nkyJFauHCh3njjDTk5OUmScnNzzX1r1aolZ2dnnTp1yuIygNuhd+/emjlzpn799Ve1bt0631METp06pTNnzqh8+fKSpJ07d8rBwUEBAQEqV66cypcvr19++UXPP//8ba3TWggCAAAACmDUqFFWG2vSpElWGwsACiIzM1O//fabcnNz9fvvv2vdunWaPHmyOnTooBdffPGa88yYMUM+Pj5q2LChHBwc9NVXX8nb21teXl6qVq2asrOzNWfOHHXs2FGxsbFasGCBxfzh4eFq27atatSoofPnzys6OlqBgYGSpMqVK8tkMmn16tVq166dXF1d5e7uriFDhmjQoEHKy8vTww8/rNTUVMXGxsrDw8Oq194/99xzGjJkiBYuXKhPPvkk33QXFxf17NlT06ZNU1pamgYMGKDu3bvL29tbkhQZGakBAwbI09NTbdq0UWZmpvbs2aPz589r8ODBVqvTWrg0AAAAAADszLp16+Tj4yM/Pz+1adNG0dHRmj17tlauXClHR8drzuPu7q6pU6eqSZMmatq0qZKSkvTdd9/JwcFB9evX14wZMzRlyhTVqVNHS5cutXi0oPTXt/39+vVTYGCg2rRpoxo1aphvJFihQgVFRkZqxIgRKleunPr37y9JGj9+vEaPHq3Jkyeb51uzZs11L18oLE9PTz311FMqXry4OnfunG96tWrV1KVLF7Vr106PP/646tWrZ/F4wN69e2vRokVavHix6tatq6CgIEVFRVm9TmsxGYZh2LqIwkpLS5Onp6dSU1Pl4eFh63IAAIAd4IwA4O50rx4bZGRkKDExUf7+/nJxcbF1OXatVatWql27tmbPnm3RHhERoRUrViguLs42hRXAzX6euDQAAAAAAGC3zp8/r5iYGMXExFh8y38/IwgAAAAAANithg0b6vz585oyZYoCAgJsXc4dQRAAAAAAALBbSUlJN5weERGhiIiIO1LLncLN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mx/ctQYMGKB169Zp2rRpOnbsmN5//32Lu6VfFRwcrKVLl5r3kZIlSyowMFDLli2zCAKef/55lS5dWp06ddK2bduUmJiomJgYDRgwQP/73/+UmJiokSNHaseOHTp58qQ2bNigY8eOKTAwUNJf+05iYqLi4uL0xx9/KDMz885sCNz3du3apUmTJmnPnj06deqUvvnmG509e1aBgYEaOnSopkyZomXLlikhIUEjRoxQXFycBg4cKEmqVq2afH19FRERoWPHjmnNmjWaPn26xfh+fn5KT0/Xpk2b9Mcff3C5GGymdevWqlu3rp5//nnt27dPP/74o1588UUFBQWpSZMmN5y3sP9+GTNmjD755BNFRkbq4MGDOnz4sP7zn//o7bfflvTXPpSdna05c+bol19+0aeffqoFCxZYjBEeHq7169crMTFR+/btU3R0tPlvQ+XKlWUymbR69WqdPXvW4mkDAHAjBAEwCwoKUm5urjkIKFmypGrVqiVvb2/zgXy9evW0ZcsWHT16VI888ogaNmyoMWPGqHz58pL++ob0m2++UcuWLRUYGKgFCxboiy++UO3atSVJQ4YMkaOjo2rVqqUyZcro1KlTNllX4N889NBDWrhwoWbNmqX69etrw4YN5n+4/d0/9xvpr3Dgn23FihXT1q1bValSJfM9OHr16qWMjAx5eHioWLFiOnLkiJ566inVqFFDr7zyivr166dXX31VkvTUU0+pTZs2CgkJUZkyZfTFF1/c7k0AO+Hh4aGtW7eqXbt2qlGjht5++21Nnz5dbdu21YABAzR48GC9+eabqlu3rtatW6dVq1aZL3kpWrSovvjiCx05ckT16tXTlClTNGHCBIvxmzdvrtdee01PP/20ypQpo6lTp9piNQGZTCatXLlSJUqU0KOPPqrWrVurSpUqWrZs2b/OW9h/v4SGhmr16tXasGGDmjZtqoceekjvvfeeKleuLOmve3TMmDFDU6ZMUZ06dbR06VJNnjzZYozc3Fz169dPgYGBatOmjWrUqKF58+ZJkipUqKDIyEiNGDFC5cqVM38xAwD/xmT8/cI+AAAAAABwX+OMAAAAAAAA7AhBAAAAAAAAdoQgAAAAAAAAO0IQAAAAAACAHSEIAAAAAADAjhAEAAAAAABgRwgCAAAAAACwIwQBAAAAAADYEYIAAMB9JSoqSl5eXrYuAwAA4K5FEAAAuGPCwsJkMplkMplUtGhR+fv7a9iwYcrIyLDaMp5++mkdPXrUauMBAADcb4rYugAAgH1p06aNFi9erOzsbO3du1c9e/aUyWTSlClTrDK+q6urXF1drTIWAADA/YgzAgAAd5Szs7O8vb3l6+urzp07q3Xr1vr+++8lSXl5eZo8ebL8/f3l6uqq+vXra/ny5Rbzr1q1StWrV5eLi4tCQkK0ZMkSmUwmXbhwQdK1Lw2YP3++qlatKicnJwUEBOjTTz+1mG4ymbRo0SI9+eSTKlasmKpXr65Vq1bdtm0AAABgSwQBAACbOXDggH744Qc5OTlJkiZPnqxPPvlECxYs0MGDBzVo0CC98MIL2rJliyQpMTFRXbt2VefOnRUfH69XX31Vb7311g2X8e2332rgwIF68803deDAAb366qt66aWXFB0dbdEvMjJS3bt3188//6x27drp+eef17lz527PigMAANiQyTAMw9ZFAADsQ1hYmD777DO5uLgoJydHmZmZcnBw0JdffqkOHTqoZMmS2rhxo5o1a2aep3fv3rp8+bI+//xzjRgxQmvWrNH+/fvN099++21NnDhR58+fl5eXl6KiohQeHm4+Q6BFixaqXbu2PvzwQ/M83bt316VLl7RmzRpJf50R8Pbbb2v8+PGSpEuXLql48eJau3at2rRpcwe2DAAAwJ3DPQIAAHdUSEiI5s+fr0uXLum9995TkSJF9NRTT+ngwYO6fPmyHnvsMYv+WVlZatiwoSQpISFBTZs2tZj+wAMP3HB5hw8f1iuvvGLR1qJFC82aNcuirV69euaf3dzc5OHhoZSUlAKvHwAAwN2OIAAAcEe5ubmpWrVqkqSPP/5Y9evX10cffaQ6depIktasWaMKFSpYzOPs7Hzb6ypatKjFe5PJpLy8vNu+XAAAgDuNIAAAYDMODg4aNWqUBg8erKNHj8rZ2VmnTp1SUFDQNfsHBATou+++s2jbvXv3DZcRGBio2NhY9ezZ09wWGxurWrVq3foKAAAA3IMIAgAANtWtWzcNHTpUH3zwgYYMGaJBgwYpLy9PDz/8sFJTUxUbGysPDw/17NlTr776qmbMmKHhw4erV69eiouLU1RUlKS/vsG/lqFDh6p79+5q2LChWrdurf/+97/65ptvtHHjxju4lgAAAHcPggAAgE0VKVJE/fv319SpU5WYmKgyZcpo8uTJ+uWXX+Tl5aVGjRpp1KhRkiR/f38tX75cb775pmbNmqVmzZrprbfe0uuvv37dywc6d+6sWbNmadq0aRo4cKD8/f21ePFiBQcH38G1BAAAuHvw1AAAwD1t4sSJWrBggU6fPm3rUgAAAO4JnBEAALinzJs3T02bNlWpUqUUGxurd999V/3797d1WQAAAPcMggAAwD3l2LFjmjBhgs6dO6dKlSrpzTff1MiRI21dFgAAwD2DSwMAAAAAALAjDrYuAAAAAAAA3DkEAQAAAAAA2BGCAAAAAAAA7AhBAAAAAAAAdoQgAAAAAAAAO0IQAAAAAACAHSEIAAAAAADAjhAEAAAAAABgR/4PnAWgJEyzUGAAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=(10,6))\n", + "sns.barplot(x='Region', y='Count', hue='Disaster Type', data=disaster_map, errorbar=None, palette='muted')\n", + "plt.title('Count of Each Disaster by Region')\n", + "plt.ylabel('Count')\n", + "plt.xlabel('Region')\n", + "plt.legend(title='Disaster Type', bbox_to_anchor=(1.05, 1), loc='upper left')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##### Find the number of claims by region #####" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [], + "source": [ + "regional_claim_map = data.get_total_claims_per_regional_disaster()" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Count\n", + "Region \n", + "south 328\n", + "midwest 240\n", + "west 224\n", + "northeast 208\n" + ] + } + ], + "source": [ + "# Initialize lists to store the data\n", + "claim_map_regions = []\n", + "claim_map_state = []\n", + "claim_map_counts = []\n", + "\n", + "# Populate the lists with data\n", + "for region, state in regional_claim_map.items():\n", + " for state_name, count in state.items():\n", + " claim_map_regions.append(region)\n", + " claim_map_state.append(state_name)\n", + " claim_map_counts.append(count)\n", + "\n", + "# Create a DataFrame\n", + "claim_map = pd.DataFrame({\n", + " 'Region': claim_map_regions,\n", + " 'Disaster Type': claim_map_state,\n", + " 'Count': claim_map_counts\n", + "})\n", + "\n", + "\n", + "# Print the sum of the disaster regionally.\n", + "total_claim_map = claim_map.groupby(['Region']).sum().sort_values(by='Count', ascending=False)\n", + "print(total_claim_map)" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1IAAAIjCAYAAAAJLyrXAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy89olMNAAAACXBIWXMAAA9hAAAPYQGoP6dpAABJiUlEQVR4nO3deVwVZf//8fcBWRQFxAUkcU8Ft0xN0UpMFJcWCzPLTMstQ82l9PbO2626+Wq5ZS7ZXWKm3WZli+auuKIp5r4bLqloqYArCFy/P/p5bk9uDKIH5fV8PM7j4Vxzzcxnhjly3szMdWzGGCMAAAAAQJa5OLsAAAAAALjXEKQAAAAAwCKCFAAAAABYRJACAAAAAIsIUgAAAABgEUEKAAAAACwiSAEAAACARQQpAAAAALCIIAUAAAAAFhGkACAXiY2Nlc1mU2xsrLNLyfXS09PVv39/BQUFycXFRa1atcqR9d7Oz2Do0KGy2Ww5UsftCgsLU9WqVZ1dxh0VExMjm82mgwcPOrsUAHkQQQpAnmez2bL0ysoH63//+9/6/vvv73jNVxw4cEDdunVTuXLl5OnpKW9vbzVo0EDjxo3TxYsX71odNzNx4kTFxMTk+Ho///xzffDBB2rdurWmTZumPn363HKZOXPmqHnz5ipatKjc3d0VGBioNm3aaNmyZTleX17x9/eJt7e3GjZsqHnz5jm7NAC4o2zGGOPsIgDAmb788kuH6S+++EKLFy/W9OnTHdqbNGkif3//m66rYMGCat26dbaDQ2xsrBo1aqTly5crLCzspn3nzZun559/Xh4eHnrllVdUtWpVpaWlafXq1fr222/VsWNHTZkyJVt15KSqVauqaNGiOX6VrW3btlq9erV+//33W/Y1xui1115TTEyMatasqdatWysgIEDHjx/XnDlzFB8frzVr1qh+/fqWfgZ/l56ervT0dHl6emZzr3JOWFiY/vzzT23fvv2Obsdms6lJkyZ65ZVXZIzRoUOHNGnSJB0/flzz589XRETEHdt2RkaGLl++LA8Pj1xzJRBA3pHP2QUAgLO9/PLLDtPr1q3T4sWLr2nPTRISEtS2bVuVLl1ay5YtU4kSJezzoqKitH///vv+isDJkyfl6+ubpb6jRo1STEyMevfurdGjRzt86H7nnXc0ffp05ct3+78S8+XLlyPruddUrFjR4f0SGRmpkJAQjRs37o4GKVdXV7m6ut6x9QPAzXBrHwBkwfnz59WvXz8FBQXJw8NDlSpV0ocffqirL+rbbDadP39e06ZNs9/m1LFjR0nSoUOH9MYbb6hSpUrKnz+/ihQpoueffz7bz3aMHDlS586d02effeYQoq6oUKGC3nzzTft0enq63n33XZUvX14eHh4qU6aM/vnPfyo1NdVhOZvNpqFDh16zvjJlytj3Rfrfsylr1qxR3759VaxYMXl5eenZZ5/VH3/84bDcjh07tGLFCvsxudVVnlsd64MHD8pms2n58uXasWPHLW+9vHjxoqKjo1W5cmV9+OGH171y0b59ez3yyCM3rGnVqlV6/vnnVapUKXl4eCgoKEh9+vS55vbJ6z0jZbPZ1KNHD82ePVshISHKnz+/QkNDtW3bNknSJ598ogoVKsjT01NhYWHXnBP79u1TZGSkAgIC5OnpqZIlS6pt27ZKTk6+6XG8Ij4+XvXr11f+/PlVtmxZTZ482T7v3Llz8vLycjhXrvj999/l6uqq6OjoLG3nasHBwSpatKgOHDjg0J6amqohQ4aoQoUK9uPYv3//a87DixcvqlevXipatKgKFSqkp59+WkePHr3m/LzRM1ITJ05UlSpV5OHhocDAQEVFRSkpKcmhz5VnyHbu3KlGjRqpQIECeuCBBzRy5EjL+wsgb8p7fzYDAIuMMXr66ae1fPlyderUSQ899JAWLlyot99+W0ePHtWYMWMkSdOnT1fnzp31yCOPqGvXrpKk8uXLS5I2bNigtWvXqm3btipZsqQOHjyoSZMmKSwsTDt37lSBAgUs1fTTTz+pXLlyql+/fpb6d+7cWdOmTVPr1q3Vr18/rV+/XtHR0dq1a5fmzJljadtX69mzpwoXLqwhQ4bo4MGDGjt2rHr06KFZs2ZJksaOHauePXuqYMGCeueddyTpprdHZuVYFytWTNOnT9f777+vc+fO2T/oBwcHX3edq1ev1unTp9W7d+9sX72YPXu2Lly4oO7du6tIkSL65ZdfNH78eP3++++aPXv2LZdftWqVfvzxR0VFRUmSoqOj9eSTT6p///6aOHGi3njjDZ05c0YjR47Ua6+9Zn9mKy0tTREREUpNTVXPnj0VEBCgo0ePau7cuUpKSpKPj89Nt3vmzBm1aNFCbdq00Ysvvqivv/5a3bt3l7u7u1577TUVLFhQzz77rGbNmqXRo0c7HJ+vvvpKxhi1a9fO8vFKTk7WmTNn7Oe/JGVmZurpp5/W6tWr1bVrVwUHB2vbtm0aM2aM9u7d6/BsYceOHfX111+rffv2qlevnlasWKGWLVtmadtDhw7VsGHDFB4eru7du2vPnj2aNGmSNmzYoDVr1sjNzc3h+DRr1kzPPfec2rRpo2+++UYDBgxQtWrV1Lx5c8v7DSCPMQAAB1FRUebq/x6///57I8m89957Dv1at25tbDab2b9/v73Ny8vLdOjQ4Zp1Xrhw4Zq2uLg4I8l88cUX9rbly5cbSWb58uU3rC85OdlIMs8880yW9mfz5s1GkuncubND+1tvvWUkmWXLltnbJJkhQ4Zcs47SpUs77NfUqVONJBMeHm4yMzPt7X369DGurq4mKSnJ3lalShXTsGHDLNVq5Vg3bNjQVKlS5ZbrHDdunJFk5syZk6UarvczuN7PLzo62thsNnPo0CF725AhQ8zff7VKMh4eHiYhIcHe9sknnxhJJiAgwKSkpNjbBw4caCTZ+/76669Gkpk9e3aWar9aw4YNjSQzatQoe1tqaqp56KGHTPHixU1aWpoxxpiFCxcaSWb+/PkOy1evXj1LPzdJplOnTuaPP/4wJ0+eNBs3bjTNmjUzkswHH3xg7zd9+nTj4uJiVq1a5bD85MmTjSSzZs0aY4wx8fHxRpLp3bu3Q7+OHTtec35eOQ+vHK+TJ08ad3d307RpU5ORkWHv9/HHHxtJ5vPPP7/m+Fz9/ktNTTUBAQEmMjLylvsNANzaBwC38PPPP8vV1VW9evVyaO/Xr5+MMZo/f/4t15E/f377vy9fvqxTp06pQoUK8vX11aZNmyzVk5KSIkkqVKhQlvr//PPPkqS+ffs6tPfr10+SbutZqq5duzrcyvbYY48pIyNDhw4dytb6cuJY/53V43U9V//8zp8/rz///FP169eXMUa//vrrLZdv3LixypQpY5+uW7eupL+eJbq6rivtv/32myTZrzgtXLhQFy5csFx3vnz51K1bN/u0u7u7unXrppMnTyo+Pl6SFB4ersDAQM2YMcPeb/v27dq6dWuWnxP87LPPVKxYMRUvXly1a9fW0qVL1b9/f4dzbvbs2QoODlblypX1559/2l9PPPGEJGn58uWSpAULFkiS3njjDYdt9OzZ85Z1LFmyRGlpaerdu7dcXP73EadLly7y9va+5lwvWLCgwz66u7vrkUcesR9/ALgZghQA3MKhQ4cUGBh4zQfxK7eSZSU0XLx4UYMHD7Y/91O0aFEVK1ZMSUlJWX7W5Qpvb29J0tmzZ7Ncv4uLiypUqODQHhAQIF9f32yHHkkqVaqUw3ThwoUl/XXLVHbkxLH+O6vH63oOHz6sjh07ys/PTwULFlSxYsXUsGFDScrSz+/vx+lKQAoKCrpu+5XjV7ZsWfXt21f/+c9/VLRoUUVERGjChAlZPmcCAwPl5eXl0FaxYkVJsj9X5OLionbt2un777+3h7UZM2bI09NTzz//fJa288wzz2jx4sWaN2+e/TmxCxcuOISZffv2aceOHSpWrJjD60o9J0+elPS/87Vs2bIO2/j7+Xs9V86PSpUqObS7u7urXLly15w/JUuWvOaZtsKFC2f7/AWQt/CMFADcBT179tTUqVPVu3dvhYaGysfHRzabTW3btlVmZqaldXl7eyswMNDysNa3Mzx0RkbGddtv9MyRyUXfrFG5cmVJ0rZt27L1pb0ZGRlq0qSJTp8+rQEDBqhy5cry8vLS0aNH1bFjxyz9/G50nLJy/EaNGqWOHTvqhx9+0KJFi9SrVy9FR0dr3bp1KlmypOX9uZ5XXnlFH3zwgb7//nu9+OKLmjlzpp588slbPoN1RcmSJRUeHi5JatGihYoWLaoePXqoUaNGeu655yT99YxUtWrVNHr06Ouu4++h8m64F85fALkXV6QA4BZKly6tY8eOXXNFY/fu3fb5V9worHzzzTfq0KGDRo0apdatW6tJkyZ69NFHrxlJLKuefPJJHThwQHFxcVmqPzMzU/v27XNoP3HihJKSkhzqL1y48DU1paWl6fjx49mqU7IW4Kwc66x69NFHVbhwYX311Vc3DIQ3s23bNu3du1ejRo3SgAED9Mwzz9hvh7tbqlWrpkGDBmnlypVatWqVjh496jD63o0cO3ZM58+fd2jbu3evJDncali1alXVrFlTM2bM0KpVq3T48GG1b98+2/V269ZN5cuX16BBg+yhpHz58jp9+rQaN26s8PDwa15XriJdOV8TEhIc1rl///5bbvfK+bFnzx6H9rS0NCUkJGTr/AGAGyFIAcAttGjRQhkZGfr4448d2seMGSObzeYwupeXl9d1w5Grq+s1f+UeP358tj7YS1L//v3l5eWlzp0768SJE9fMP3DggMaNG2evX/prBL2rXbkycPVoaOXLl9fKlSsd+k2ZMiXbdUo3PibXY+VYZ1WBAgU0YMAA7dq1SwMGDLju1YYvv/xSv/zyy3WXv3LV4urljDH243snpaSkKD093aGtWrVqcnFxuWbI8OtJT0/XJ598Yp9OS0vTJ598omLFiqlWrVoOfdu3b69FixZp7NixKlKkyG2NWpcvXz7169dPu3bt0g8//CBJatOmjY4ePapPP/30mv4XL160B74r3zs1ceJEhz7jx4+/5XbDw8Pl7u6ujz76yOHn9dlnnyk5OTnLI/8BQFZwax8A3MJTTz2lRo0a6Z133tHBgwdVo0YNLVq0SD/88IN69+7tMMRzrVq1tGTJEo0ePVqBgYEqW7as6tatqyeffFLTp0+Xj4+PQkJCFBcXpyVLlqhIkSLZqql8+fKaOXOmXnjhBQUHB+uVV15R1apVlZaWprVr12r27Nn2732qUaOGOnTooClTpigpKUkNGzbUL7/8omnTpqlVq1Zq1KiRfb2dO3fW66+/rsjISDVp0kRbtmzRwoULVbRo0Wwfv1q1amnSpEl67733VKFCBRUvXtw+wMDfWTnWVrz99tvasWOHRo0apeXLl6t169YKCAhQYmKivv/+e/3yyy9au3btdZetXLmyypcvr7feektHjx6Vt7e3vv3227vyHM2yZcvUo0cPPf/886pYsaLS09M1ffp0ubq6KjIy8pbLBwYGasSIETp48KAqVqyoWbNmafPmzZoyZYrDMOCS9NJLL6l///6aM2eOunfvfs18qzp27KjBgwdrxIgRatWqldq3b6+vv/5ar7/+upYvX64GDRooIyNDu3fv1tdff62FCxeqdu3aqlWrliIjIzV27FidOnXKPvz5lStpN7vCWaxYMQ0cOFDDhg1Ts2bN9PTTT2vPnj2aOHGi6tSpk6u/ZBvAPcg5gwUCQO719+HPjTHm7Nmzpk+fPiYwMNC4ubmZBx980HzwwQcOQ38bY8zu3bvN448/bvLnz28k2YcMP3PmjHn11VdN0aJFTcGCBU1ERITZvXv3NcOKZ2X486vt3bvXdOnSxZQpU8a4u7ubQoUKmQYNGpjx48ebS5cu2ftdvnzZDBs2zJQtW9a4ubmZoKAgM3DgQIc+xhiTkZFhBgwYYIoWLWoKFChgIiIizP79+284/PmGDRsclr9e/YmJiaZly5amUKFCRtIth9TO6rHO6vDnV/vmm29M06ZNjZ+fn8mXL58pUaKEeeGFF0xsbOxN92Hnzp0mPDzcFCxY0BQtWtR06dLFbNmyxUgyU6dOtfe70fDnUVFRDm0JCQnXDA9+9bavDHf+22+/mddee82UL1/eeHp6Gj8/P9OoUSOzZMmSW+7rleOzceNGExoaajw9PU3p0qXNxx9/fMNlWrRoYSSZtWvX3nL9N9u/K4YOHepwLNPS0syIESNMlSpVjIeHhylcuLCpVauWGTZsmElOTrYvd/78eRMVFWX8/PxMwYIFTatWrcyePXuMJPN///d/9n5/H/78io8//thUrlzZuLm5GX9/f9O9e3dz5syZ6x6fv+vQoYMpXbp0lvcfQN5lM4YnKgEAgPTss89q27ZtWXoe6W7bvHmzatasqS+//DJbXxIMADmNZ6QAAICOHz+uefPm3dYgEznl4sWL17SNHTtWLi4uevzxx51QEQBci2ekAADIwxISErRmzRr95z//kZubm8MX+DrLyJEjFR8fr0aNGilfvnyaP3++5s+fr65duzplmHQAuB6CFAAAediKFSv06quvqlSpUpo2bZoCAgKcXZLq16+vxYsX691339W5c+dUqlQpDR06VO+8846zSwMAO56RAgAAAACLeEYKAAAAACwiSAEAAACARTwjJSkzM1PHjh1ToUKFbvpFfwAAAADub8YYnT17VoGBgXJxufF1J4KUpGPHjjEKEAAAAAC7I0eOqGTJkjecT5CSVKhQIUl/HSxvb28nVwMAAADAWVJSUhQUFGTPCDdCkJLst/N5e3sTpAAAAADc8pEfBpsAAAAAAIsIUgAAAABgEUEKAAAAACwiSAEAAACARQQpAAAAALCIIAUAAAAAFhGkAAAAAMAighQAAAAAWESQAgAAAACLCFIAAAAAYBFBCgAAAAAsIkgBAAAAgEUEKQAAAACwiCAFAAAAABYRpAAAAADAIoIUAAAAAFhEkAIAAAAAiwhSAAAAAGARQQoAAAAALMrn7ALuRy8NjnV2CcgjZg4Pc3YJAAAAeRJXpAAAAADAIoIUAAAAAFhEkAIAAAAAiwhSAAAAAGARQQoAAAAALCJIAQAAAIBFBCkAAAAAsIggBQAAAAAWEaQAAAAAwCKCFAAAAABYRJACAAAAAIsIUgAAAABgEUEKAAAAACwiSAEAAACARQQpAAAAALCIIAUAAAAAFhGkAAAAAMAighQAAAAAWESQAgAAAACLCFIAAAAAYBFBCgAAAAAsIkgBAAAAgEUEKQAAAACwiCAFAAAAABYRpAAAAADAIoIUAAAAAFhEkAIAAAAAiwhSAAAAAGARQQoAAAAALCJIAQAAAIBFBCkAAAAAsIggBQAAAAAWOTVITZo0SdWrV5e3t7e8vb0VGhqq+fPn2+dfunRJUVFRKlKkiAoWLKjIyEidOHHCYR2HDx9Wy5YtVaBAARUvXlxvv/220tPT7/auAAAAAMhDnBqkSpYsqf/7v/9TfHy8Nm7cqCeeeELPPPOMduzYIUnq06ePfvrpJ82ePVsrVqzQsWPH9Nxzz9mXz8jIUMuWLZWWlqa1a9dq2rRpiomJ0eDBg521SwAAAADyAJsxxji7iKv5+fnpgw8+UOvWrVWsWDHNnDlTrVu3liTt3r1bwcHBiouLU7169TR//nw9+eSTOnbsmPz9/SVJkydP1oABA/THH3/I3d09S9tMSUmRj4+PkpOT5e3tfdv78NLg2NteB5AVM4eHObsEAACA+0pWs0GueUYqIyND//3vf3X+/HmFhoYqPj5ely9fVnh4uL1P5cqVVapUKcXFxUmS4uLiVK1aNXuIkqSIiAilpKTYr2pdT2pqqlJSUhxeAAAAAJBVTg9S27ZtU8GCBeXh4aHXX39dc+bMUUhIiBITE+Xu7i5fX1+H/v7+/kpMTJQkJSYmOoSoK/OvzLuR6Oho+fj42F9BQUE5u1MAAAAA7mtOD1KVKlXS5s2btX79enXv3l0dOnTQzp077+g2Bw4cqOTkZPvryJEjd3R7AAAAAO4v+ZxdgLu7uypUqCBJqlWrljZs2KBx48bphRdeUFpampKSkhyuSp04cUIBAQGSpICAAP3yyy8O67syqt+VPtfj4eEhDw+PHN4TAAAAAHmF069I/V1mZqZSU1NVq1Ytubm5aenSpfZ5e/bs0eHDhxUaGipJCg0N1bZt23Ty5El7n8WLF8vb21shISF3vXYAAAAAeYNTr0gNHDhQzZs3V6lSpXT27FnNnDlTsbGxWrhwoXx8fNSpUyf17dtXfn5+8vb2Vs+ePRUaGqp69epJkpo2baqQkBC1b99eI0eOVGJiogYNGqSoqCiuOAEAAAC4Y5wapE6ePKlXXnlFx48fl4+Pj6pXr66FCxeqSZMmkqQxY8bIxcVFkZGRSk1NVUREhCZOnGhf3tXVVXPnzlX37t0VGhoqLy8vdejQQcOHD3fWLgEAAADIA3Ld90g5A98jhXsV3yMFAACQs+6575ECAAAAgHsFQQoAAAAALCJIAQAAAIBFBCkAAAAAsIggBQAAAAAWEaQAAAAAwCKCFAAAAABYRJACAAAAAIsIUgAAAABgEUEKAAAAACwiSAEAAACARQQpAAAAALCIIAUAAAAAFhGkAAAAAMAighQAAAAAWESQAgAAAACLCFIAAAAAYBFBCgAAAAAsIkgBAAAAgEUEKQAAAACwiCAFAAAAABYRpAAAAADAIoIUAAAAAFhEkAIAAAAAiwhSAAAAAGARQQoAAAAALCJIAQAAAIBFBCkAAAAAsIggBQAAAAAWEaQAAAAAwCKCFAAAAABYRJACAAAAAIsIUgAAAABgEUEKAAAAACwiSAEAAACARQQpAAAAALCIIAUAAAAAFhGkAAAAAMAighQAAAAAWESQAgAAAACLCFIAAAAAYBFBCgAAAAAsIkgBAAAAgEUEKQAAAACwiCAFAAAAABYRpAAAAADAIoIUAAAAAFhEkAIAAAAAiwhSAAAAAGARQQoAAAAALCJIAQAAAIBFBCkAAAAAsIggBQAAAAAWEaQAAAAAwCKCFAAAAABYRJACAAAAAIucGqSio6NVp04dFSpUSMWLF1erVq20Z88ehz5hYWGy2WwOr9dff92hz+HDh9WyZUsVKFBAxYsX19tvv6309PS7uSsAAAAA8pB8ztz4ihUrFBUVpTp16ig9PV3//Oc/1bRpU+3cuVNeXl72fl26dNHw4cPt0wUKFLD/OyMjQy1btlRAQIDWrl2r48eP65VXXpGbm5v+/e9/39X9AQAAAJA3ODVILViwwGE6JiZGxYsXV3x8vB5//HF7e4ECBRQQEHDddSxatEg7d+7UkiVL5O/vr4ceekjvvvuuBgwYoKFDh8rd3f2O7gMAAACAvCdXPSOVnJwsSfLz83NonzFjhooWLaqqVatq4MCBunDhgn1eXFycqlWrJn9/f3tbRESEUlJStGPHjutuJzU1VSkpKQ4vAAAAAMgqp16RulpmZqZ69+6tBg0aqGrVqvb2l156SaVLl1ZgYKC2bt2qAQMGaM+ePfruu+8kSYmJiQ4hSpJ9OjEx8brbio6O1rBhw+7QngAAAAC43+WaIBUVFaXt27dr9erVDu1du3a1/7tatWoqUaKEGjdurAMHDqh8+fLZ2tbAgQPVt29f+3RKSoqCgoKyVzgAAACAPCdX3NrXo0cPzZ07V8uXL1fJkiVv2rdu3bqSpP3790uSAgICdOLECYc+V6Zv9FyVh4eHvL29HV4AAAAAkFVODVLGGPXo0UNz5szRsmXLVLZs2Vsus3nzZklSiRIlJEmhoaHatm2bTp48ae+zePFieXt7KyQk5I7UDQAAACBvc+qtfVFRUZo5c6Z++OEHFSpUyP5Mk4+Pj/Lnz68DBw5o5syZatGihYoUKaKtW7eqT58+evzxx1W9enVJUtOmTRUSEqL27dtr5MiRSkxM1KBBgxQVFSUPDw9n7h4AAACA+5RTr0hNmjRJycnJCgsLU4kSJeyvWbNmSZLc3d21ZMkSNW3aVJUrV1a/fv0UGRmpn376yb4OV1dXzZ07V66urgoNDdXLL7+sV155xeF7pwAAAAAgJzn1ipQx5qbzg4KCtGLFiluup3Tp0vr5559zqiwAAAAAuKlcMdgEAAAAANxLCFIAAAAAYBFBCgAAAAAsIkgBAAAAgEUEKQAAAACwiCAFAAAAABYRpAAAAADAIqd+jxSA+9feDzs6uwTkERXfinF2CQCAPIgrUgAAAABgEUEKAAAAACwiSAEAAACARQQpAAAAALCIIAUAAAAAFhGkAAAAAMAighQAAAAAWESQAgAAAACLCFIAAAAAYBFBCgAAAAAsIkgBAAAAgEUEKQAAAACwiCAFAAAAABYRpAAAAADAIoIUAAAAAFhEkAIAAAAAiwhSAAAAAGARQQoAAAAALCJIAQAAAIBFBCkAAAAAsCifswsAAOB+1T+2r7NLQB4xMmy0s0sA8hyuSAEAAACARQQpAAAAALCIIAUAAAAAFhGkAAAAAMAighQAAAAAWESQAgAAAACLCFIAAAAAYBFBCgAAAAAsIkgBAAAAgEUEKQAAAACwiCAFAAAAABYRpAAAAADAIoIUAAAAAFhEkAIAAAAAiwhSAAAAAGARQQoAAAAALCJIAQAAAIBFBCkAAAAAsIggBQAAAAAWEaQAAAAAwCKCFAAAAABYlM/ZBQAAAOD+tO7NN51dAvKIeuPG3fVtckUKAAAAACwiSAEAAACARQQpAAAAALCIIAUAAAAAFhGkAAAAAMAighQAAAAAWOTUIBUdHa06deqoUKFCKl68uFq1aqU9e/Y49Ll06ZKioqJUpEgRFSxYUJGRkTpx4oRDn8OHD6tly5YqUKCAihcvrrffflvp6el3c1cAAAAA5CFODVIrVqxQVFSU1q1bp8WLF+vy5ctq2rSpzp8/b+/Tp08f/fTTT5o9e7ZWrFihY8eO6bnnnrPPz8jIUMuWLZWWlqa1a9dq2rRpiomJ0eDBg52xSwAAAADyAKd+Ie+CBQscpmNiYlS8eHHFx8fr8ccfV3Jysj777DPNnDlTTzzxhCRp6tSpCg4O1rp161SvXj0tWrRIO3fu1JIlS+Tv76+HHnpI7777rgYMGKChQ4fK3d39mu2mpqYqNTXVPp2SknJndxQAAADAfSVXPSOVnJwsSfLz85MkxcfH6/LlywoPD7f3qVy5skqVKqW4uDhJUlxcnKpVqyZ/f397n4iICKWkpGjHjh3X3U50dLR8fHzsr6CgoDu1SwAAAADuQ7kmSGVmZqp3795q0KCBqlatKklKTEyUu7u7fH19Hfr6+/srMTHR3ufqEHVl/pV51zNw4EAlJyfbX0eOHMnhvQEAAABwP3PqrX1Xi4qK0vbt27V69eo7vi0PDw95eHjc8e0AAAAAuD/liitSPXr00Ny5c7V8+XKVLFnS3h4QEKC0tDQlJSU59D9x4oQCAgLsff4+it+V6St9AAAAACAnOTVIGWPUo0cPzZkzR8uWLVPZsmUd5teqVUtubm5aunSpvW3Pnj06fPiwQkNDJUmhoaHatm2bTp48ae+zePFieXt7KyQk5O7sCAAAAIA8xam39kVFRWnmzJn64YcfVKhQIfszTT4+PsqfP798fHzUqVMn9e3bV35+fvL29lbPnj0VGhqqevXqSZKaNm2qkJAQtW/fXiNHjlRiYqIGDRqkqKgobt8DAAAAcEc4NUhNmjRJkhQWFubQPnXqVHXs2FGSNGbMGLm4uCgyMlKpqamKiIjQxIkT7X1dXV01d+5cde/eXaGhofLy8lKHDh00fPjwu7UbAAAAAPIYpwYpY8wt+3h6emrChAmaMGHCDfuULl1aP//8c06WBgAAAAA3lCsGmwAAAACAewlBCgAAAAAsIkgBAAAAgEUEKQAAAACwiCAFAAAAABYRpAAAAADAIoIUAAAAAFhEkAIAAAAAiwhSAAAAAGARQQoAAAAALCJIAQAAAIBFBCkAAAAAsChbQapcuXI6derUNe1JSUkqV67cbRcFAAAAALlZtoLUwYMHlZGRcU17amqqjh49ettFAQAAAEBuls9K5x9//NH+74ULF8rHx8c+nZGRoaVLl6pMmTI5VhwAAAAA5EaWglSrVq0kSTabTR06dHCY5+bmpjJlymjUqFE5VhwAAAAA5EaWglRmZqYkqWzZstqwYYOKFi16R4oCAAAAgNzMUpC6IiEhIafrAAAAAIB7RraClCQtXbpUS5cu1cmTJ+1Xqq74/PPPb7swAAAAAMitshWkhg0bpuHDh6t27doqUaKEbDZbTtcFAAAAALlWtoLU5MmTFRMTo/bt2+d0PQAAAACQ62Xre6TS0tJUv379nK4FAAAAAO4J2QpSnTt31syZM3O6FgAAAAC4J2Tr1r5Lly5pypQpWrJkiapXry43NzeH+aNHj86R4gAAAAAgN8pWkNq6daseeughSdL27dsd5jHwBAAAAID7XbaC1PLly3O6DgAAAAC4Z2TrGSkAAAAAyMuydUWqUaNGN72Fb9myZdkuCAAAAAByu2wFqSvPR11x+fJlbd68Wdu3b1eHDh1yoi4AAAAAyLWyFaTGjBlz3fahQ4fq3Llzt1UQAAAAAOR2OfqM1Msvv6zPP/88J1cJAAAAALlOjgapuLg4eXp65uQqAQAAACDXydatfc8995zDtDFGx48f18aNG/Wvf/0rRwoDAAAAgNwqW0HKx8fHYdrFxUWVKlXS8OHD1bRp0xwpDAAAAAByq2wFqalTp+Z0HQAAAABwz8hWkLoiPj5eu3btkiRVqVJFNWvWzJGiAAAAACA3y1aQOnnypNq2bavY2Fj5+vpKkpKSktSoUSP997//VbFixXKyRgAAAADIVbI1al/Pnj119uxZ7dixQ6dPn9bp06e1fft2paSkqFevXjldIwAAAADkKtm6IrVgwQItWbJEwcHB9raQkBBNmDCBwSYAAAAA3PeydUUqMzNTbm5u17S7ubkpMzPztosCAAAAgNwsW0HqiSee0Jtvvqljx47Z244ePao+ffqocePGOVYcAAAAAORG2QpSH3/8sVJSUlSmTBmVL19e5cuXV9myZZWSkqLx48fndI0AAAAAkKtk6xmpoKAgbdq0SUuWLNHu3bslScHBwQoPD8/R4gAAAAAgN7J0RWrZsmUKCQlRSkqKbDabmjRpop49e6pnz56qU6eOqlSpolWrVt2pWgEAAAAgV7AUpMaOHasuXbrI29v7mnk+Pj7q1q2bRo8enWPFAQAAAEBuZClIbdmyRc2aNbvh/KZNmyo+Pv62iwIAAACA3MxSkDpx4sR1hz2/Il++fPrjjz9uuygAAAAAyM0sBakHHnhA27dvv+H8rVu3qkSJErddFAAAAADkZpaCVIsWLfSvf/1Lly5dumbexYsXNWTIED355JM5VhwAAAAA5EaWhj8fNGiQvvvuO1WsWFE9evRQpUqVJEm7d+/WhAkTlJGRoXfeeeeOFAoAAAAAuYWlIOXv76+1a9eqe/fuGjhwoIwxkiSbzaaIiAhNmDBB/v7+d6RQAAAAAMgtLH8hb+nSpfXzzz/rzJkz2r9/v4wxevDBB1W4cOE7UR8AAAAA5DqWg9QVhQsXVp06dXKyFgAAAAC4J1gabAIAAAAAQJACAAAAAMsIUgAAAABgkVOD1MqVK/XUU08pMDBQNptN33//vcP8jh07ymazObyaNWvm0Of06dNq166dvL295evrq06dOuncuXN3cS8AAAAA5DVODVLnz59XjRo1NGHChBv2adasmY4fP25/ffXVVw7z27Vrpx07dmjx4sWaO3euVq5cqa5du97p0gEAAADkYdketS8nNG/eXM2bN79pHw8PDwUEBFx33q5du7RgwQJt2LBBtWvXliSNHz9eLVq00IcffqjAwMAcrxkAAAAAcv0zUrGxsSpevLgqVaqk7t2769SpU/Z5cXFx8vX1tYcoSQoPD5eLi4vWr19/w3WmpqYqJSXF4QUAAAAAWZWrg1SzZs30xRdfaOnSpRoxYoRWrFih5s2bKyMjQ5KUmJio4sWLOyyTL18++fn5KTEx8YbrjY6Olo+Pj/0VFBR0R/cDAAAAwP3Fqbf23Urbtm3t/65WrZqqV6+u8uXLKzY2Vo0bN872egcOHKi+ffvap1NSUghTAAAAALIsV1+R+rty5cqpaNGi2r9/vyQpICBAJ0+edOiTnp6u06dP3/C5Kumv5668vb0dXgAAAACQVfdUkPr999916tQplShRQpIUGhqqpKQkxcfH2/ssW7ZMmZmZqlu3rrPKBAAAAHCfc+qtfefOnbNfXZKkhIQEbd68WX5+fvLz89OwYcMUGRmpgIAAHThwQP3791eFChUUEREhSQoODlazZs3UpUsXTZ48WZcvX1aPHj3Utm1bRuwDAAAAcMc49YrUxo0bVbNmTdWsWVOS1LdvX9WsWVODBw+Wq6urtm7dqqeffloVK1ZUp06dVKtWLa1atUoeHh72dcyYMUOVK1dW48aN1aJFCz366KOaMmWKs3YJAAAAQB7g1CtSYWFhMsbccP7ChQtvuQ4/Pz/NnDkzJ8sCAAAAgJu6p56RAgAAAIDcgCAFAAAAABYRpAAAAADAIoIUAAAAAFhEkAIAAAAAiwhSAAAAAGARQQoAAAAALCJIAQAAAIBFBCkAAAAAsIggBQAAAAAWEaQAAAAAwCKCFAAAAABYRJACAAAAAIsIUgAAAABgEUEKAAAAACwiSAEAAACARQQpAAAAALCIIAUAAAAAFhGkAAAAAMAighQAAAAAWESQAgAAAACLCFIAAAAAYBFBCgAAAAAsIkgBAAAAgEUEKQAAAACwiCAFAAAAABYRpAAAAADAIoIUAAAAAFhEkAIAAAAAiwhSAAAAAGARQQoAAAAALCJIAQAAAIBFBCkAAAAAsIggBQAAAAAWEaQAAAAAwCKCFAAAAABYRJACAAAAAIsIUgAAAABgEUEKAAAAACwiSAEAAACARQQpAAAAALCIIAUAAAAAFhGkAAAAAMAighQAAAAAWESQAgAAAACLCFIAAAAAYBFBCgAAAAAsIkgBAAAAgEUEKQAAAACwiCAFAAAAABYRpAAAAADAIoIUAAAAAFhEkAIAAAAAiwhSAAAAAGARQQoAAAAALCJIAQAAAIBFTg1SK1eu1FNPPaXAwEDZbDZ9//33DvONMRo8eLBKlCih/PnzKzw8XPv27XPoc/r0abVr107e3t7y9fVVp06ddO7cubu4FwAAAADyGqcGqfPnz6tGjRqaMGHCdeePHDlSH330kSZPnqz169fLy8tLERERunTpkr1Pu3bttGPHDi1evFhz587VypUr1bVr17u1CwAAAADyoHzO3Hjz5s3VvHnz684zxmjs2LEaNGiQnnnmGUnSF198IX9/f33//fdq27atdu3apQULFmjDhg2qXbu2JGn8+PFq0aKFPvzwQwUGBt61fQEAAACQd+TaZ6QSEhKUmJio8PBwe5uPj4/q1q2ruLg4SVJcXJx8fX3tIUqSwsPD5eLiovXr199w3ampqUpJSXF4AQAAAEBW5doglZiYKEny9/d3aPf397fPS0xMVPHixR3m58uXT35+fvY+1xMdHS0fHx/7KygoKIerBwAAAHA/y7VB6k4aOHCgkpOT7a8jR444uyQAAAAA95BcG6QCAgIkSSdOnHBoP3HihH1eQECATp486TA/PT1dp0+ftve5Hg8PD3l7ezu8AAAAACCrcm2QKlu2rAICArR06VJ7W0pKitavX6/Q0FBJUmhoqJKSkhQfH2/vs2zZMmVmZqpu3bp3vWYAAAAAeYNTR+07d+6c9u/fb59OSEjQ5s2b5efnp1KlSql3795677339OCDD6ps2bL617/+pcDAQLVq1UqSFBwcrGbNmqlLly6aPHmyLl++rB49eqht27aM2AcAAADgjnFqkNq4caMaNWpkn+7bt68kqUOHDoqJiVH//v11/vx5de3aVUlJSXr00Ue1YMECeXp62peZMWOGevToocaNG8vFxUWRkZH66KOP7vq+AAAAAMg7nBqkwsLCZIy54Xybzabhw4dr+PDhN+zj5+enmTNn3onyAAAAAOC6cu0zUgAAAACQWxGkAAAAAMAighQAAAAAWESQAgAAAACLCFIAAAAAYBFBCgAAAAAsIkgBAAAAgEUEKQAAAACwiCAFAAAAABYRpAAAAADAIoIUAAAAAFhEkAIAAAAAiwhSAAAAAGARQQoAAAAALCJIAQAAAIBFBCkAAAAAsIggBQAAAAAWEaQAAAAAwCKCFAAAAABYRJACAAAAAIsIUgAAAABgEUEKAAAAACwiSAEAAACARQQpAAAAALCIIAUAAAAAFhGkAAAAAMAighQAAAAAWESQAgAAAACLCFIAAAAAYBFBCgAAAAAsIkgBAAAAgEUEKQAAAACwiCAFAAAAABYRpAAAAADAIoIUAAAAAFhEkAIAAAAAiwhSAAAAAGARQQoAAAAALCJIAQAAAIBFBCkAAAAAsIggBQAAAAAWEaQAAAAAwCKCFAAAAABYRJACAAAAAIsIUgAAAABgEUEKAAAAACwiSAEAAACARQQpAAAAALCIIAUAAAAAFhGkAAAAAMAighQAAAAAWESQAgAAAACLCFIAAAAAYBFBCgAAAAAsIkgBAAAAgEUEKQAAAACwKFcHqaFDh8pmszm8KleubJ9/6dIlRUVFqUiRIipYsKAiIyN14sQJJ1YMAAAAIC/I1UFKkqpUqaLjx4/bX6tXr7bP69Onj3766SfNnj1bK1as0LFjx/Tcc885sVoAAAAAeUE+ZxdwK/ny5VNAQMA17cnJyfrss880c+ZMPfHEE5KkqVOnKjg4WOvWrVO9evXudqkAAAAA8ohcf0Vq3759CgwMVLly5dSuXTsdPnxYkhQfH6/Lly8rPDzc3rdy5coqVaqU4uLibrrO1NRUpaSkOLwAAAAAIKtydZCqW7euYmJitGDBAk2aNEkJCQl67LHHdPbsWSUmJsrd3V2+vr4Oy/j7+ysxMfGm642OjpaPj4/9FRQUdAf3AgAAAMD9Jlff2te8eXP7v6tXr666deuqdOnS+vrrr5U/f/5sr3fgwIHq27evfTolJYUwBQAAACDLcvUVqb/z9fVVxYoVtX//fgUEBCgtLU1JSUkOfU6cOHHdZ6qu5uHhIW9vb4cXAAAAAGTVPRWkzp07pwMHDqhEiRKqVauW3NzctHTpUvv8PXv26PDhwwoNDXVilQAAAADud7n61r633npLTz31lEqXLq1jx45pyJAhcnV11YsvvigfHx916tRJffv2lZ+fn7y9vdWzZ0+FhoYyYh8AAACAOypXB6nff/9dL774ok6dOqVixYrp0Ucf1bp161SsWDFJ0pgxY+Ti4qLIyEilpqYqIiJCEydOdHLVAAAAAO53uTpI/fe//73pfE9PT02YMEETJky4SxUBAAAAwD32jBQAAAAA5AYEKQAAAACwiCAFAAAAABYRpAAAAADAIoIUAAAAAFhEkAIAAAAAiwhSAAAAAGARQQoAAAAALCJIAQAAAIBFBCkAAAAAsIggBQAAAAAWEaQAAAAAwCKCFAAAAABYRJACAAAAAIsIUgAAAABgEUEKAAAAACwiSAEAAACARQQpAAAAALCIIAUAAAAAFhGkAAAAAMAighQAAAAAWESQAgAAAACLCFIAAAAAYBFBCgAAAAAsIkgBAAAAgEUEKQAAAACwiCAFAAAAABYRpAAAAADAIoIUAAAAAFhEkAIAAAAAiwhSAAAAAGARQQoAAAAALCJIAQAAAIBFBCkAAAAAsIggBQAAAAAWEaQAAAAAwCKCFAAAAABYRJACAAAAAIsIUgAAAABgEUEKAAAAACwiSAEAAACARQQpAAAAALCIIAUAAAAAFhGkAAAAAMAighQAAAAAWESQAgAAAACLCFIAAAAAYBFBCgAAAAAsIkgBAAAAgEUEKQAAAACwiCAFAAAAABYRpAAAAADAIoIUAAAAAFhEkAIAAAAAiwhSAAAAAGARQQoAAAAALLpvgtSECRNUpkwZeXp6qm7duvrll1+cXRIAAACA+9R9EaRmzZqlvn37asiQIdq0aZNq1KihiIgInTx50tmlAQAAALgP3RdBavTo0erSpYteffVVhYSEaPLkySpQoIA+//xzZ5cGAAAA4D6Uz9kF3K60tDTFx8dr4MCB9jYXFxeFh4crLi7uusukpqYqNTXVPp2cnCxJSklJyZGaLqeez5H1ALeSU+fsnXDuUpqzS0AekZvfB6nnU2/dCcgBufV9cD6V9wDujpx8D1xZlzHmpv3u+SD1559/KiMjQ/7+/g7t/v7+2r1793WXiY6O1rBhw65pDwoKuiM1AnfKNyOdXQGQC/zrK2dXADjdR5ro7BIA5/rkkxxf5dmzZ+Xj43PD+fd8kMqOgQMHqm/fvvbpzMxMnT59WkWKFJHNZnNiZXlXSkqKgoKCdOTIEXl7ezu7HOCu4z0A8D4AJN4HuYExRmfPnlVgYOBN+93zQapo0aJydXXViRMnHNpPnDihgICA6y7j4eEhDw8PhzZfX987VSIs8Pb25j8N5Gm8BwDeB4DE+8DZbnYl6op7frAJd3d31apVS0uXLrW3ZWZmaunSpQoNDXViZQAAAADuV/f8FSlJ6tu3rzp06KDatWvrkUce0dixY3X+/Hm9+uqrzi4NAAAAwH3ovghSL7zwgv744w8NHjxYiYmJeuihh7RgwYJrBqBA7uXh4aEhQ4Zcc8slkFfwHgB4HwAS74N7ic3calw/AAAAAICDe/4ZKQAAAAC42whSAAAAAGARQQoAAAAALCJI4Z5UpkwZjR071tllAA5iY2Nls9mUlJR0wz4xMTF8bx0AwC4rvzuQOxGkkKvxoRP3kvr16+v48eNZ+hI/Zxg6dKgeeughZ5cB5JiwsDD17t3b2WUAWZZbz1nCXPYQpAAgh7i7uysgIEA2m83ZpQAAcpG0tDRnl4A7gCCF2/bNN9+oWrVqyp8/v4oUKaLw8HCdP39emZmZGj58uEqWLCkPDw/793tdcb2/fmzevFk2m00HDx5UbGysXn31VSUnJ8tms8lms2no0KH2vhcuXNBrr72mQoUKqVSpUpoyZcpd3GvkBWFhYerZs6d69+6twoULy9/fX59++qn9C78LFSqkChUqaP78+ZKuf07HxMSoVKlSKlCggJ599lmdOnXKPi85OVmurq7auHGjJCkzM1N+fn6qV6+evc+XX36poKAg+/SRI0fUpk0b+fr6ys/PT88884wOHjxonx8bG6tHHnlEXl5e8vX1VYMGDXTo0CHFxMRo2LBh2rJli/39FBMTc2cOHPK0uXPnytfXVxkZGZL+9//6P/7xD3ufzp076+WXX5YkrV69Wo899pjy58+voKAg9erVS+fPn7f3nThxoh588EF5enrK399frVu3liR17NhRK1as0Lhx4+zn9NXvBeB2hIWFqVevXurfv7/8/PwUEBDg8Bnk8OHDeuaZZ1SwYEF5e3urTZs2OnHihH3+lTsA/vOf/6hs2bLy9PS85TkbHx+v2rVrq0CBAqpfv7727NnjUNMPP/yghx9+WJ6enipXrpyGDRum9PR0+/zRo0erWrVq8vLyUlBQkN544w2dO3fOPv/QoUN66qmnVLhwYXl5ealKlSr6+eefdfDgQTVq1EiSVLhwYdlsNnXs2DFnD+j9ygC34dixYyZfvnxm9OjRJiEhwWzdutVMmDDBnD171owePdp4e3ubr776yuzevdv079/fuLm5mb179xpjjFm+fLmRZM6cOWNf36+//mokmYSEBJOammrGjh1rvL29zfHjx83x48fN2bNnjTHGlC5d2vj5+ZkJEyaYffv2mejoaOPi4mJ2797tjMOA+1TDhg1NoUKFzLvvvmv27t1r3n33XePq6mqaN29upkyZYvbu3Wu6d+9uihQpYs6fP3/NOb1u3Trj4uJiRowYYfbs2WPGjRtnfH19jY+Pj30bDz/8sPnggw+MMcZs3rzZ+Pn5GXd3d/u53rlzZ9OuXTtjjDFpaWkmODjYvPbaa2br1q1m586d5qWXXjKVKlUyqamp5vLly8bHx8e89dZbZv/+/Wbnzp0mJibGHDp0yFy4cMH069fPVKlSxf5+unDhwl09nsgbkpKSjIuLi9mwYYMxxpixY8eaokWLmrp169r7VKhQwXz66adm//79xsvLy4wZM8bs3bvXrFmzxtSsWdN07NjRGGPMhg0bjKurq5k5c6Y5ePCg2bRpkxk3bpx9O6GhoaZLly72czo9Pf3u7zDuSw0bNjTe3t5m6NChZu/evWbatGnGZrOZRYsWmYyMDPPQQw+ZRx991GzcuNGsW7fO1KpVyzRs2NC+/JAhQ4yXl5dp1qyZ2bRpk9myZcsNz9krvzvq1q1rYmNjzY4dO8xjjz1m6tevb1/fypUrjbe3t4mJiTEHDhwwixYtMmXKlDFDhw619xkzZoxZtmyZSUhIMEuXLjWVKlUy3bt3t89v2bKladKkidm6das5cOCA+emnn8yKFStMenq6+fbbb40ks2fPHnP8+HGTlJR0V47zvY4ghdsSHx9vJJmDBw9eMy8wMNC8//77Dm116tQxb7zxhjHm1kHKGGOmTp3q8KHzitKlS5uXX37ZPp2ZmWmKFy9uJk2adPs7Bfx/DRs2NI8++qh9Oj093Xh5eZn27dvb244fP24kmbi4uGvO6RdffNG0aNHCYZ0vvPCCwzndt29f07JlS2PMXx84X3jhBVOjRg0zf/58Y8xfHzinTJlijDFm+vTpplKlSiYzM9O+fGpqqsmfP79ZuHChOXXqlJFkYmNjr7s/Q4YMMTVq1Mj28QCy6uo/ELRq1cq8//779j8Q/P7770aS2bt3r+nUqZPp2rWrw7KrVq0yLi4u5uLFi+bbb7813t7eJiUl5brbadiwoXnzzTfv9O4gD/r7///G/PUZZsCAAWbRokXG1dXVHD582D5vx44dRpL55ZdfjDF//X/r5uZmTp48ec16/37OXvndsWTJEnvbvHnzjCRz8eJFY4wxjRs3Nv/+978dlps+fbopUaLEDfdh9uzZpkiRIvbpatWqOQSv69Vw9Wcy3Bq39uG21KhRQ40bN1a1atX0/PPP69NPP9WZM2eUkpKiY8eOqUGDBg79GzRooF27duXItqtXr27/t81mU0BAgE6ePJkj6wauuPo8c3V1VZEiRVStWjV7m7+/vyRd99zbtWuX6tat69AWGhrqMN2wYUOtXr1aGRkZWrFihcLCwhQWFqbY2FgdO3ZM+/fvV1hYmCRpy5Yt2r9/vwoVKqSCBQuqYMGC8vPz06VLl3TgwAH5+fmpY8eOioiI0FNPPaVx48bp+PHjOXUogCxr2LChYmNjZYzRqlWr9Nxzzyk4OFirV6/WihUrFBgYqAcffFBbtmxRTEyM/XwuWLCgIiIilJmZqYSEBDVp0kSlS5dWuXLl1L59e82YMUMXLlxw9u4hj7j6/39JKlGihE6ePKldu3YpKCjI4bbrkJAQ+fr6OnzGKV26tIoVK5at7ZUoUULS/363bNmyRcOHD3d4r3Tp0kXHjx+3vyeWLFmixo0b64EHHlChQoXUvn17nTp1yj6/V69eeu+999SgQQMNGTJEW7dutXhE8HcEKdwWV1dXLV68WPPnz1dISIjGjx+vSpUqKSEh4ZbLurj8dfoZY+xtly9fzvK23dzcHKZtNpsyMzOzvDyQFdc7z65uuzKwRHbPvccff1xnz57Vpk2btHLlSocgdfUHTkk6d+6catWqpc2bNzu89u7dq5deekmSNHXqVMXFxal+/fqaNWuWKlasqHXr1mWrNiC7wsLCtHr1am3ZskVubm6qXLmyw3ndsGFDSX+d0926dXM4n7ds2aJ9+/apfPnyKlSokDZt2qSvvvpKJUqU0ODBg1WjRg1GFsNdcbufM7y8vLK9vb//bjl37pyGDRvm8F7Ztm2b9u3bJ09PTx08eFBPPvmkqlevrm+//Vbx8fGaMGGCpP8NdNG5c2f99ttvat++vbZt26batWtr/PjxlmqEI4IUbpvNZlODBg00bNgw/frrr3J3d9fSpUsVGBioNWvWOPRds2aNQkJCJMn+V5qr/2K+efNmh/7u7u72B5aBe01wcLDWr1/v0Pb3UOPr66vq1avr448/tn/gfPzxx/Xrr79q7ty59g+ckvTwww9r3759Kl68uCpUqODwunrI9Zo1a2rgwIFau3atqlatqpkzZ0ri/YS757HHHtPZs2c1ZswY+zl8JUjFxsbar7I+/PDD2rlz5zXnc4UKFeTu7i5Jypcvn8LDwzVy5Eht3bpVBw8e1LJlyyRxTsM5goODdeTIER05csTetnPnTiUlJdk/49xIds/Zhx9+WHv27Lnue8XFxUXx8fHKzMzUqFGjVK9ePVWsWFHHjh27Zj1BQUF6/fXX9d1336lfv3769NNP7XVJ4v1kEUEKt2X9+vX697//rY0bN+rw4cP67rvv9Mcffyg4OFhvv/22RowYoVmzZmnPnj36xz/+oc2bN+vNN9+UJFWoUEFBQUEaOnSo9u3bp3nz5mnUqFEO6y9TpozOnTunpUuX6s8//+SWDtxTevXqpQULFujDDz/Uvn379PHHHzuMXHlFWFiYZsyYYf/A6efnp+DgYM2aNcshSLVr105FixbVM888o1WrVikhIUGxsbHq1auXfv/9dyUkJGjgwIGKi4vToUOHtGjRIu3bt0/BwcGS/no/JSQkaPPmzfrzzz+Vmpp6dw4E8pzChQurevXqmjFjhj00Pf7449q0aZP27t1rP68HDBigtWvXqkePHtq8ebP27dunH374QT169JD01wiAH330kTZv3qxDhw7piy++UGZmpipVqiTpr3N6/fr1OnjwoP7880/uSsBdER4ermrVqqldu3batGmTfvnlF73yyitq2LChateufdNls3vODh48WF988YWGDRumHTt2aNeuXfrvf/+rQYMGSfrrM9Xly5c1fvx4/fbbb5o+fbomT57ssI7evXtr4cKFSkhI0KZNm7R8+XL774fSpUvLZrNp7ty5+uOPPxxG+8ONEaRwW7y9vbVy5Uq1aNFCFStW1KBBgzRq1Cg1b95cvXr1Ut++fdWvXz9Vq1ZNCxYs0I8//mi/TcnNzU1fffWVdu/ererVq2vEiBF67733HNZfv359vf7663rhhRdUrFgxjRw50hm7CWRLvXr19Omnn2rcuHGqUaOGFi1aZP+ld7WGDRsqIyPD/oFT+itc/b2tQIECWrlypUqVKmV/5qRTp066dOmSvL29VaBAAe3evVuRkZGqWLGiunbtqqioKHXr1k2SFBkZqWbNmqlRo0YqVqyYvvrqqzt9CJCH/f289vPzU0hIiAICAuxBqHr16lqxYoX27t2rxx57TDVr1tTgwYMVGBgo6a8rtt99952eeOIJBQcHa/Lkyfrqq69UpUoVSdJbb70lV1dXhYSEqFixYjp8+LBT9hV5i81m0w8//KDChQvr8ccfV3h4uMqVK6dZs2bdctnsnrMRERGaO3euFi1apDp16qhevXoaM2aMSpcuLemvZ9ZHjx6tESNGqGrVqpoxY4aio6Md1pGRkaGoqCgFBwerWbNmqlixoiZOnChJeuCBBzRs2DD94x//kL+/v/2PGbg5m7n6ARUAAAAAwC1xRQoAAAAALCJIAQAAAIBFBCkAAAAAsIggBQAAAAAWEaQAAAAAwCKCFAAAAABYRJACAAAAAIsIUgAAAABgEUEKAIDriImJka+vr7PLAADkUgQpAMA9p2PHjrLZbLLZbHJzc1PZsmXVv39/Xbp0Kce28cILL2jv3r05tj4AwP0ln7MLAAAgO5o1a6apU6fq8uXLio+PV4cOHWSz2TRixIgcWX/+/PmVP3/+HFkXAOD+wxUpAMA9ycPDQwEBAQoKClKrVq0UHh6uxYsXS5IyMzMVHR2tsmXLKn/+/KpRo4a++eYbh+V//PFHPfjgg/L09FSjRo00bdo02Ww2JSUlSbr+rX2TJk1S+fLl5e7urkqVKmn69OkO8202m/7zn//o2WefVYECBfTggw/qxx9/vGPHAADgPAQpAMA9b/v27Vq7dq3c3d0lSdHR0friiy80efJk7dixQ3369NHLL7+sFStWSJISEhLUunVrtWrVSlu2bFG3bt30zjvv3HQbc+bM0Ztvvql+/fpp+/bt6tatm1599VUtX77cod+wYcPUpk0bbd26VS1atFC7du10+vTpO7PjAACnsRljjLOLAADAio4dO+rLL7+Up6en0tPTlZqaKhcXF3399dd68skn5efnpyVLlig0NNS+TOfOnXXhwgXNnDlT//jHPzRv3jxt27bNPn/QoEF6//33debMGfn6+iomJka9e/e2X6Fq0KCBqlSpoilTptiXadOmjc6fP6958+ZJ+uuK1KBBg/Tuu+9Kks6fP6+CBQtq/vz5atas2V04MgCAu4VnpAAA96RGjRpp0qRJOn/+vMaMGaN8+fIpMjJSO3bs0IULF9SkSROH/mlpaapZs6Ykac+ePapTp47D/EceeeSm29u1a5e6du3q0NagQQONGzfOoa169er2f3t5ecnb21snT560vH8AgNyNIAUAuCd5eXmpQoUKkqTPP/9cNWrU0GeffaaqVatKkubNm6cHHnjAYRkPD487Xpebm5vDtM1mU2Zm5h3fLgDg7iJIAQDueS4uLvrnP/+pvn37au/evfLw8NDhw4fVsGHD6/avVKmSfv75Z4e2DRs23HQbwcHBWrNmjTp06GBvW7NmjUJCQm5/BwAA9xyCFADgvvD888/r7bff1ieffKK33npLffr0UWZmph599FElJydrzZo18vb2VocOHdStWzeNHj1aAwYMUKdOnbR582bFxMRI+usK0vW8/fbbatOmjWrWrKnw8HD99NNP+u6777RkyZK7uJcAgNyCIAUAuC/ky5dPPXr00MiRI5WQkKBixYopOjpav/32m3x9ffXwww/rn//8pySpbNmy+uabb9SvXz+NGzdOoaGheuedd9S9e/cb3v7XqlUrjRs3Th9++KHefPNNlS1bVlOnTlVYWNhd3EsAQG7BqH0AAEh6//33NXnyZB05csTZpQAA7gFckQIA5EkTJ05UnTp1VKRIEa1Zs0YffPCBevTo4eyyAAD3CIIUACBP2rdvn9577z2dPn1apUqVUr9+/TRw4EBnlwUAuEdwax8AAAAAWOTi7AIAAAAA4F5DkAIAAAAAiwhSAAAAAGARQQoAAAAALCJIAQAAAIBFBCkAAAAAsIggBQAAAAAWEaQAAAAAwKL/B1QrrzNcCChPAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=(10,6))\n", + "sns.barplot(x='Region', y='Count', data=total_claim_map, legend=False, palette='muted', hue='Region')\n", + "\n", + "plt.title('Total Count of Claims by Region')\n", + "plt.ylabel('Count')\n", + "plt.xlabel('Region')\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/python/requirements.txt b/python/requirements.txt index b705adb..b0afa50 100644 --- a/python/requirements.txt +++ b/python/requirements.txt @@ -1 +1,11 @@ -pytest==7.2.2 \ No newline at end of file +pytest==7.2.2 + +numpy==1.26.0 + +pandas==1.3.5 + +matplotlib==3.6.0 + +seaborn==0.13.0 + +flask==3.0.0 \ No newline at end of file diff --git a/python/simple_data_tool.py b/python/simple_data_tool.py index f57ad2f..faa7074 100644 --- a/python/simple_data_tool.py +++ b/python/simple_data_tool.py @@ -1,10 +1,12 @@ +# ------------------------------------ Package Installation ------------------------------------ # import json import math -from statistics import mean - +# from statistics import mean # Deprecated since we are not using it +from datetime import datetime # For formatting datetime strings +# ------------------------------------ Class Declaration ------------------------------------ # class SimpleDataTool: AGENTS_FILEPATH = 'data/sfcc_2023_agents.json' @@ -51,6 +53,7 @@ def get_claim_data(self): # Unit Test Methods +# ------------------------------------ Unit Test One ------------------------------------ # # region Test Set One def get_num_closed_claims(self): @@ -59,7 +62,10 @@ def get_num_closed_claims(self): Returns: int: number of closed claims """ - pass + claims = self.get_claim_data() + closed_claims_count = sum(1 for claim in claims if claim['status'] == 'Closed') + return closed_claims_count + def get_num_claims_for_claim_handler_id(self, claim_handler_id): """Calculates the number of claims assigned to a specific claim handler @@ -70,7 +76,11 @@ def get_num_claims_for_claim_handler_id(self, claim_handler_id): Returns: int: number of claims assigned to claim handler """ - pass + claims = self.get_claim_data() + claim_handler_claims = sum(1 for claim in claims if claim['claim_handler_assigned_id'] == claim_handler_id) + return claim_handler_claims + + def get_num_disasters_for_state(self, state): """Calculates the number of disasters for a specific state @@ -82,10 +92,15 @@ def get_num_disasters_for_state(self, state): Returns: int: number of disasters for state """ - pass + disasters = self.get_disaster_data() + state_disasters = sum(1 for disaster in disasters if disaster['state'] == state) + return state_disasters + + # endregion +# ------------------------------------ Unit Test Two ------------------------------------ # # region Test Set Two def get_total_claim_cost_for_disaster(self, disaster_id): @@ -98,8 +113,21 @@ def get_total_claim_cost_for_disaster(self, disaster_id): float | None: estimate cost of disaster, rounded to the nearest hundredths place returns None if no claims are found """ + # Assign dataset to variable + claims = self.get_claim_data() + + # Total_cost to calculate all sums of estimate_cost + total_cost = 0 + + # Looping through claims to find those related to the disaster_id + for claim in claims: + if claim['disaster_id'] == disaster_id: + # add to total cost if disaster_id matches + total_cost += claim['estimate_cost'] + + # If there is no cost, return None + return round(total_cost, 2) if total_cost > 0 else None - pass def get_average_claim_cost_for_claim_handler(self, claim_handler_id): """Gets the average estimated cost of all claims assigned to a claim handler @@ -111,8 +139,22 @@ def get_average_claim_cost_for_claim_handler(self, claim_handler_id): float | None : average cost of claims, rounded to the nearest hundredths place or None if no claims are found """ + # Initialize variables for total_cost and count + total_cost = 0 + count = 0 - pass + # Assign dataset to variable + claims = self.get_claim_data() + + # Iterate through claims, add estimate_cost if claim_handler_assigned_id matches + for claim in claims: + if claim['claim_handler_assigned_id'] == claim_handler_id: + # If the dataset matches, add to total_cost and increment count + total_cost += claim['estimate_cost'] + count += 1 + + # If count is 0, return None, else return average cost rounded to nearest hundredths place + return None if count == 0 else round(total_cost / count, 2) def get_state_with_most_disasters(self): """Returns the name of the state with the most disasters based on disaster data @@ -127,7 +169,31 @@ def get_state_with_most_disasters(self): Returns: string: single name of state """ - pass + # Create a dictionary to hold counts of disasters per state + disaster_counts = {} + + # Assign dataset to variable + disasters = self.get_disaster_data() + + # Iterate through disasters, add to dictionary for each state + for disaster in disasters: + state = disaster['state'] + disaster_counts[state] = disaster_counts.get(state, 0) + 1 + + # Initialize variables to store the state with most disasters + most_disasters_state = None + max_disasters_count = 0 + + # Sorted list of states alphabetically by using keys() method + states = sorted(disaster_counts.keys()) + + # Iterate through states and find the state with the most disasters + for state in states: + if disaster_counts[state] > max_disasters_count: + most_disasters_state = state + max_disasters_count = disaster_counts[state] + + return most_disasters_state def get_state_with_least_disasters(self): """Returns the name of the state with the least disasters based on disaster data @@ -142,7 +208,31 @@ def get_state_with_least_disasters(self): Returns: string: single name of state """ - pass + # Create a dictionary to hold counts of disasters per state + disaster_counts = {} + + # Assign dataset to variable + disasters = self.get_disaster_data() + + # Iterate through disasters, add to dictionary for each state + for disaster in disasters: + state = disaster['state'] + disaster_counts[state] = disaster_counts.get(state, 0) + 1 + + # Initialize variables to store the state with the least disasters + least_disasters_state = None + min_disasters_count = float('inf') # Set initial value to positive infinity + + # Sorted list of states alphabetically + states = sorted(disaster_counts.keys()) + + # Iterate through states and find the state with the least disasters + for state in states: + if disaster_counts[state] < min_disasters_count: + least_disasters_state = state + min_disasters_count = disaster_counts[state] + + return least_disasters_state def get_most_spoken_agent_language_by_state(self, state): """Returns the name of the most spoken language by agents (besides English) for a specific state @@ -154,7 +244,29 @@ def get_most_spoken_agent_language_by_state(self, state): string: name of language or empty string if state doesn't exist """ - pass + # Create a dictionary to hold counts of languages per state + language_counts = {} + + # Assign dataset to variable + agents = self.get_agent_data() + + # Traverse through agents data + for agent in agents: + # Check if the agent is from the specified state + if agent['state'] == state: + # Get the languages spoken by the agent excluding English + languages = [lang for lang in [agent['primary_language'], agent['secondary_language']] if lang != 'English'] + # Increment count for each language in the dictionary + for lang in languages: + language_counts[lang] = language_counts.get(lang, 0) + 1 + + # Check if no languages were found return empty string + if not language_counts: + return '' + + # Find and return the most spoken language / get function returns 0 if key not found + most_spoken_language = max(language_counts, key=language_counts.get) + return most_spoken_language def get_num_of_open_claims_for_agent_and_severity(self, agent_id, min_severity_rating): """Returns the number of open claims for a specific agent and for a minimum severity level and higher @@ -170,11 +282,39 @@ def get_num_of_open_claims_for_agent_and_severity(self, agent_id, min_severity_r -1 if severity rating out of bounds None if agent does not exist, or agent has no claims (open or not) """ - - pass + # Assign dataset to variable + agents = self.get_agent_data() + claims = self.get_claim_data() + + # Check if the severity rating is out of bounds + if min_severity_rating < 1 or min_severity_rating > 10: + return -1 + + # Check if the agent exists / any() returns True if any element of the iterable is true + agent_exists = any(agent['id'] == agent_id for agent in agents) + if not agent_exists: + return None + + + # Initialize a counter for open claims + open_claims_count = 0 + # Check every claim + for claim in claims: + # Check if the claim is assigned to the agent, is not closed, and has sufficient severity + if ( + claim['agent_assigned_id'] == agent_id and + claim['status'] != "Closed" and + claim['severity_rating'] >= min_severity_rating + ): + # If all conditions are met, increment the counter + open_claims_count += 1 + + # Return None if there are no qualifying claims + return open_claims_count if open_claims_count > 0 else None # endregion +# ------------------------------------ Unit Test Three ------------------------------------ # # region TestSetThree def get_num_disasters_declared_after_end_date(self): @@ -183,8 +323,23 @@ def get_num_disasters_declared_after_end_date(self): Returns: int: number of disasters where the declared date is after the end date """ + disasters = self.get_disaster_data() + # Initialize a counter + disasters_declared = 0 + + # Loop through each disaster in the disasters list + for disaster in disasters: + # Convert string dates to datetime.date objects + declared_date = datetime.strptime(disaster['declared_date'], '%Y-%m-%d').date() + end_date = datetime.strptime(disaster['end_date'], '%Y-%m-%d').date() + + # Check if declared_date is greater than end_date and increment the counter if true + if declared_date > end_date: + disasters_declared += 1 + + return disasters_declared + - pass def build_map_of_agents_to_total_claim_cost(self): """Builds a map of agent and their total claim cost @@ -197,8 +352,22 @@ def build_map_of_agents_to_total_claim_cost(self): Returns: dict: key is agent id, value is total cost of claims associated to the agent """ + # Assign dataset to variable + claims = self.get_claim_data() + + # Initialize a dictionary to store the total cost of claims per agent + agent_costs = {agent_id: 0 for agent_id in range(1, 101)} + + # Loop through each claim + for claim in claims: + agent_id = claim["agent_assigned_id"] # Get the agent id + cost = claim["estimate_cost"] # Get the cost of the claim + + # Add the cost of this claim to the total cost for this agent + agent_costs[agent_id] = round(agent_costs[agent_id] + cost, 2) + + return agent_costs - pass def calculate_disaster_claim_density(self, disaster_id): """Calculates density of a diaster based on the number of claims and impact radius @@ -212,16 +381,33 @@ def calculate_disaster_claim_density(self, disaster_id): Returns: float: density of claims to disaster area, rounded to the nearest thousandths place - None if disaster does not exist + None if disaster does not exist """ - pass + disaster = next((d for d in self.get_disaster_data() if d['id'] == disaster_id), None) + + if not disaster: + return None + + # Calculate disaster impact area + radius = disaster['radius_miles'] + disaster_area = math.pi * (radius ** 2) + + # Count claims associated with this disaster + num_claims = sum(1 for claim in self.get_claim_data() if claim['disaster_id'] == disaster_id) + + # Compute claim density + density = num_claims / disaster_area + + return round(density, 5) + # endregion +# ------------------------------------ Unit Test Four ------------------------------------ # # region TestSetFour def get_top_three_months_with_highest_num_of_claims_desc(self): - """Gets the top three months with the highest total claim cost + """Gets the top three months with the highest total claims Hint: Month should be full name like 01 is January and 12 is December @@ -231,7 +417,107 @@ def get_top_three_months_with_highest_num_of_claims_desc(self): Returns: list: three strings of month and year, descending order of highest claims """ + + # Dictionary to store the total cost of claims per month + monthly_costs = {} + + # Assign dataset to variable + claims = self.get_claim_data() + + # Convert disasters list to a dictionary for O(1) lookups + disasters_dict = {disaster['id']: disaster for disaster in self.get_disaster_data()} + + # Loop through each claim + for claim in claims: + disaster_id = claim['disaster_id'] + disaster = disasters_dict.get(disaster_id) - pass + if disaster: + claim_date = datetime.strptime(disaster['declared_date'], '%Y-%m-%d') + month_year = claim_date.strftime('%B %Y') + # Add the cost of this claim to the monthly total + monthly_costs[month_year] = monthly_costs.get(month_year, 0) + 1 + + # Get the top three months by total claim cost + top_three_months = sorted(monthly_costs.keys(), key=lambda month: monthly_costs[month], reverse=True)[:3] + + return top_three_months + # endregion + +# ------------------------------------ Nice to Have! ------------------------------------ # + + # This functions maps out each regional disaster by type and counts the number of each type + def get_regional_disaster_map(self):\ + + # Assign dataset to variable + disasters = self.get_disaster_data() + + # Initialize a dictionary to store disaster types per region + regional_disaster_map = { + 'west': {}, + 'midwest': {}, + 'south': {}, + 'northeast': {} + } + + # Helper function to get the region of a given state + def get_region(state): + for region, states in self.REGION_MAP.items(): + if state in states.split(','): + return region + return None + + # Accumulate disaster types per region + for disaster in disasters: + region = get_region(disaster['state']) + if region: + disaster_type = disaster['type'] + if disaster_type in regional_disaster_map[region]: + regional_disaster_map[region][disaster_type] += 1 + else: + regional_disaster_map[region][disaster_type] = 1 + + return regional_disaster_map + + + # This functions maps out each regional claims by type and counts the total claims of each type + def get_total_claims_per_regional_disaster(self): + + # Assign dataset to variable + claims = self.get_claim_data() + disasters = self.get_disaster_data() + + # Map disasters by id for quick lookup + disaster_map = {disaster['id']: disaster for disaster in disasters} + + # Initialize the result data structure + regional_claims = {region: {} for region in self.REGION_MAP.keys()} + + # Helper function to get the region of a state + def get_region(state): + for region, states in self.REGION_MAP.items(): + if state in states: + return region + return None # or 'unknown' + + # Iterate through each claim, map to disaster, and update counts + for claim in claims: + # Map claim to disaster using disaster_id + disaster = disaster_map.get(claim['disaster_id']) + + # Ensure disaster exists + if disaster: + state = disaster['state'] + region = get_region(state) + + # Ensure region is found and update the counts + if region is not None: + if state in regional_claims[region]: + regional_claims[region][state] += 1 + else: + regional_claims[region][state] = 1 + + # Return the resulting data structure + return regional_claims