From 6c8fe6364d0fb07847b430baac95eff3719f906f Mon Sep 17 00:00:00 2001 From: Gituto Miano Date: Tue, 30 Sep 2025 13:30:07 +0300 Subject: [PATCH 1/3] Completed Month 1 & 2 projects --- month1_student_management/student_data.py | 54 +++++++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/month1_student_management/student_data.py b/month1_student_management/student_data.py index 38ded7e..2a6456f 100644 --- a/month1_student_management/student_data.py +++ b/month1_student_management/student_data.py @@ -5,16 +5,64 @@ def add_student(): TODO: Prompt the user to enter student name, age, and grade. Append the student as a dictionary to the students list. """ - pass + name = input("Enter student name: ") + age_input = input("Enter student age: ") + grade_input = input("Enter student grade: ") + + try: + age = int(age_input) + grade = float(grade_input) + except ValueError: + print("Invalid input. Age must be an integer and grade must be a number.") + return + + student = {"name": name, "age": age, "grade": grade} + students.append(student) + print(f"{name} added successfully!\n") + def view_students(): """ TODO: Loop through the students list and print each student's info. """ - pass + if not students: + print("No students in the list.\n") + return + + for i, student in enumerate(students, start=1): + print(f"{i}. Name: {student['name']}, Age: {student['age']}, Grade: {student['grade']}") + print() # blank line + def get_average_grade(): """ TODO: Return the average grade of all students. """ - pass \ No newline at end of file + if not students: + print("No students to calculate average.\n") + return 0 + + total = sum(student["grade"] for student in students) + average = total / len(students) + return average + +# Menu loop +if __name__ == "__main__": + while True: + print("1. Add student") + print("2. View students") + print("3. Get average grade") + print("4. Exit") + choice = input("Choose an option: ") + + if choice == "1": + add_student() + elif choice == "2": + view_students() + elif choice == "3": + avg = get_average_grade() + print(f"Average grade: {avg}\n") + elif choice == "4": + break + else: + print("Invalid option. Try again.\n") \ No newline at end of file From ef29b683c532b26d649e158425a03395bde44cd9 Mon Sep 17 00:00:00 2001 From: Gituto Miano Date: Sun, 5 Oct 2025 14:04:48 +0300 Subject: [PATCH 2/3] Completed Month 1 & 2 projects --- .../report_generator.cpython-313.pyc | Bin 0 -> 1306 bytes .../python/__pycache__/utils.cpython-313.pyc | Bin 0 -> 1368 bytes month2_minimart_analysis/python/main.py | 45 ++++++++++++++ month2_minimart_analysis/python/report.json | 11 ++++ .../python/report_generator.py | 25 ++++++++ month2_minimart_analysis/python/utils.py | 20 ++++++ .../sql/create_tables.sql | 37 ++++++++++++ .../sql/customers_data.csv | 6 ++ month2_minimart_analysis/sql/insert_data.sql | 22 +++++++ month2_minimart_analysis/sql/orders_data.csv | 6 ++ .../sql/products_data.csv | 6 ++ month2_minimart_analysis/sql/queries.sql | 57 ++++++++++++++++++ 12 files changed, 235 insertions(+) create mode 100644 month2_minimart_analysis/python/__pycache__/report_generator.cpython-313.pyc create mode 100644 month2_minimart_analysis/python/__pycache__/utils.cpython-313.pyc create mode 100644 month2_minimart_analysis/python/report.json create mode 100644 month2_minimart_analysis/sql/customers_data.csv create mode 100644 month2_minimart_analysis/sql/orders_data.csv create mode 100644 month2_minimart_analysis/sql/products_data.csv diff --git a/month2_minimart_analysis/python/__pycache__/report_generator.cpython-313.pyc b/month2_minimart_analysis/python/__pycache__/report_generator.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..09ca76a4a59d35bd1d0f26df7c832e7f17c08b27 GIT binary patch literal 1306 zcmah}L2naB6rT0k>v2ek6p-nLbi0s9m8B-olF))e8&U!l3Q23T7qGNh?7`l2cXm57 z3%IAKKcH$4sBmhI^p>BpBOe^i5u{4JxpI#^bjJ2Z!Y%5P_RW0rzW3hu#_Ju-%uE4k zAKiQ1{#ys&jRKiz$7 z9M&DZrmGaW=GD3^o!l2bl>3J#b)DQOT2+(@TN~rGaUYzQJ&O}032R!$`2Skf(!cYw zKDgj$)!{9@%~3NACn;S2N_I0=a|%_b-)1RPE2;=K9Q{9a!V{f^VFl$TEYnh*od`&n z#cK4Q{S)LK^PH_A=|T?euMcD_DIJjD2@oTpZctAe~UVHh#2u3 zbVW?XBx)uN=K9TwCUOxLg;++AfZrt^W z<|c&6LB#CD8JST`V|0mBy*hSg;)gG<*BvTb)D!9Jx1vT8BFt$0=JtL2)>i$oPbgca zC`6PYvMhz|qlOH>>pYAwYk%T~KK4V8FxSIg(4ju9#~s#=aD61gZH<2Bh^)jNF*`=c z9Yu*HCFbNqf0yn6^dXqHe_eRFaM(Utf3c978)?3Lyma;GDPQ^`-MpVVF5leaOMCM8 zrw-3w_{#w2trw3EA8_k(&sycyYS+5jo&Pk=pX(c{mi5wlHQhDWj`q2EvuAE`bE|9K z>6ts+-07NMtMX;*m*D5%@UvIjeDPX(W0x=Prr)^fqRY#By>g3}TWQgNINa#M%^tkV;oUCW?(3jn_NRb-<=DP-Y_I-V%%3(6Zp)MD zxr2KHIVsqwXv5im1LOk<$@|g?xE{(^JV2k53lgf22vz^?zOHH7Apf2=H{|{U6t+#U literal 0 HcmV?d00001 diff --git a/month2_minimart_analysis/python/__pycache__/utils.cpython-313.pyc b/month2_minimart_analysis/python/__pycache__/utils.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f1b3d3acd4bf67948f09d94c767fc9890d371d3c GIT binary patch literal 1368 zcma)6NpI6Y6rORMkPx*EWh+pm0kIiT0~KY7Do|;QKvWzsL6sUQvg}D>sin@JqtfM6uQdGnUU|(fXh8`jxfsXlOAy)#@g{Ir5d7O#>)Yag;wJjG+B`03M-sb`p||pLq3sf< z!9`f3j2|F%7P<{b0A~j-37HF0GHqSvq|Cw^;a7c94tS?;jeYv4UTHTG(jM{Dq5R62W>ElM}7$-_~{kZHXAtbssoi7$R@hCJIIU4GC>sNuD-^2xtGpHlqB>rxd4X56nJC$T?Kio{ zi}j|chC#6*JfEBOW|Z-vaVmW#r%8v8=Yh1*m)!8P?Bi@_^w@Ilc>COkp>+>#+`G}) zHnBW(w0-u&z|ez*dkdW{hnEM&+h^WqH@r%9vU@uEo>lNhjw~!*{m~&HSwizT{{$gB zjZgu`q@ayK;ISk^yWk9$skQb`)$4wfxE^=HMj(h+hU@ekO6YZmQkN4^Wt3Op`pgwM zWUmplIjKydOkWqJV}Q8JECa^Tpe@l$v62mgFbf~w2BeKX?%uz=`{Q-Uk#v}-)!(fpz5l>>T1QEhOhN4OtOeyn$Qh8Q-qNFQwaQFQ^ckRJ=tR5D^O7|E=@A6r-e4u$&D3M~-EHEBQ97 z(2^Q!$YB$=W0epIrZ3hoICR{RK6By&qX#F=miT8dV)bMHiJ+0x9A3(M% F_n$&JPyPS^ literal 0 HcmV?d00001 diff --git a/month2_minimart_analysis/python/main.py b/month2_minimart_analysis/python/main.py index 583f1c8..5f179fd 100644 --- a/month2_minimart_analysis/python/main.py +++ b/month2_minimart_analysis/python/main.py @@ -1 +1,46 @@ # Entry point for the MiniMart data reporting system +from utils import load_data, apply_discount, convert_currency, flag_large_order +from report_generator import generate_report +import pandas as pd +import json + +def main(): + # Load base data + customers, products, orders = load_data() + + # ✅ Simulate new orders using a list of dicts + new_orders = [ + {"order_id": 6, "customer_id": 2, "product_id": 1, "quantity": 3}, + {"order_id": 7, "customer_id": 3, "product_id": 2, "quantity": 5}, + {"order_id": 8, "customer_id": 1, "product_id": 3, "quantity": 10}, + ] + new_orders_df = pd.DataFrame(new_orders) + + # Merge new orders into existing ones + orders = pd.concat([orders, new_orders_df], ignore_index=True) + + # ✅ Apply discounts and currency conversion on products + products["discounted_price"] = products["price"].apply(apply_discount) + products["price_in_kes"] = products["discounted_price"].apply(convert_currency) + + # ✅ Flag large orders (> $100 before conversion) + orders_with_prices = orders.merge(products, on="product_id") + orders_with_prices["order_total"] = orders_with_prices["discounted_price"] * orders_with_prices["quantity"] + orders_with_prices["large_order"] = orders_with_prices["order_total"].apply(flag_large_order) + + # Generate report + report = generate_report(customers, products, orders) + + # Print results + print("==== MiniMart Report ====") + for key, value in report.items(): + print(f"{key}: {value}") + + # Save report to JSON + with open("report.json", "w") as f: + json.dump(report, f, indent=4) + + print("\n✅ Report saved to report.json") + +if __name__ == "__main__": + main() diff --git a/month2_minimart_analysis/python/report.json b/month2_minimart_analysis/python/report.json new file mode 100644 index 0000000..5689dd5 --- /dev/null +++ b/month2_minimart_analysis/python/report.json @@ -0,0 +1,11 @@ +{ + "total_products_sold": 30, + "most_popular_product": "Bread Loaf", + "revenue_per_customer": { + "1": 23.0, + "2": 6.5, + "3": 17.5, + "4": 5.6, + "5": 3.6 + } +} \ No newline at end of file diff --git a/month2_minimart_analysis/python/report_generator.py b/month2_minimart_analysis/python/report_generator.py index fb6ddb8..429a883 100644 --- a/month2_minimart_analysis/python/report_generator.py +++ b/month2_minimart_analysis/python/report_generator.py @@ -1 +1,26 @@ # Code to generate dictionary summary reports +def generate_report(customers, products, orders): + """Generate a dictionary report with key metrics.""" + + # Merge orders with products + orders_with_prices = orders.merge(products, on="product_id") + orders_with_prices["revenue"] = orders_with_prices["price"] * orders_with_prices["quantity"] + + # ✅ Total products sold + total_products_sold = int(orders["quantity"].sum()) + + # ✅ Most popular product + popular_product_id = orders.groupby("product_id")["quantity"].sum().idxmax() + popular_product = products.loc[products["product_id"] == popular_product_id, "product_name"].values[0] + + # ✅ Revenue per customer + revenue_per_customer = ( + orders_with_prices.groupby("customer_id")["revenue"].sum().to_dict() + ) + + report = { + "total_products_sold": total_products_sold, + "most_popular_product": popular_product, + "revenue_per_customer": revenue_per_customer + } + return report diff --git a/month2_minimart_analysis/python/utils.py b/month2_minimart_analysis/python/utils.py index 7049a76..0e0bbc4 100644 --- a/month2_minimart_analysis/python/utils.py +++ b/month2_minimart_analysis/python/utils.py @@ -1 +1,21 @@ # Utility functions for data conversion and filtering +import pandas as pd + +def load_data(): + """Load customers, products, and orders CSVs from sql folder.""" + customers = pd.read_csv("../sql/customers_data.csv") + products = pd.read_csv("../sql/products_data.csv") + orders = pd.read_csv("../sql/orders_data.csv") + return customers, products, orders + +def apply_discount(price, threshold=50, discount=0.1): + """Apply discount if price exceeds threshold.""" + return price * (1 - discount) if price > threshold else price + +def convert_currency(price, rate=150): + """Convert product price to another currency (e.g., USD→KES).""" + return price * rate + +def flag_large_order(total, threshold=100): + """Flag orders exceeding a given total threshold.""" + return total > threshold diff --git a/month2_minimart_analysis/sql/create_tables.sql b/month2_minimart_analysis/sql/create_tables.sql index 1411bac..6a8875a 100644 --- a/month2_minimart_analysis/sql/create_tables.sql +++ b/month2_minimart_analysis/sql/create_tables.sql @@ -1 +1,38 @@ +-- create databse first +CREATE DATABASE minimart; +USE minimart; + -- SQL script to create necessary tables +-- Customers table +CREATE TABLE customers ( + customer_id SERIAL PRIMARY KEY, + name VARCHAR(100), + email VARCHAR(100) +); + +-- Products table +CREATE TABLE products ( + product_id SERIAL PRIMARY KEY, + product_name VARCHAR(100), + price DECIMAL(10,2) +); + +-- Orders table +CREATE TABLE orders ( + order_id SERIAL PRIMARY KEY, + customer_id INT, + order_date DATE, + FOREIGN KEY (customer_id) REFERENCES customers(customer_id) +); + +-- Order details table (to link orders and products) +CREATE TABLE order_details ( + detail_id SERIAL PRIMARY KEY, + order_id INT, + product_id INT, + quantity INT, + FOREIGN KEY (order_id) REFERENCES orders(order_id), + FOREIGN KEY (product_id) REFERENCES products(product_id) +); + + diff --git a/month2_minimart_analysis/sql/customers_data.csv b/month2_minimart_analysis/sql/customers_data.csv new file mode 100644 index 0000000..ad5b577 --- /dev/null +++ b/month2_minimart_analysis/sql/customers_data.csv @@ -0,0 +1,6 @@ +customer_id,name,email,join_date +1,"Alice Johnson",alice.johnson@example.com,2024-01-15 +2,"Brian Smith",brian.smith@example.com,2024-02-10 +3,"Catherine Lee",catherine.lee@example.com,2024-03-05 +4,"David Kim",david.kim@example.com,2024-03-20 +5,"Emily Davis",emily.davis@example.com,2024-04-01 diff --git a/month2_minimart_analysis/sql/insert_data.sql b/month2_minimart_analysis/sql/insert_data.sql index 97dc4da..a9a7f06 100644 --- a/month2_minimart_analysis/sql/insert_data.sql +++ b/month2_minimart_analysis/sql/insert_data.sql @@ -1 +1,23 @@ -- SQL script to insert sample data +INSERT INTO customers (name, email, join_date) VALUES +('Alice Johnson', 'alice.johnson@example.com', '2024-01-15'), +('Brian Smith', 'brian.smith@example.com', '2024-02-10'), +('Catherine Lee', 'catherine.lee@example.com', '2024-03-05'), +('David Kim', 'david.kim@example.com', '2024-03-20'), +('Emily Davis', 'emily.davis@example.com', '2024-04-01'); + +INSERT INTO products (product_name, category, price) VALUES +('Coca Cola 500ml', 'Drinks', 1.50), +('Pepsi 500ml', 'Drinks', 1.40), +('Bread Loaf', 'Bakery', 2.00), +('Apples 1kg', 'Fruits', 3.50), +('Milk 1L', 'Dairy', 1.80); + + +INSERT INTO orders (customer_id, product_id, quantity, order_date) VALUES +(1, 1, 2, '2024-04-05'), -- Alice buys 2 Coca Cola +(2, 3, 1, '2024-04-06'), -- Brian buys 1 Bread +(3, 4, 3, '2024-04-06'), -- Catherine buys 3 kg Apples +(4, 2, 4, '2024-04-07'), -- David buys 4 Pepsi +(5, 5, 2, '2024-04-07'); -- Emily buys 2 Milk + diff --git a/month2_minimart_analysis/sql/orders_data.csv b/month2_minimart_analysis/sql/orders_data.csv new file mode 100644 index 0000000..400429f --- /dev/null +++ b/month2_minimart_analysis/sql/orders_data.csv @@ -0,0 +1,6 @@ +order_id,customer_id,product_id,quantity,order_date +4,4,2,4,2024-04-07 +5,5,5,2,2024-04-07 +2,2,3,1,2024-04-06 +3,3,4,3,2024-04-06 +1,1,1,2,2024-04-05 diff --git a/month2_minimart_analysis/sql/products_data.csv b/month2_minimart_analysis/sql/products_data.csv new file mode 100644 index 0000000..5199188 --- /dev/null +++ b/month2_minimart_analysis/sql/products_data.csv @@ -0,0 +1,6 @@ +product_id,product_name,category,price +1,"Coca Cola 500ml",Drinks,1.50 +2,"Pepsi 500ml",Drinks,1.40 +3,"Bread Loaf",Bakery,2.00 +4,"Apples 1kg",Fruits,3.50 +5,"Milk 1L",Dairy,1.80 diff --git a/month2_minimart_analysis/sql/queries.sql b/month2_minimart_analysis/sql/queries.sql index 883d8ae..9d843e4 100644 --- a/month2_minimart_analysis/sql/queries.sql +++ b/month2_minimart_analysis/sql/queries.sql @@ -1 +1,58 @@ -- SQL queries for retrieving insights +SELECT * +FROM customers; + +SELECT * +FROM products; + +SELECT product_id, product_name, price +FROM products +WHERE category = 'Drinks'; + +SELECT p.product_name, + SUM(p.price * o.quantity) AS total_revenue +FROM orders o +JOIN products p ON o.product_id = p.product_id +GROUP BY p.product_name; + +SELECT AVG(price) AS average_price +FROM products; + + +SELECT * +FROM orders +ORDER BY order_date DESC; + +SELECT COUNT(*) AS total_orders +FROM orders; + +SELECT o.order_id, + c.name AS customer_name, + c.email, + p.product_name, + p.category, + o.quantity, + o.order_date, + (p.price * o.quantity) AS total_price +FROM orders o +INNER JOIN customers c ON o.customer_id = c.customer_id +INNER JOIN products p ON o.product_id = p.product_id; + +SELECT c.customer_id, + c.name, + c.email, + o.order_id, + o.order_date, + o.quantity +FROM customers c +LEFT JOIN orders o ON c.customer_id = o.customer_id; + +-- left join for all data +SELECT p.product_id, + p.product_name, + p.category, + p.price, + o.order_id, + o.quantity +FROM products p +LEFT JOIN orders o ON p.product_id = o.product_id; \ No newline at end of file From 805a4a4d8b21fec47d48bf07fab0753e1b5183eb Mon Sep 17 00:00:00 2001 From: Gituto Miano Date: Sun, 5 Oct 2025 15:40:10 +0300 Subject: [PATCH 3/3] Add results.csv export and SensorReading class --- Water_Quality_Monitoring/requirements.txt | 1 + Water_Quality_Monitoring/water_quality_monitoring | 1 + 2 files changed, 2 insertions(+) create mode 100644 Water_Quality_Monitoring/requirements.txt create mode 160000 Water_Quality_Monitoring/water_quality_monitoring diff --git a/Water_Quality_Monitoring/requirements.txt b/Water_Quality_Monitoring/requirements.txt new file mode 100644 index 0000000..9a12b4e --- /dev/null +++ b/Water_Quality_Monitoring/requirements.txt @@ -0,0 +1 @@ +pandas diff --git a/Water_Quality_Monitoring/water_quality_monitoring b/Water_Quality_Monitoring/water_quality_monitoring new file mode 160000 index 0000000..d8e01fa --- /dev/null +++ b/Water_Quality_Monitoring/water_quality_monitoring @@ -0,0 +1 @@ +Subproject commit d8e01fac730cad564e68aef22682011e0fb721ed