diff --git a/.gitignore b/.gitignore index 2b76d7c..4219678 100644 --- a/.gitignore +++ b/.gitignore @@ -87,6 +87,7 @@ web_modules/ .env .env.* !.env.example +.week11-streamlit/.env # parcel-bundler cache (https://parceljs.org/) .cache @@ -156,3 +157,4 @@ dist vite.config.js.timestamp-* vite.config.ts.timestamp-* +week11-streamlit/.env diff --git a/AI_ASSIST.md b/AI_ASSIST.md index 8585a41..b48dc61 100644 --- a/AI_ASSIST.md +++ b/AI_ASSIST.md @@ -3,34 +3,38 @@ Document one place you used an LLM during this assignment. ## The problem +i did not know how to record myself using teams or zoom - +## The prompt -TODO +how to record my screen and voice with my computer using teams or zoom -## The prompt +## The response +🎥 Recording in Microsoft Teams +Takeaway: You can record any meeting, even if you're alone, and Teams will capture your screen, microphone, and system audio (if enabled). - +How to do it +Open Teams and start a meeting -TODO +Click Calendar → Meet now, or open an existing meeting. -## The response +Join the meeting - +Turn on your microphone if you want your voice recorded. -TODO +Share your screen -## Reflection +Click Share (the square-with-arrow icon). + +Choose Screen, Window, or PowerPoint Live. - +Start recording -TODO +Click More (···) → Start recording. + +## Reflection ---- +I need to join a meeting even if by myself there is no other way of recording and need to upgrade to premium so i switched to OBS. > Remember: never paste real connection strings, passwords, or PII into an LLM. > The NYC TLC dataset is public so sample rows are safe here, but practise the habit. diff --git a/README.md b/README.md index 91de124..6b9b436 100644 --- a/README.md +++ b/README.md @@ -52,9 +52,11 @@ Fill in `week11-streamlit/metric_definitions.md`: a five-field definition (name, 2) Paste its link below, plus screenshots or a PDF export in this repo. 3) Paste your 5-minute presentation recording link (keep it PRIVATE). --> -- Metabase dashboard (in the **Week 11 Submissions** collection): TODO -- Screenshots / PDF export: TODO -- Presentation recording (private, hosted in the Azure `student-submissions` container): TODO +- Metabase dashboard (in the **Week 11 Submissions** collection): +https://metabase-hyf.politepebble-abd3ebc2.westeurope.azurecontainerapps.io/dashboard/46-nyc-taxi-analytics-hannah +- Screenshots / PDF export: screenshots are in the docs folder +- Presentation recording (private, hosted in the Azure `student-submissions` container): +https://hyfstoragedev.blob.core.windows.net/student-submissions/week-11/hannahwn.mp4 > ⚠️ **Keep the recording private.** It shows your screen and voice. Never make it public and never commit the `.mp4` (git history is forever). Check the frame for passwords, `.env` contents, or connection strings before uploading. diff --git a/docs/metabase screenshot.png b/docs/metabase screenshot.png new file mode 100644 index 0000000..effa0d2 Binary files /dev/null and b/docs/metabase screenshot.png differ diff --git a/docs/streamlit screenshot.png b/docs/streamlit screenshot.png new file mode 100644 index 0000000..bea3211 Binary files /dev/null and b/docs/streamlit screenshot.png differ diff --git a/week11-streamlit/.env.example b/week11-streamlit/.env.example index 810f19b..1bfb646 100644 --- a/week11-streamlit/.env.example +++ b/week11-streamlit/.env.example @@ -1,6 +1,6 @@ # PostgreSQL connection string (your Week 9/10 login) # Keep the database name as team1 and the ?sslmode=require suffix; only swap # in your own user, password, and host. -POSTGRES_URL=postgresql://your-pg-user:your-pg-password@your-pg-host:5432/team1?sslmode=require +POSTGRES_URL=postgresql://hannahwn:HhRHmt469pEm3Ou0@hyf-data-pg.postgres.database.azure.com:5432/team1?sslmode=require # Your dev schema name (e.g. dev_jana) -DB_SCHEMA=dev_yourname +DB_SCHEMA=dev_hannahwn diff --git a/week11-streamlit/app.py b/week11-streamlit/app.py index cf06bcb..30d740b 100644 --- a/week11-streamlit/app.py +++ b/week11-streamlit/app.py @@ -18,28 +18,86 @@ load_dotenv() # reads .env file if present POSTGRES_URL = os.environ["POSTGRES_URL"] -DB_SCHEMA = os.environ.get("DB_SCHEMA", "dev_yourname") +DB_SCHEMA = os.environ.get("DB_SCHEMA", "dev_hannahwn") st.set_page_config(page_title="NYC Taxi Metrics", layout="wide") st.title("NYC Taxi Metrics") + + @st.cache_data(ttl=300) def run_query(sql: str) -> pd.DataFrame: engine = sqlalchemy.create_engine(POSTGRES_URL) with engine.connect() as conn: return pd.read_sql(sql, conn) +st.sidebar.header("Filters") + +payment_types = run_query(f""" + SELECT DISTINCT payment_type_label + FROM {DB_SCHEMA}.fct_trips + WHERE payment_type_label IS NOT NULL + ORDER BY payment_type_label +""")["payment_type_label"].tolist() + +selected_payment_type = st.sidebar.selectbox( + "Payment type", + ["All"] + payment_types +) + +if selected_payment_type == "All": + where_clause = "" +else: + where_clause = f"WHERE payment_type_label = '{selected_payment_type}'" + st.subheader("Headline KPIs") +KPIs= run_query(f""" + SELECT + COUNT(*) AS total_trips, + AVG(trip_distance) AS avg_trip_distance, + AVG(fare_per_mile) AS avg_fare_per_mile + FROM {DB_SCHEMA}.fct_trips + {where_clause} +""").iloc[0] + +col1, col2, col3 = st.columns(3) +col1.metric("Total Trips", f"{KPIs['total_trips']:,}") +col2.metric("Avg Trip Distance (miles)", f"{KPIs['avg_trip_distance']:.2f}") +col3.metric("Avg Fare per Mile ($)", f"{KPIs['avg_fare_per_mile']:.2f}") + -# TODO: query total trip count, average trip_distance, and average -# fare_per_mile from {DB_SCHEMA}.fct_trips through run_query(), then -# render three tiles side by side with st.columns(3) and .metric(). -# This is deliberately not the total-trips/avg-fare/total-revenue trio -# from the chapter: trip_distance and fare_per_mile are different columns, -# so copying the chapter's SQL verbatim will not answer this. -raise NotImplementedError( - "TODO: implement the headline KPIs panel (total trips, avg trip " - "distance, avg fare per mile) from fct_trips." + + +st.subheader("Trip Distance Distribution") +hourly_dist = run_query(f""" + SELECT + EXTRACT(HOUR FROM pickup_datetime) AS hour_of_day, + COUNT(*) AS trip_count + FROM {DB_SCHEMA}.fct_trips + GROUP BY 1 + ORDER BY 1 +""") + +if hourly_dist.empty: + st.warning("No data available for the selected filters.") +else: + st.bar_chart(hourly_dist.set_index("hour_of_day")["trip_count"]) + + +st.subheader("Data Freshness") +freshness = run_query(f""" + SELECT + MAX(pickup_datetime) AS last_pickup, + MAX(dropoff_datetime) AS last_dropoff + FROM {DB_SCHEMA}.fct_trips +""").iloc[0] + +col1, col2 = st.columns(2) + +col1.metric("Row count", f"{KPIs['total_trips']:,}") +col2.metric( + "Last pickup", str(freshness["last_pickup"])[:16] if freshness["last_pickup"] else "unknown" ) + diff --git a/week11-streamlit/metric_definitions.md b/week11-streamlit/metric_definitions.md new file mode 100644 index 0000000..dfb2284 --- /dev/null +++ b/week11-streamlit/metric_definitions.md @@ -0,0 +1,51 @@ +# Metric definitions + +Five fields per metric: Name, Description, Calculation, Data source, Refresh frequency. One block per panel. Copy this file to `metric_definitions.md` inside your `week11-streamlit/` folder and fill it in. + +## Metabase panels + + + +### Panel 1: + +- **Name**: Trip count by payment type +- **Description**: Helps identify which payment type is preffered +- **Calculation**: sum of payments grouped by type of payment +- **Data source**: fct_trips +- **Refresh frequency**: every time fct_trips is built + +### Panel 2: + +- **Name**: Average fare per mile by dropoff borough +- **Description**: Helps show the average money paid per mile in every borough +- **Calculation**: finding the average of of fare paid by mile and grouping per borough +- **Data source**: the fct_trips +- **Refresh frequency**: every time fct_trips is built + +### Panel 3: + +- **Name**: Average trip duration per hour +- **Description**: Shows which hours are busiest by average +- **Calculation**: we deduct the pickup time time from dropoff time and then find average +- **Data source**: fct_trips +- **Refresh frequency**: every time fct_trips is run + +## Streamlit panels + + + +### Panel 1: + +- **Name**: Headline KPIs +- **Description**: total trips,average_trip distance,average fare per mile +- **Calculation**: COUNT(*) AS total_trips, + AVG(trip_distance) AS avg_trip_distance, + AVG(fare_per_mile) AS avg_fare_per_mile +- **Data source**: fct_trips +- **Refresh frequency**: when data is cached + +