diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..06e1be7
Binary files /dev/null and b/.DS_Store differ
diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/cloud-computing-predict.iml b/.idea/cloud-computing-predict.iml
new file mode 100644
index 0000000..d0876a7
--- /dev/null
+++ b/.idea/cloud-computing-predict.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/csv-plugin.xml b/.idea/csv-plugin.xml
new file mode 100644
index 0000000..39c0600
--- /dev/null
+++ b/.idea/csv-plugin.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..d56657a
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..c5e8517
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..50793d9
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/img/me.jpg b/assets/img/me.jpg
new file mode 100644
index 0000000..bbf3305
Binary files /dev/null and b/assets/img/me.jpg differ
diff --git a/assets/img/portfolio/BI.jpeg b/assets/img/portfolio/BI.jpeg
new file mode 100644
index 0000000..f619f79
Binary files /dev/null and b/assets/img/portfolio/BI.jpeg differ
diff --git a/assets/img/portfolio/BI2.jpeg b/assets/img/portfolio/BI2.jpeg
new file mode 100644
index 0000000..c5c48c5
Binary files /dev/null and b/assets/img/portfolio/BI2.jpeg differ
diff --git a/assets/img/portfolio/data-warehouse-business-intelligenc-260nw-275396558.jpeg b/assets/img/portfolio/data-warehouse-business-intelligenc-260nw-275396558.jpeg
new file mode 100644
index 0000000..fab1033
Binary files /dev/null and b/assets/img/portfolio/data-warehouse-business-intelligenc-260nw-275396558.jpeg differ
diff --git a/assets/img/portfolio/data-warehousing.jpeg b/assets/img/portfolio/data-warehousing.jpeg
new file mode 100644
index 0000000..eb62241
Binary files /dev/null and b/assets/img/portfolio/data-warehousing.jpeg differ
diff --git a/assets/img/portfolio/dataengin.jpeg b/assets/img/portfolio/dataengin.jpeg
new file mode 100644
index 0000000..518d32b
Binary files /dev/null and b/assets/img/portfolio/dataengin.jpeg differ
diff --git a/assets/img/portfolio/datawarehouse.jpeg b/assets/img/portfolio/datawarehouse.jpeg
new file mode 100644
index 0000000..0265ced
Binary files /dev/null and b/assets/img/portfolio/datawarehouse.jpeg differ
diff --git a/assets/img/portfolio/pipeline.jpeg b/assets/img/portfolio/pipeline.jpeg
new file mode 100644
index 0000000..fad8fe8
Binary files /dev/null and b/assets/img/portfolio/pipeline.jpeg differ
diff --git a/assets/mail/contact_me.js b/assets/mail/contact_me.js
index 9273d67..16d335c 100644
--- a/assets/mail/contact_me.js
+++ b/assets/mail/contact_me.js
@@ -24,7 +24,7 @@ $(function () {
var json = {name: name, phone: phone, email: email, message: message}
$.ajax({
// --- CHANGE THIS LINE TO YOUR OWN API GATEWAY --------
- url: "{Insert your own AWS API Gateway Endpoint URL here}",
+ url: "https://98005irfla.execute-api.eu-west-1.amazonaws.com/rootfunction",
// ------------------------------------------------------
type: "POST",
data: JSON.stringify(json),
diff --git a/index.html b/index.html
index d6bb6d6..8b67daa 100644
--- a/index.html
+++ b/index.html
@@ -8,7 +8,7 @@
-
Explore Data Science Academy - Serverless Student Portfolio Web page
+ Thulasizwe Ntsele - Serverless Student Portfolio Web page
@@ -41,12 +41,12 @@
-
+
-
Cloud Computing Predict - Project Portfolio
+
Thulasizwe Ntsele Cloud Computing - Project Portfolio
@@ -57,7 +57,7 @@
Cloud Computing Predict - Proje
- Machine Learning - Time Series - Dashboarding
+
Data Warehouse - Data Engineering - Business Intelligence - Predictive Models
@@ -82,7 +82,7 @@
-
+
@@ -240,9 +240,9 @@
Location
- 12th Floor, Rennie House, 19 Ameshoff St
+ 3A Violet Close
- Johannesburg, 2001
+ Cape Town, 7441
@@ -261,9 +261,9 @@ Around the Web
-
Explore AI Cloud Computing Predict
+
Thulasizwe AI Cloud Computing Project
- Create your own data science portfolio with an intelligent NPL bot handling enquiries for you.
+ Data is the future off all organisation therefore it must be treated with respect.
@@ -294,7 +294,7 @@ Explore AI Cloud Computing Predict
-
Credit Fraud Detector
+
Data Warehouse
@@ -303,10 +303,10 @@
+
-
Built a credit card fraud detection system for one of South Africas big four banks
+
Build an electronic method of organizing, analyzing, and reporting information
Close Window
@@ -335,7 +335,7 @@
- Rock Formation Classifier
+ DATA ENGINEERING
@@ -344,10 +344,10 @@
+
-
Designed and built a PoC rock formation density classifier to aid engineers in the preliminary building design phase
+
A data pipeline is a set of actions that ingest raw data from disparate sources and move the data to a destination for storage and analysis. A pipeline also may include filtering and features that provide resiliency against failure
Close Window
@@ -376,7 +376,7 @@
- Search for Dark Matter Hints with Machine Learning
+ Business Intelligence
@@ -385,10 +385,10 @@
+
-
This project covers several cases of detector design optimization in high energy physics experiments using Bayesian optimization with Gaussian processes
+
Business intelligence (BI) is a technology-driven process for analyzing data and delivering actionable information that helps executives, managers and workers make informed business decisions.
Close Window
diff --git a/student_solution_files/DB.py b/student_solution_files/DB.py
new file mode 100644
index 0000000..c31c9ba
--- /dev/null
+++ b/student_solution_files/DB.py
@@ -0,0 +1,176 @@
+
+"""
+ Lambda function that decodes and writes data from your portfolio website to your DynamoDB database.
+
+ Author: Explore Data Science Academy.
+
+ Note:
+ ---------------------------------------------------------------------
+ The contents of this file should be added to a AWS Lambda function
+ created as part of the EDSA Cloud-Computing Predict.
+ For further guidance around this process, see the README instruction
+ file which sits at the root of this repo.
+ ---------------------------------------------------------------------
+
+"""
+
+# Lambda dependencies
+import boto3 # Python AWS SDK
+import json # Used for handling API-based data.
+import base64 # Needed to decode the incoming POST
+import random
+import uuid
+from botocore.exceptions import ClientError
+
+#CREATE_RAW_PATH = "/contactme"
+
+def lambda_handler(event, context):
+ if event["rawPath"]== "/contactme":
+ # Perform JSON data decoding
+ body_enc = json.loads(event['body'])
+ body_enc = event['body']
+ dec_dict = json.loads(base64.b64decode(body_enc))
+
+ table.put_item(Item={'ResponsesID': rid, # <--- Insert the correct variable
+ 'Name': dec_dict['name'], # <--- Insert the correct variable
+ 'Email': dec_dict['email'], # <--- Insert the correct variable
+ 'Cell': dec_dict['phone'], # <--- Insert the correct variable
+ 'Message': dec_dict['message'] # <--- Insert the correct variable
+ })
+
+ # --- Write to dynamodb ---
+
+ # ** Create a variable that can take a random value between 1 and 1 000 000 000.
+ # This variable will be used as our key value i.e the ResponsesID and should be of type integer.
+ # It is important to note that the ResponseID i.e. the rid variable, should take
+ # on a unique value to prevent errors when writing to DynamoDB. **
+
+ # --- Insert your code here ---
+ rid =random.randint(1,1000000)
+ # rid = None # <--- Replace this value with your code.
+ # -----------------------------
+
+ # ** Instantiate the DynamoDB service with the help of the boto3 library **
+
+ # --- Insert your code here ---
+ dynamodb = boto3.resource('dynamodb')#,region_name='eu-west-1') # <--- Replace this value with your code.
+ # -----------------------------
+
+ # Instantiate the table. Remember pass the name of the DynamoDB table created in step 4
+ table = dynamodb.Table('PredictDB')
+
+ # ** Write the responses to the table using the put_item method. **
+
+ # Complete the below code so that the appropriate
+ # incoming data is sent to the matching column in your DynamoDB table
+ # --- Insert your code here ---
+ """db_response = table.put_item(Item={'ResponsesID': rid, # <--- Insert the correct variable
+ 'Name': dec_dict['name'], # <--- Insert the correct variable
+ 'Email': dec_dict['email'], # <--- Insert the correct variable
+ 'Cell': dec_dict['phone'], # <--- Insert the correct variable
+ 'Message': dec_dict['message'] # <--- Insert the correct variable
+ })
+ # -----------------------------
+ """
+ #email_text = 'Hello world'
+
+ # ** SES Functionality **
+
+ # Replace sender@example.com with your "From" address.
+ # This address must be verified with Amazon SES.
+ # --- Insert your code here ---
+ """"SENDER = 'ntseleta@gmail.com'
+ ses.send_mail(
+ Source='ntseleta@gmail.com',
+ Destination={
+ 'ToAddresses': [
+ 'ntselet@hotmail.com',
+ ]
+ },
+ Message={
+ 'Subject': {
+ 'Data': 'Predict',
+ 'Charset': 'UTF-8'
+ },
+ 'Body': {
+ 'Text': {
+ 'Data': email_text,
+ 'Charset': 'UTF-8'
+ },
+
+ }
+ },
+ )
+ # -----------------------------
+
+ # Replace recipient@example.com with a "To" address. If your account
+ # is still in the sandbox, this address must be verified.
+ # --- Insert your code here ---
+ RECIPIENT = 'ntseleta@gmail.com'
+ # -----------------------------
+
+ # The subject line for the email.
+ # --- DO NOT MODIFY THIS CODE ---
+ SUBJECT = f"Data Science Portfolio Project Website - Hello {dec_dict['name']}"
+ # -------------------------------
+
+ # The email body for recipients with non-HTML email clients
+ BODY_TEXT = (email_text)
+
+ # The character encoding for the email.
+ CHARSET = "UTF-8"
+
+ # Create a new SES service resource
+ client = boto3.client('ses')
+
+ # Try to send the email.
+ try:
+ # Provide the contents of the email.
+ ses_response = client.send_email(
+ Destination={
+ 'ToAddresses': [
+ RECIPIENT,
+ # 'edsa.predicts@explore-ai.net', # <--- Uncomment this line once you have successfully tested your predict end-to-end
+ ],
+ },
+ Message={
+ 'Body': {
+
+ 'Text': {
+ 'Charset': CHARSET,
+ 'Data': BODY_TEXT,
+ },
+ },
+ 'Subject': {
+ 'Charset': CHARSET,
+ 'Data': SUBJECT,
+ },
+ },
+ Source=SENDER,
+ )
+
+ # Display an error if something goes wrong.
+ except ClientError as e:
+ print(e.response['Error']['Message'])
+ else:
+ print("Email sent! Message ID:"),
+ print(ses_response['MessageId'])
+
+
+ # ** Create a response object to inform the website
+ # that the workflow executed successfully. **
+ lambda_response = {
+ 'statusCode': 200,
+ 'body': json.dumps({
+ 'Name': dec_dict['Name'],
+ 'Email': dec_dict['Email'],
+ 'Cell': dec_dict['Phone_number'],
+ 'Message': dec_dict['Message'],
+ 'DB_response': db_response
+ })
+ }"""
+
+ return lambda_response
+
+
+
diff --git a/student_solution_files/main.py b/student_solution_files/main.py
new file mode 100644
index 0000000..de9e0e6
--- /dev/null
+++ b/student_solution_files/main.py
@@ -0,0 +1,367 @@
+"""
+ Final AWS Lambda function skeleton.
+
+ Author: Explore Data Science Academy.
+
+ Note:
+ ---------------------------------------------------------------------
+ The contents of this file should be added to a AWS Lambda function
+ created as part of the EDSA Cloud-Computing Predict.
+ For further guidance around this process, see the README instruction
+ file which sits at the root of this repo.
+ ---------------------------------------------------------------------
+
+"""
+
+# Lambda dependencies
+import boto3 # Python AWS SDK
+import json # Used for handling API-based data.
+import base64 # Needed to decode the incoming POST data
+import numpy as np # Array manipulation
+import random
+rid = random
+from botocore.exceptions import ClientError # Catch errors on client side
+
+
+# <<< You will need to add additional libraries to complete this script >>>
+
+# ** Insert key phrases function **
+def key_phrase_finder(list_of_important_phrases, list_of_extracted_phrases):
+ listing = []
+ PhraseChecker = None
+
+ res = str(list_of_extracted_phrases).split()
+
+ for important_word in list_of_important_phrases:
+ names = res
+ names2 = [word for word in names if important_word in word]
+ isnot_empty = np.array(names2).size > 0
+
+ if isnot_empty == True:
+ listing = np.append(listing, names2)
+
+ else:
+ listing = listing
+
+ if np.array(listing).size > 0:
+ PhraseChecker = True
+
+ else:
+ PhraseChecker = False
+
+ # -----------------------------
+
+ # ** Insert sentiment extraction function **
+
+ def find_max_sentiment(Comprehend_Sentiment_Output):
+
+ sentiment_score = 0
+
+ if Comprehend_Sentiment_Output['Sentiment'] == 'POSITIVE':
+ sentiment_score = Comprehend_Sentiment_Output['SentimentScore']['Positive']
+
+ elif Comprehend_Sentiment_Output['Sentiment'] == 'NEGATIVE':
+ sentiment_score = Comprehend_Sentiment_Output['SentimentScore']['Negative']
+
+ elif Comprehend_Sentiment_Output['Sentiment'] == 'NEUTRAL':
+ sentiment_score = Comprehend_Sentiment_Output['SentimentScore']['Neutral']
+
+ else:
+ sentiment_score = Comprehend_Sentiment_Output['SentimentScore']['Mixed']
+
+ print(sentiment_score, Comprehend_Sentiment_Output['Sentiment'])
+
+ return Comprehend_Sentiment_Output['Sentiment'], sentiment_score
+
+
+# -----------------------------
+
+# ** Insert email responses function **
+def email_response(name, critical_phrase_list, list_of_extracted_phrases, AWS_Comprehend_Sentiment_Dump):
+ # Function Constants
+ SENDER_NAME = 'Thulasizwe'
+
+ # --- Check for the sentiment of the message and find dominant sentiment score ---
+ Sentiment_finder = find_max_sentiment(AWS_Comprehend_Sentiment_Dump)
+ overwhelming_sentiment = Sentiment_finder[0]
+ overwhelming_sentiment_score = Sentiment_finder[1]
+
+ # --- Check for article critical phrases ---
+ Phrase_Matcher_Article = key_phrase_finder(critical_phrase_list, list_of_extracted_phrases)
+ Matched_Phrases_Article = Phrase_Matcher_Article[0]
+ Matched_Phrases_Checker_Article = Phrase_Matcher_Article[1]
+
+ # --- Check for project phrases ---
+ Phrase_Matcher_Project = key_phrase_finder(['github', 'git', 'Git',
+ 'GitHub', 'projects',
+ 'portfolio', 'Portfolio'],
+ list_of_extracted_phrases)
+ Matched_Phrases_Project = Phrase_Matcher_Project[0]
+ Matched_Phrases_Checker_Project = Phrase_Matcher_Project[1]
+
+ # --- Check for C.V phrases ---
+ Phrase_Matcher_CV = key_phrase_finder(['C.V', 'resume', 'Curriculum Vitae',
+ 'Resume', 'CV'],
+ list_of_extracted_phrases)
+ Matched_Phrases_CV = Phrase_Matcher_CV[0]
+ Matched_Phrases_Checker_CV = Phrase_Matcher_CV[1]
+
+ # --- Generate standard responses ---
+ # === DO NOT MODIFY THIS TEXT FOR THE PURPOSE OF PREDICT ASSESSMENT ===
+ Greetings_text = f'Good day {name},'
+
+ CV_text = 'I see that you mentioned my C.V in your message. \
+ I am happy to forward you my C.V in response. \
+ If you have any other questions or C.V related queries please do get in touch. '
+
+ Project_Text = 'The projects I listed on my site only include \
+ the ones not running in production. I have \
+ several other projects that might interest you.'
+
+ Article_Text = 'In your message you mentioned my blog posts and data science articles. \
+ I have several other articles published in academic journals. \
+ Please do let me know if you are interested - I am happy to forward them to you'
+
+ Negative_Text = f'I see that you are unhappy in your response. \
+ Can we please set up a session to discuss why you are not happy, \
+ be it with the website, my personal projects or anything else. \
+ \n\nLooking forward to our discussion. \n\nKind Regards, \n\nMy Name'
+
+ Neutral_Text = f'Thank you for your email. Let me know if you need any additional information.\
+ \n\nKind Regards, \n\n{SENDER_NAME}'
+
+ Farewell_Text = f'Thank you for your email.\n\nIf there is anything else I can assist \
+ you with please let me know and I will set up a meeting for us to meet\
+ in person.\n\nKind Regards, \n\n{SENDER_NAME}'
+ # =====================================================================
+
+ # --- Email Logic ---
+ if overwhelming_sentiment == 'POSITIVE':
+ if ((Matched_Phrases_Checker_CV == True) & \
+ (Matched_Phrases_Checker_Article == True) & \
+ (Matched_Phrases_Checker_Project == True)):
+
+ mytuple = (Greetings_text, CV_text, Article_Text, Project_Text, Farewell_Text)
+ Text = "\n \n".join(mytuple)
+
+ elif ((Matched_Phrases_Checker_CV == True) & \
+ (Matched_Phrases_Checker_Article == False) & \
+ (Matched_Phrases_Checker_Project == True)):
+
+ mytuple = (Greetings_text, CV_text, Project_Text, Farewell_Text)
+ Text = "\n \n".join(mytuple)
+
+ elif ((Matched_Phrases_Checker_CV == True) & \
+ (Matched_Phrases_Checker_Article == False) & \
+ (Matched_Phrases_Checker_Project == False)):
+
+ mytuple = (Greetings_text, CV_text, Farewell_Text)
+ Text = "\n \n".join(mytuple)
+
+ elif ((Matched_Phrases_Checker_CV == False) & \
+ (Matched_Phrases_Checker_Article == True) & \
+ (Matched_Phrases_Checker_Project == False)):
+
+ mytuple = (Greetings_text, Article_Text, Farewell_Text)
+ Text = "\n \n".join(mytuple)
+
+ elif ((Matched_Phrases_Checker_CV == False) & \
+ (Matched_Phrases_Checker_Article == False) & \
+ (Matched_Phrases_Checker_Project == False)):
+
+ mytuple = (Greetings_text, Farewell_Text)
+ Text = "\n \n".join(mytuple)
+
+ elif ((Matched_Phrases_Checker_CV == False) & \
+ (Matched_Phrases_Checker_Article == False) & \
+ (Matched_Phrases_Checker_Project == True)):
+
+ mytuple = (Greetings_text, Project_Text, Farewell_Text)
+ Text = "\n \n".join(mytuple)
+
+ elif ((Matched_Phrases_Checker_CV == True) & \
+ (Matched_Phrases_Checker_Article == True) & \
+ (Matched_Phrases_Checker_Project == False)):
+
+ mytuple = (Greetings_text, CV_text, Article_Text, Farewell_Text)
+ Text = "\n \n".join(mytuple)
+
+ else:
+ mytuple = (Greetings_text, Project_Text, Article_Text, Farewell_Text)
+ Text = "\n \n".join(mytuple)
+
+ elif overwhelming_sentiment == 'NEGATIVE':
+ mytuple = (Greetings_text, Negative_Text)
+ Text = "\n \n".join(mytuple)
+
+ else:
+ mytuple = (Greetings_text, Neutral_Text)
+ Text = "\n \n".join(mytuple)
+
+ return Text
+
+
+# -----------------------------
+
+# Lambda function orchestrating the entire predict logic
+def lambda_handler(event, context):
+ # Perform JSON data decoding
+ body_enc = event['body']
+ dec_dict = json.loads(base64.b64decode(body_enc))
+
+ # ** Insert code to write to dynamodb **
+ # <<< Ensure that the DynamoDB write response object is saved
+ # as the variable `db_response` >>>
+ rid = np.random.randint(1, 1000000000) # <--- Replace this value with your code.
+ # -----------------------------
+
+ # ** Instantiate the DynamoDB service with the help of the boto3 library **
+
+ # --- Insert your code here ---
+ dynamodb = boto3.resource('dynamodb', region_name='eu-west-1') # <--- Replace this value with your code.
+ # -----------------------------
+
+ # Instantiate the table. Remember pass the name of the DynamoDB table created in step 4
+ table = dynamodb.Table('PredictDB')
+
+ # Do not change the name of this variable
+ db_response = table.put_item(Item={'ResponsesID': rid, # <--- Insert the correct variable
+ 'Name': dec_dict['name'], # <--- Insert the correct variable
+ 'Email': dec_dict['email'], # <--- Insert the correct variable
+ 'Cell': dec_dict['phone'], # <--- Insert the correct variable
+ 'Message': dec_dict['message'] # <--- Insert the correct variable
+ })
+ # -----------------------------
+
+ # --- Amazon Comprehend ---
+ comprehend = boto3.client(service_name='comprehend')
+
+ # --- Insert your code here ---
+ enquiry_text = client.batch_detect_dominant_language(
+ TextList=[
+ 'Thank you line 243',
+ ]
+ ) # <--- Insert code to place the website message into this variable
+ # -----------------------------
+
+ # --- Insert your code here ---
+ sentiment = comprehend.detect_sentiment(
+ Text=dec_dict[‘message’], LanguageCode = 'en') # <---Insert code to get the sentiment with AWS comprehend
+ # -----------------------------
+
+ # --- Insert your code here ---
+ key_phrases = key_phrases = comprehend.detect_key_phrases(Text=comments, LanguageCode='en')
+ key_phrases = comprehend.detect_key_phrases(Text=comments, LanguageCode='en')
+ # <--- Insert code to get the key phrases with AWS comprehend
+ # -----------------------------
+
+ # Get list of phrases in numpy array
+ phrase = []
+ for i in range(0, len(key_phrases['KeyPhrases']) - 1):
+ phrase = np.append(phrase, key_phrases['KeyPhrases'][i]['Text'])
+
+ # ** Use the `email_response` function to generate the text for your email response **
+ # <<< Ensure that the response text is stored in the variable `email_text` >>>
+ # --- Insert your code here ---
+ # Do not change the name of this variable
+ email_text = 'Hello there! Thank you for your message'
+
+ # -----------------------------
+
+ # ** SES Functionality **
+
+ # Insert code to send an email, using AWS SES, with the above defined
+ # `email_text` variable as it's body.
+ # <<< Ensure that the SES service response is stored in the variable `ses_response` >>>
+ # --- Insert your code here ---
+ SENDER = 'ntselet@hotmail.com'
+ # -----------------------------
+
+ # Replace recipient@example.com with a "To" address. If your account
+ # is still in the sandbox, this address must be verified.
+ # --- Insert your code here ---
+ RECIPIENT = 'ntselet@gmail.com'
+ # -----------------------------
+
+ AWS_REGION = "eu-west-1"
+
+ # The subject line for the email.
+ # --- DO NOT MODIFY THIS CODE ---
+ SUBJECT = f"Data Science Portfolio Project Website - Hello {dec_dict['name']}"
+ # -------------------------------
+
+ # The email body for recipients with non-HTML email clients
+ BODY_TEXT = (email_text)
+
+ # The character encoding for the email.
+ CHARSET = "UTF-8"
+
+ # Create a new SES service resource
+ client = boto3.client('ses', region_name='eu-west-1')
+
+ # Do not change the name of this variable
+ # ses_response = None
+ try:
+ # Provide the contents of the email.
+ ses_response = client.send_email(
+ Destination={
+ 'ToAddresses': [
+ RECIPIENT, 'ntseleta@gmail.com'
+ # 'edsa.predicts@explore-ai.net', # <--- Uncomment this line once you have successfully tested your predict end-to-end
+ ],
+ },
+ Message={
+ 'Body': {
+
+ 'Text': {
+ 'Charset': CHARSET,
+ 'Data': BODY_TEXT,
+ },
+ },
+ 'Subject': {
+ 'Charset': CHARSET,
+ 'Data': SUBJECT,
+ },
+ },
+ Source=SENDER,
+
+ )
+
+# Display an error if something goes wrong.
+except ClientError as e:
+print(e.response['Error']['Message'])
+else:
+print("Email sent! Message ID:"),
+print(ses_response['MessageId'])
+
+# ...
+
+# Do not modify the email subject line
+SUBJECT = f"Data Science Portfolio Project Website - Hello {dec_dict['name']}"
+
+# -----------------------------
+
+
+# ** Create a response object to inform the website that the
+# workflow executed successfully. Note that this object is
+# used during predict marking and should not be modified.**
+# --- DO NOT MODIFY THIS CODE ---
+lambda_response = {
+ 'statusCode': 200,
+ 'body': json.dumps({
+ 'Name': dec_dict['name'],
+ 'Email': dec_dict['email'],
+ 'Cell': dec_dict['phone'],
+ 'Message': dec_dict['message'],
+ 'DB_response': db_response,
+ 'SES_response': ses_response,
+ 'Email_message': email_text
+ })
+}
+# -----------------------------
+
+return lambda_response
+
+"""
+Your module description
+"""
diff --git a/student_solution_files/predict_detail_submission_template.csv b/student_solution_files/predict_detail_submission_template.csv
index 8c70fbe..d400973 100644
--- a/student_solution_files/predict_detail_submission_template.csv
+++ b/student_solution_files/predict_detail_submission_template.csv
@@ -1,2 +1,2 @@
Name,Surname,Website_URL,API_Gateway_URL
-Dorah,Explorer,https://sample-website-url.com,https://sample-api-url.com
\ No newline at end of file
+Thulasizwe,Ntsele,https://predict.d3n2uqpd60ztr.amplifyapp.com/,https://98005irfla.execute-api.eu-west-1.amazonaws.com/rootfunction
\ No newline at end of file
diff --git a/student_solution_files/step7.py b/student_solution_files/step7.py
new file mode 100644
index 0000000..a9f0e0a
--- /dev/null
+++ b/student_solution_files/step7.py
@@ -0,0 +1,162 @@
+"""
+ Initial AWS Lambda function is used to decode POST-request data received from the
+ student portfolio website.
+
+ Author: Explore Data Science Academy.
+ Note:
+ ---------------------------------------------------------------------
+ The contents of this file should be added to a AWS Lambda function
+ created as part of the EDSA Cloud-Computing Predict.
+ For further guidance around this process, see the README instruction
+ file which sits at the root of this repo.
+ ---------------------------------------------------------------------
+"""
+
+# Lambda dependencies
+import boto3 # Python AWS SDK
+import json # Used for handling API-based data.
+import base64 # Needed to decode the incoming POST data
+import random #Used to generate random numbers
+from botocore.exceptions import ClientError # Catch errors on client side
+import numpy as np #array manipulation
+
+def lambda_handler(event, context):
+
+ # Perform JSON data decoding
+ body_enc = json.loads(event['body'])
+ #body_enc = event['body']
+ dec_dict = json.loads(base64.b64decode(body_enc))
+
+ # Note that all of the POST data from our website form can now
+ # be accessed via the `dec_dict` dictionary object.
+ # For example, if we entered the name field as 'Student_name on the website' :
+ # >>> dec_dict['name']
+ # 'Student_name'
+
+ # Create a response object to tell the website that the form data
+ # was successfully received. We use the contents of the decoded JSON dictionary
+ # to create this response. As the predict progresses, we'll include
+ # more information about the AWS services we will invoke.
+
+
+# --- Write to dynamodb ---
+
+ # ** Create a variable that can take a random value between 1 and 1 000 000 000.
+ # This variable will be used as our key value i.e the ResponsesID and should be of type integer.
+ # It is important to note that the ResponseID i.e. the rid variable, should take
+ # on a unique value to prevent errors when writing to DynamoDB. **
+
+ # --- Insert your code here ---
+ rid = np.random.randint(1,1000000000) # <--- Replace this value with your code.
+ # -----------------------------
+
+ # ** Instantiate the DynamoDB service with the help of the boto3 library **
+
+ # --- Insert your code here ---
+ dynamodb = boto3.resource('dynamodb', region_name='eu-west-1') # <--- Replace this value with your code.
+ # -----------------------------
+
+ # Instantiate the table. Remember pass the name of the DynamoDB table created in step 4
+ table = dynamodb.Table('PredictDB')
+
+ # ** Write the responses to the table using the put_item method. **
+
+ # Complete the below code so that the appropriate
+ # incoming data is sent to the matching column in your DynamoDB table
+ # --- Insert your code here ---
+ db_response = table.put_item(Item={'ResponsesID': rid, # <--- Insert the correct variable
+ 'Name': dec_dict['name'], # <--- Insert the correct variable
+ 'Email': dec_dict['email'], # <--- Insert the correct variable
+ 'Cell': dec_dict['phone'], # <--- Insert the correct variable
+ 'Message': dec_dict['message'] # <--- Insert the correct variable
+ })
+ # -----------------------------
+
+ # ** Create a response object to inform the website
+ # that the workflow executed successfully. **
+
+ email_text = 'Hello there! Thank you for your message'
+
+ # ** SES Functionality **
+
+ # Replace sender@example.com with your "From" address.
+ # This address must be verified with Amazon SES.
+ # --- Insert your code here ---
+ SENDER = 'ntselet@hotmail.com'
+ # -----------------------------
+
+ # Replace recipient@example.com with a "To" address. If your account
+ # is still in the sandbox, this address must be verified.
+ # --- Insert your code here ---
+ RECIPIENT = 'ntselet@gmail.com'
+ # -----------------------------
+
+ AWS_REGION = "eu-west-1"
+
+ # The subject line for the email.
+ # --- DO NOT MODIFY THIS CODE ---
+ SUBJECT = f"Data Science Portfolio Project Website - Hello {dec_dict['name']}"
+ # -------------------------------
+
+ # The email body for recipients with non-HTML email clients
+ BODY_TEXT = (email_text)
+
+ # The character encoding for the email.
+ CHARSET = "UTF-8"
+
+
+ # Create a new SES service resource
+ client = boto3.client('ses',region_name=AWS_REGION)
+
+
+ # Try to send the email.
+ try:
+ #Provide the contents of the email.
+ ses_response = client.send_email(
+ Destination={
+ 'ToAddresses': [
+ RECIPIENT,
+ # 'edsa.predicts@explore-ai.net', # <--- Uncomment this line once you have successfully tested your predict end-to-end
+ ],
+ },
+ Message={
+ 'Body': {
+
+ 'Text': {
+ 'Charset': CHARSET,
+ 'Data': BODY_TEXT,
+ },
+ },
+ 'Subject': {
+ 'Charset': CHARSET,
+ 'Data': SUBJECT,
+ },
+ },
+ Source=SENDER,
+
+ )
+
+ # Display an error if something goes wrong.
+ except ClientError as e:
+ print(e.response['Error']['Message'])
+ else:
+ print("Email sent! Message ID:"),
+ print(ses_response['MessageId'])
+
+ # ** Create a response object to inform the website
+ # that the workflow executed successfully. **
+
+ lambda_response = {
+ 'statusCode': 200,
+ 'body': json.dumps({
+ 'Name': dec_dict['name'],
+ 'Email': dec_dict['email'],
+ 'Cell': dec_dict['phone'],
+ 'Message': dec_dict['message'],
+ 'SES_response': ses_response,
+ 'Email_message': email_text,
+ 'DB_response': db_response
+ })
+ }
+
+ return lambda_response