import csv
# Open the file that's sitting in the same folder as this script
with open("battle_data.csv", "r") as f:
lines = f.readlines()
print(f"The file contains {len(lines)} lines (including the header).")
print("First 5 lines:")
for line in lines[:5]:
print(line.strip())
Reading and Processing the Battle Log
Mission Brief
The Forge Command Centre has handed you battle_data.csv — a real file, a log of every battle fought by six robots. Your job is to write real Python file-processing code in IDLE: open the file, read it, and turn raw rows into useful statistics.
This saves an actual battle_data.csv file to your computer — the same file your Python program will open.
Getting Set Up in IDLE
- Click the download button above and make a new folder for this project — call it something like battlebot_redux.
- Move the downloaded battle_data.csv into that folder.
- Open IDLE. Go to File → New File.
- Save this new file into the same folder as your CSV — name it battle_analysis.py. This matters:
open("battle_data.csv")only works if the CSV is in the same folder as the script you're running. - Copy each starter code block below into your file as you go, complete the TODOs, then run your program with Run → Run Module (or press F5). Check your output in the IDLE Shell window.
open() gives you a file object, .readlines() gives you every line as a string in a list. The with block automatically closes the file when you're done — no need to call f.close() yourself.import csv
with open("battle_data.csv", "r") as f:
reader = csv.DictReader(f)
battles = list(reader) # each row becomes a dictionary
print(f"Loaded {len(battles)} battle records.")
print("\nExample record:")
print(battles[0])
# TODO: print the robot_name and result for the first 5 battles
# Your code here:
for battle in battles[:5]:
print(battle["robot_name"], "-", battle["result"])win_rate() functionimport csv
with open("battle_data.csv", "r") as f:
battles = list(csv.DictReader(f))
def win_rate(robot_name, battles):
"""Return the win rate (0-100) for a given robot, rounded to 1 decimal place."""
# TODO:
# 1. Filter 'battles' down to only rows where robot_name matches
# 2. Count how many of those rows have result == "Win"
# 3. Return (wins / total) * 100, rounded to 1 decimal place
pass
print("Titanium Fang win rate:", win_rate("Titanium Fang", battles), "%")
print("Nova Striker win rate:", win_rate("Nova Striker", battles), "%")
def win_rate(robot_name, battles):
robot_battles = [b for b in battles if b["robot_name"] == robot_name]
wins = [b for b in robot_battles if b["result"] == "Win"]
return round((len(wins) / len(robot_battles)) * 100, 1)import csv
with open("battle_data.csv", "r") as f:
battles = list(csv.DictReader(f))
def average_damage_dealt(robot_name, battles):
"""Return the average damage_dealt for a robot, rounded to 1 decimal place."""
# Remember: values from a CSV file are always strings!
# You'll need to convert damage_dealt to an int before doing maths on it.
# TODO: complete this function
pass
robots = ["Titanium Fang", "Volt Reaper", "Iron Wraith",
"Crimson Gearhead", "Nova Striker", "Obsidian Juggernaut"]
for robot in robots:
avg = average_damage_dealt(robot, battles)
print(f"{robot:<20} avg damage dealt: {avg}")
def average_damage_dealt(robot_name, battles):
robot_battles = [b for b in battles if b["robot_name"] == robot_name]
damages = [int(b["damage_dealt"]) for b in robot_battles]
return round(sum(damages) / len(damages), 1)import csv
with open("battle_data.csv", "r") as f:
battles = list(csv.DictReader(f))
def win_rate(robot_name, battles):
robot_battles = [b for b in battles if b["robot_name"] == robot_name]
wins = [b for b in robot_battles if b["result"] == "Win"]
return round((len(wins) / len(robot_battles)) * 100, 1)
robots = ["Titanium Fang", "Volt Reaper", "Iron Wraith",
"Crimson Gearhead", "Nova Striker", "Obsidian Juggernaut"]
# TODO: build a list of (robot_name, win_rate) tuples,
# then sort it so the highest win rate comes first,
# then print a numbered leaderboard, e.g.
# 1. Crimson Gearhead - 66.7%
leaderboard = []
# your code here
leaderboard = [(robot, win_rate(robot, battles)) for robot in robots]
leaderboard.sort(key=lambda pair: pair[1], reverse=True)
for i, (robot, rate) in enumerate(leaderboard, start=1):
print(f"{i}. {robot} - {rate}%")Data Visualisation
Mission Brief
Numbers in a table are hard to compare at a glance — graphs make patterns jump out. Here you'll use Python's matplotlib library to turn the same battle log into charts, still running in IDLE against your real battle_data.csv.
Before you start
- Make sure matplotlib is installed. In IDLE, go to Run → Python Shell and type
import matplotlib— if you get an error, ask your teacher to help you install it (usuallypip install matplotlibfrom a command prompt). - Keep working in the same folder as battle_data.csv. You can add these charts to battle_analysis.py or start a new file — either way,
plt.show()will pop up a chart window when you run the program.
import csv
import matplotlib.pyplot as plt
with open("battle_data.csv", "r") as f:
battles = list(csv.DictReader(f))
robots = ["Titanium Fang", "Volt Reaper", "Iron Wraith",
"Crimson Gearhead", "Nova Striker", "Obsidian Juggernaut"]
# TODO: build a list "win_counts" with the number of wins for each robot,
# in the same order as "robots"
win_counts = []
# your code here
plt.figure(figsize=(8, 4.5))
plt.bar(robots, win_counts, color="#2e8f6d")
plt.title("Wins per Robot")
plt.ylabel("Wins")
plt.xticks(rotation=25, ha="right")
plt.tight_layout()
plt.show()
win_counts = []
for robot in robots:
wins = [b for b in battles if b["robot_name"] == robot and b["result"] == "Win"]
win_counts.append(len(wins))plt.show() opens a window with your chart in it. Close that window to let the rest of your program (or the Shell) continue.import csv
import matplotlib.pyplot as plt
with open("battle_data.csv", "r") as f:
battles = list(csv.DictReader(f))
# TODO: build three lists from 'battles':
# - dealt: damage_dealt as an int, for every battle
# - taken: damage_taken as an int, for every battle
# - colors: "#2e8f6d" (green) if result == "Win" else "#c94f3d" (red)
dealt, taken, colors = [], [], []
# your code here
plt.figure(figsize=(6, 6))
plt.scatter(dealt, taken, c=colors, alpha=0.75, edgecolor="#101826")
plt.title("Damage Dealt vs Damage Taken")
plt.xlabel("Damage Dealt")
plt.ylabel("Damage Taken")
plt.plot([0, 100], [0, 100], linestyle="--", color="#5b6b85") # reference line
plt.tight_layout()
plt.show()
for b in battles:
dealt.append(int(b["damage_dealt"]))
taken.append(int(b["damage_taken"]))
colors.append("#2e8f6d" if b["result"] == "Win" else "#c94f3d")import csv
import matplotlib.pyplot as plt
with open("battle_data.csv", "r") as f:
battles = list(csv.DictReader(f))
robots = ["Titanium Fang", "Volt Reaper", "Iron Wraith",
"Crimson Gearhead", "Nova Striker", "Obsidian Juggernaut"]
# Challenge: no scaffolding this time!
# Calculate the average energy_used for each robot and plot it as a
# horizontal bar chart (hint: plt.barh(...)). Which robot is most
# energy efficient?
# your code here
plt.show()
avg_energy = []
for robot in robots:
energies = [int(b["energy_used"]) for b in battles if b["robot_name"] == robot]
avg_energy.append(sum(energies) / len(energies))
plt.figure(figsize=(8, 4.5))
plt.barh(robots, avg_energy, color="#f4b731")
plt.xlabel("Average Energy Used")
plt.title("Energy Efficiency per Robot")
plt.tight_layout()Build the Ultimate Robot
Mission Brief
Use everything the data taught you. You have 100 points to distribute across five stats. Adjust the sliders, watch the radar chart update live, then hit Simulate Battle to see how your build stacks up against the Forge's toughest boss bot, Obsidian Juggernaut Mk.II.
def battle_sim(stats, boss):
"""
stats/boss: dicts with keys armor, speed, weapon, energy, targeting (0-60 each)
Returns a dict with win_probability and whether the player won.
"""
import random
player_power = (stats["weapon"] * 1.1 + stats["targeting"] * 0.6
+ stats["speed"] * 0.4 + stats["armor"] * 0.3
+ stats["energy"] * 0.2)
boss_power = (boss["weapon"] * 1.1 + boss["targeting"] * 0.6
+ boss["speed"] * 0.4 + boss["armor"] * 0.3
+ boss["energy"] * 0.2)
win_probability = player_power / (player_power + boss_power)
won = random.random() < win_probability
return {
"win_probability": round(win_probability * 100, 1),
"won": won
}
# Try it yourself: build a "stats" dictionary matching the sliders above,
# a "boss" dictionary with armor=22, speed=18, weapon=28, energy=16, targeting=16,
# and call battle_sim(stats, boss). Run it a few times -- since it uses
# random.random(), does a robot with a higher win_probability always win?