It was an interesting week for me on KA. In terms of making it through content on KA, I got less done than any other week so far studying CS, and yet I probably worked harder and learned more this week than any other. 🤔 I’m pretty sad to say that I only made it through one video, one exercise, and one1 challenge, but the reason why I feel like I learned more this week than all the others is because I spent probably close to 10 hours working through the bonus step in the Challenge from Unit 6, Lesson 4. To be fair, when I say I “worked through” it, really what I mean by that is I attempted it, got my ass kicked, and used Gemini to tutor me and help me grind my way through each step, and then eventually write most of the code for me… BUT, I do think I retained a lot of what Gemini helped me with, so it could have been worse. All in all, it was another one of those could-have-been-better, could-have-been-worse kind of weeks, but I’m happy with the effort I put in, so I’ve got that going for me which is nice. 😌
Here’s everything I made notes on this week:
Unit 6 – Analyzing Data with Dictionaries
Lesson 4 – Nested Date: Lists
Video – Program Design: Emergency Response




In this video, Kim talked about 2D lists, i.e. lists nested in lists. She talks about how these are used for matrix multiplication in linear algebra, game design, and are commonly used to create 2D pixel images. The second screenshot above shows how you iterate through each element in nested lists using a for loop in a for loop. The last screenshot shows Kim doing this in practice to print out each integer that makes up the heart image in the bottom right corner.
Exercise – Trace Nested Data: Lists
Question 1



Question 2



This exercise wasn’t too hard, although I did get the second question above wrong. (I screwed up the indexing. 👎🏼) Generally the questions from this exercise weren’t hard but some of the syntax that was used to index into elements/items in nested lists and dictionaries was new to me, so (as always) it was still helpful practice.
Challenge: Listening Habits


I sort of finished this step on my own (or at least without using Gemini), but I did Google how to check if a string was already in a list. Google told me to use the same “not in” operator as on line 13 so it became clear after that — although I did need to know that I needed to add [artist] at the end of tracks_by_artist[artists] which I DID know, which I was happy about.

I had to get Gemini’s help with this step. I was on the right track and understood the logic of what I needed to do, but I didn’t know the right syntax to use. I didn’t think to use “artist, tracks” in line 7 and tracks_by_artist.items(). Once Gemini showed me this code, it made complete sense.

Gemini helped me with this step as well. (Actually, Gemini helped me with every step from hereon, so I’m going to stop saying that.) I typed into Gemini what I thought the logic was and I’m happy to say I had it correct, I just didn’t know how to write the syntax. Gemini didn’t give me the answer but acted as a tutor and helped me figure out the solution on my own. Once I did, it then said I simply could have written:
def count_playtime(streams):
“””Returns a dictionary of artist name to total playtime in ms.”””
playtime_by_artist = {}
for stream in streams:
artist = stream[“artistName”]
msPlayed = stream[“msPlayed”]
if artist not in playtime_by_artist:
playtime_by_artist[artist] = 0
playtime_by_artist[artist] += msPlayed
return playtime_by_artist
Which makes sense to me and would have been a lot easier. 😮💨 Nonetheless, this step helped me remember/practice setting variables ahead of for loops to add the into dictionaries separately.
After finishing off the three required steps of the challenge, KA gave me the instructions for the bonus section of the challenge:
“Add a new module to summarize Mila’s listening habits based on other dimensions. Which tracks does she play on repeat? Find which tracks she frequently skips based on short playtimes. Use the timestamps to identify separate listening sessions. What is her average session length? Are there trends based on the time of day or week?”
I then took those instructions and gave them to Gemini to get it to help me break down what I needed to do, and it said:
1. “Add a new module…”
- What it means: A “module” in Python is just a separate .py file. Just like you had artists.py to hold artist-related functions, you’ll want to create a new file (maybe called listening_habits.py) to hold all these new functions.
- The Logic: This keeps your code clean. main.py will import this new file to run the analyses.
2. “Which tracks does she play on repeat?”
- What it means: We need a function to find Mila’s most-played tracks.
- The Logic: This is actually very similar to the count_playtime function you just wrote! But instead of keeping a running total of msPlayed for each artistName, you would count the number of times a specific trackName appears in the list.
3. “Find which tracks she frequently skips based on short playtimes.”
- What it means: We need to identify tracks that she starts but doesn’t finish.
- The Logic: You have the msPlayed data. You’ll need to decide on a “skip threshold” (e.g., if a track is played for less than 10,000 milliseconds—or 10 seconds—it counts as a skip). Then, you create a dictionary to count how many times each track falls under that threshold.
4. “Use the timestamps to identify separate listening sessions.”
- What it means: We need to group tracks together based on when they were played.
- The Logic: This is where it gets tricky. You’d need to look at the endTime strings. If the time gap between track A and track B is small (say, less than 15 minutes), they are in the same “session”. If there’s a 4-hour gap, track B is the start of a new session.
5. “What is her average session length?”
- What it means: Once you have grouped the tracks into sessions (from Step 4), you calculate the math.
- The Logic: Find the total time spent in each session, add all those session times together, and divide by the total number of sessions.
6. “Are there trends based on time of day or week?”
- What it means: Finding out if she listens to more music on Tuesday mornings vs. Friday nights.
- The Logic: You would need to use Python’s built-in datetime library to convert the string “2024-04-07 00:02” into a format where you can easily ask Python, “What day of the week was this?” and then count the streams per day.


