Help us measure site usage?

With your permission, we use self-hosted analytics to understand page usage. It is optional and does not affect the Service. Learn more.

ScalabeginnercliAI generated

CSV Grade Summary

Build a command-line tool in Scala that reads a CSV file of student grades and prints a summary: each student's average and letter grade, and for each assignment the average, highest and lowest score and how many students missed it. Bad rows (a missing name, a score that isn't a number, a score above 100) are reported with their line number instead of crashing the program. The main program uses Cats Effect's IO for reading the file, while all the calculations are plain functions that are easy to test. It's a friendly first Scala project: you'll learn case classes, collections (map, groupBy, sum), Option and Either for handling problems, and testing with MUnit.

Estimate
~8.5h
Steps
6
Completed by
0
Proposed by
codeseed.app

sbt · Cats Effect

Project roadmap

  1. 01

    Set up the project and sample data

    ~1h

    Install Scala with Coursier (cs setup) and create an sbt project with Scala 3, adding cats-effect and munit. Add data/grades.csv with a header row (student, assignment, score) and at least 40 rows for 8 students and 5 assignments, including a few broken rows and some missing assignments. Done when: sbt run prints Hello, and the sample file is in the repo.

  2. 02

    Parse rows into case classes

    ~1.5h

    Define a case class Grade(student: String, assignment: String, score: Double). Write parseLine(line, lineNumber): Either[String, Grade] that splits the line by commas, trims the values, and returns Left with a message like line 7: score 'abc' is not a number for a missing field, a non-number or a score outside 0 to 100. Done when: valid lines become Grade values, and each kind of bad line gives a clear message.

  3. 03

    Read the file with Cats Effect

    ~1.5h

    Make the main object an IOApp.Simple. Read the file inside IO (for example with scala.io.Source wrapped in IO.blocking, closing it with Resource), skip the header, and parse every line, splitting the results into valid grades and errors. Print the errors to stderr, and exit with a clear message if the file doesn't exist. Done when: running the program prints how many grades were read and lists the bad lines.

  4. 04

    Summarize students and assignments

    ~2h

    Write pure functions: studentAverages(grades) returns each student's average, rounded to one decimal, with a letter (A for 90 and above, B for 80 and above, and so on); assignmentStats(grades, students) returns each assignment's average, highest and lowest score, and the number of students who have no score for it. Use groupBy and map. Done when: the results for the sample file match your own calculations.

  5. 05

    Print the report

    ~1h

    Print two tables: students sorted by average from highest to lowest (name, average, letter), and assignments (name, average, highest, lowest, missing), with aligned columns using String.format or f-interpolators. End with the class average. Done when: the report is readable and aligned.

  6. 06

    Write tests

    ~1.5h

    Write MUnit tests for parseLine (valid rows, a missing field, a non-number, an out-of-range score), for studentAverages and the letter grades (including boundary values like 89.9 and 90), and for assignmentStats with missing scores. Done when: sbt test passes.

Ready to build this?

Get a GitHub repo and start building. Your AI reviewer checks each step as you go.

~8.5h · 6 steps

Tech stack

sbtCats Effect