Degree Audit, More Flexibly

There is another way to run a degree audit. It’s more flexible but does not have the ability to compare against expected results.

degreeAudit --help will show you the available options:

oat3 oat-plandefs: degreeAudit --help
Degree Audit 0.7.1-SNAPSHOT (2025-06-22 16:56)
Usage:  [options] [<uwid>...]

  --help                   prints this usage text
  --transcript <transcript_file>
                           read transcript from a file (for testing)
  --plans <dir>            root directory containing plan specifications; fetch from DB if not specified
  --pprint {none|withIncludes|withoutIncludes|topIncludesOnly|includesOnly}
                           pretty print plan specification; defaults to none
  --ppWidth <intVal>       max width for printing planspec
  --verbose                verbose (debug) printing
  --auditSpec              print audit spec before attempting to parse it
  --server <value>         OAT server (defaults to production; otherwise likely localhost:9443
  --outDir <value>         directory where HTML output is placed; defaults to output
  --summary                write a summary to stdout, likely for use in a test suite
  --maxNext <value>        limit calls to next while searching for a solution; defaults to 500,000
  --maxSeconds <value>     limit time searching for a solution; defaults to 15 seconds
  --sshKey <value>         location of keyfile to access OAT server
  <uwid>...                fetch student transcripts from OAT
Error: Must specify either uwids or a transcript file.
Try --help for more information.
oat3 oat-plandefs: 

The --plans, --ppWidth, --verbose, --server, --outDir, and --sshKey options are probably not useful for you.

Command Action
degreeAudit 20967476 Get the transcript for student 20967476 from the OAT server and run the degree audit, putting the result in output/20967476-awhutchi.html.
degreeAudit --transcript transcripts/math/bac/statactsc/stats/biostath-1219-4b.json Gets the transcript from the named file and runs the degree audit, putting the result in output/biostath-1219-4b.html.

In the following, replace <T> with either the 20967476 or --transcript transcripts/math/bac/statactsc/stats/biostath-1219-4b.json, adjusting for the student of your choice.

Command Action
degreeAudit <T> --summary Prints the degree audit summary that is used by da-run-tests.
degreeAudit <T> --maxSeconds 25 --maxNext 1000000 Allows degreeAudit to run longer than usual to solve a tough case.

oat3 test: degreeAudit --transcript transcripts/math/bac/statactsc/stats/biostath-1219-4b.json --pprint withoutIncludes prints the plan specification as shown in OAT:

audit 20967476 "Hutchison, Andy" {
     
    # Global course specifications
    allCourses = ^([A-Z]+)_(([0-9]+X*|XXX|1X000)[A-Z]{0,2})$
     
    # uw.u baseCourseDefs
    coop = allCourses where attemptClass(Coop)
    inProgressCoopCourses = coop /\ ^COOP_.* where inProgress(true)
    coopCourses = coop /\ ^COOP_.* where courseGrade("CR") + inProgressCoopCourses
...

However, a plan specification is typically spread across many files that are combined together. This allows us to reuse common parts in several plans, reducing the amount of editing we need to do as plans change.

To see the includes, change --pprint withoutIncludes to --pprint withIncludes. --pprint stands for “pretty print”. The program is taking pains to use indentation to reflect the specification’s structure, which is “prettier”.

oat3 test: degreeAudit --transcript transcripts/math/bac/statactsc/stats/biostath-1219-4b.json --pprint withIncludes displays:

audit 20967476 "Hutchison, Andy" {
     
    # Global course specifications
    allCourses = ^([A-Z]+)_(([0-9]+X*|XXX|1X000)[A-Z]{0,2})$
     
    block {
         
        # /Users/oat3/oat/oat-plandefs/uw/u/math/baseCourseDefs-1219.plan
        include(baseCourseDefs, 
                1219, 
                uw.u.math.bac.statactsc.stats, 
                uw.u.math.bac.statactsc.stats, uw.u.math, uw.u)
             
            # /Users/oat3/oat/oat-plandefs/uw/u/baseCourseDefs-1109.plan
            include(baseCourseDefs, uw.u)
                 
                # uw.u baseCourseDefs
                coop = allCourses where attemptClass(Coop)
                inProgressCoopCourses = coop /\ ^COOP_.* where inProgress(true)
                coopCourses = coop /\ ^COOP_.* where courseGrade("CR") + inProgressCoopCourses
...

The include(baseCourseDefs, 1219, uw.u.math.bac.statactsc.stats, uw.u.math.bac.statactsc.stats, uw.u.math, uw.u) is an instruction on where to look for the file to include. The comment just above it, # /Users/oat3/oat/oat-plandefs/uw/u/math/baseCourseDefs-1219.plan is the file that was actually read.

To take it one step further/leaner, change --pprint withoutIncludes to --pprint includesOnly:

oat3 test: degreeAudit --transcript transcripts/math/bac/statactsc/stats/biostath-1219-4b.json --pprint includesOnly
block {
     
    # /Users/oat3/oat/oat-plandefs/uw/u/math/baseCourseDefs-1219.plan
    include(baseCourseDefs, 
            1219, 
            uw.u.math.bac.statactsc.stats, 
            uw.u.math.bac.statactsc.stats, uw.u.math, uw.u)
         
        # /Users/oat3/oat/oat-plandefs/uw/u/baseCourseDefs-1109.plan
        include(baseCourseDefs, uw.u)
...

To delve into includes, we should learn about the editor.