I’m not going to go into too much detail, but to satisfy the second step of Gem’s instructions, I made a new module called listening_habits.py and wrote:
“””Summarizes users listening habits based on repeat plays, skips, and sessions.”””
def most_played(streams):
“””Returns a dictionary with songs as key and number of times played as value.”””
track_counts = {}
for stream in streams:
track_name = stream[“trackName”]
if track_name not in track_counts:
track_counts[track_name] = 1
else:
track_counts[track_name] += 1
return track_counts
def get_top_10(track_counts):
“””Returns a list of tuples with user’s top 10 most played tracks.”””
sorted_songs = sorted(track_counts.items(), key=lambda item: item[1], reverse=True)
top_10 = sorted_songs[:10]
return top_10
And on main.py I wrote:
# This is where you’ll set the function to tell you what tracks Mila played most.
track_counts = listening_habits.most_played(streaming_history.april)
top_10 = listening_habits.get_top_10(track_counts)
print(“\nYour top 10 most listened to tracks were:”)
for track, count in top_10:
print(f”* {track} ({count} plays)”)
This led to the terminal outputting:
Your top 10 most listened to tracks were:
* VAGABUNDO (23 plays)
* yes, and? (21 plays)
* Cambia el Paso (18 plays)
* Arranca (feat. Omega) (18 plays)
* Sweet Melody (18 plays)
* Hands On Me (feat. Meghan Trainor) (16 plays)
* Houdini (15 plays) * Tempo (feat. Missy Elliott) (15 plays)
* Pink Venom (14 plays)
* Hey Now (Iko Iko) (14 plays)
Going back and forth with Gemini, it probably took me 1.5 hours just to do this step.


To have the terminal output what tracks were skipped more than 5 times, I pretty much just reused the code from figuring out the user’s (Mila’s) top 10 most listened to songs. In listening_habits.py I wrote:
def skipped_tracks(streams, max_ms=10000):
“””Returns a dictionary of tracks played for less than 10 seconds.”””
skipped_tracks = {}
for stream in streams:
if stream[“msPlayed”] < max_ms:
track_name = stream[“trackName”]
if track_name not in skipped_tracks:
skipped_tracks[track_name] = 1
else:
skipped_tracks[track_name] += 1
return skipped_tracks
def skipped_5_or_more(skipped_tracks, min_skipped):
“””Returns a list of tuples of tracks that were skipped 10 or more times”””
skipped_5_or_more = {}
for track in skipped_tracks:
if skipped_tracks[track] >= min_skipped:
skipped_5_or_more[track] = skipped_tracks[track]
sorted_skips = sorted(skipped_5_or_more.items(), key=lambda item: item[1], reverse=True)
return sorted_skips
And on main.py I wrote:
# This will tell users what songs were skipped before 10 seconds.
skipped_tracks = listening_habits.skipped_tracks(streaming_history.april)
skipped_5_or_more = listening_habits.skipped_5_or_more(skipped_tracks, 5)
print(“\n You skipped these tracks:”)
for track, count in skipped_5_or_more:
print(f”* {track} ({count} times)”)
The terminal output was:
You skipped these tracks:
* Tempo (feat. Missy Elliott) (7 times)
* Sweet Melody (7 times)
* Houdini (7 times)
* Cambia el Paso (6 times)
* VAGABUNDO (5 times)
* Hands On Me (feat. Meghan Trainor) (5 times)
* Shivers (5 times)
* Unholy (feat. Kim Petras) (5 times)
* yes, and? (5 times)

The fifth step of Gemini’s instructions was to figure out the average length of each on of Mila’s listening sessions. I found this step incredibly difficult and was way out of my depth trying to work through it. I’m sure I learned quite a bit by attempting it, but Gemini did the majority of the coding for me. In the end, I ended up writing these three functions in listening_habits.py:
def calculate_sessions(streams):
“””This function returns you the average listening length time of each session”””
sessions = []
current_session_ms = 0
for i in range(len(streams)):
if i == 0:
current_session_ms = streams[i][“msPlayed”]
continue
gap = get_minutes_between(streams[i – 1][“endTime”], streams[i][“endTime”])
if gap < 60:
current_session_ms += streams[i][“msPlayed”]
else:
sessions.append(current_session_ms)
current_session_ms = streams[i][“msPlayed”]
if current_session_ms > 0:
sessions.append(current_session_ms)
avg_session_length = average_session(sessions)
return avg_session_length
def get_minutes_between(time_str1, time_str2):
“””This function calculates the time gap between streams”””
time_format = “%Y-%m-%d %H:%M”
time1 = datetime.strptime(time_str1, time_format)
time2 = datetime.strptime(time_str2, time_format)
time_gap = time2 – time1
minutes = time_gap.total_seconds() / 60
return minutes
def average_session(sessions):
“””Calculates the average length of listening sessions in minutes.”””
# If session list is empty, it equals 0 which equals false. “If not
# 0″ means “false false = true” therefore this if statement will execute.
if not sessions:
return 0
total_ms = sum(sessions)
total_minutes = total_ms / 60000
avg_session = total_minutes / len(sessions)
return avg_session
And I also wrote this function call and print statement in main.py:
# This tells the user the length of their average listening session.
avg_session = listening_habits.calculate_sessions(streaming_history.april)
print(f”\nYour average listening session length was {avg_session: .1f} minutes.”)
The terminal output was, “Your average listening length was 33.9 minutes.” So, in the end it all worked, but, as I said, I struggled and did at most 50% of the coding by myself. Still, I probably spent >= 2 hours working through this step and think I ended up getting a lot out of doing it.

These last few functions I wrote to finish off the bonus section of the challenge were used to tell the user the top 5 times during the week that the listened to music. Gemini basically did everything for me (😒), but I did spend a lot of time trying to think through how to do each sub-step before getting the answer/code from Gemini. By the end of it, in listening_habits.py I’d written:
def streams_per_day(streams):
“””This function will tell the user the top 5 days and time of day
that they listen to music the most.
“””
day_counts = {}
time_format = “%Y-%m-%d %H:%M”
for stream in streams:
dt = datetime.strptime(stream[“endTime”], “%Y-%m-%d %H:%M”)
day_name = dt.strftime(“%A”)
time_block = get_time_of_day(dt.hour)
category = f”{day_name} {time_block}”
if category not in day_counts:
day_counts[category] = stream[“msPlayed”]
else:
day_counts[category] += stream[“msPlayed”]
return day_counts
def get_time_of_day(hour):
“””Categorizes an hour (0-23) into a time-of-day block.”””
if 0 <= hour < 6:
return “Night”
elif 6 <= hour < 12:
return “Morning”
elif 12 <= hour < 18:
return “Afternoon”
else:
return “Evening”
def get_top_5(day_and_time):
sorted_day_time = sorted(day_and_time.items(), key=lambda item: item[1], reverse=True)
top_5 = sorted_day_time[:5]
return top_5
And in main.py I wrote:
# This tells the user when they listened to music most throughout the week
streams_per_day = listening_habits.streams_per_day(streaming_history.april)
top_5 = listening_habits.get_top_5(streams_per_day)
print(“\nThe top 5 times you listened to music most during the week was:”)
for day_time, total_ms in top_5:
minutes = total_ms / 60000
print(f”* {day_time} ({minutes:.1f} minutes)”)
Overall, I spent 1–1.5 hours doing this final step of the bonus section. I ended up finishing it off at 6pm on Sunday. 😮💨
And that was it for this week. As you can see, I ended up writing out a decent amount of code (for me, at least), so I’m not dissatisfied with my effort. Come to think of it, I’m honestly not worried anymore about getting through the CS section of KA as quickly as possible or before a certain date. I DO want to learn CS as quickly as possible, but that really doesn’t have anything to do with getting through CS on KA as quickly as possible. I randomly decided last night (Sunday night) that I’m going to try and study Python for a minimum of 4 hours each day this week. As I type this (on Monday morning) I’ve so far studied for 2h20m05s. (I set a timer on my phone and each time I begin studying I start the time back up.) I want to commit to learning Python and I think aiming for 4 hours a day is reasonable. (Part of me feels like 4 hours isn’t that much time at all but as I’m doing it, it feels like it’s a LOT of time. 😂)
So, as always, fingers crossed I can get some decent work done this week and make some solid progress wrapping my head around Python. 🤞🏼 And double fingers crossed that I can see this 4-hours-per-day goal through to the end of the week. 🤞🏼🤞🏼 I think it would make a huge difference if I can make it happen!