Commit 21b3bcbc authored by Saikiran Srirangapalli's avatar Saikiran Srirangapalli

Merge branch 'master' of gitlab.com:saikiran1096/gradaudit

parents 8622eb88 10afd2aa
...@@ -19,17 +19,17 @@ This program is a degree audit system for degrees at The University of Texas at ...@@ -19,17 +19,17 @@ This program is a degree audit system for degrees at The University of Texas at
2. License 2. License
The Graduation Audit System is distributed under GNU Public License Version 3. The Graduation Audit System is distributed under the GNU Public License Version 3.
3. Contents 3. Contents
bs/ -degree plans for Bachelor of Sciences degrees bs/ -degree plans for Bachelor of Sciences degrees
ba/ -degree plans for Bachelor of Arts degrees ba/ -degree plans for Bachelor of Arts degrees
transcripts/ -CSV files that contain the students information transcripts/ -Some example transcripts in the specified .csv format
README -this README file README -this README file
counting.lp -file that has rules for counting hours counting.lp -file that has rules for counting hours
course.lp -file that contains every class in the system course.lp -file that contains every class in the system
COPYING -GNU GPLv3 COPYING -License
main.lp -file that is run by s(ASP) main.lp -file that is run by s(ASP)
main_writer.py -Python script that generates main.lp main_writer.py -Python script that generates main.lp
req_writer.py -Python script that generates req.lp file req_writer.py -Python script that generates req.lp file
...@@ -47,15 +47,15 @@ Ghostscript is required to run extract.py. ...@@ -47,15 +47,15 @@ Ghostscript is required to run extract.py.
Example degree plans and transcripts are included in the bs/, ba/, and transcripts/ folders. Example degree plans and transcripts are included in the bs/, ba/, and transcripts/ folders.
To run an audit, you must use main_writer.py and pass in a CSV file to create a main.lp file which will be executed by s(ASP). Run this command in the terminal: To run an audit, you must use main_writer.py and pass in a transcript file to create a main.lp file which will be executed by s(ASP). Run this command in the terminal:
python main_writer.py test.csv python main_writer.py transcripts/saics.csv
This will look for the test.csv file in the transcripts folder and update the main.lp file in the main directory. This main.lp file contains information from the transcript in the form of logic facts. Once the main.lp file is created/updated, run this command in the terminal: This will use transcripts/saics.csv to build main.lp, which can in turn be executed by s(ASP). Once the main.lp file is created run this command in the terminal:
sasp main.lp sasp main.lp
This will run the audit for the transcript created by main_writer.py and will determine if the student can graduate and if not, what classes are needed. This will run the audit and provide appropriate advising information.
6. Creating/Modifying Degree Plans 6. Creating/Modifying Degree Plans
...@@ -67,7 +67,7 @@ B. Next, create a "req" lp file with the naming convention: ...@@ -67,7 +67,7 @@ B. Next, create a "req" lp file with the naming convention:
"<acronym><year>req.lp" "<acronym><year>req.lp"
For example, for the CS 2015 degree plan, the file would be called: cs2015.req. For example, for the CS 2015 degree plan, the file would be called: cs2015req.lp.
C. Now, create logic rules in the form of: C. Now, create logic rules in the form of:
...@@ -79,13 +79,13 @@ typeOfRequirement is what type of requirement the class will fulfill. ...@@ -79,13 +79,13 @@ typeOfRequirement is what type of requirement the class will fulfill.
Note: If the class is absolutely required to graduate, its typeOfRequirement is "required". Otherwise, it is whatever requirement you want to name it. Note: If the class is absolutely required to graduate, its typeOfRequirement is "required". Otherwise, it is whatever requirement you want to name it.
Example: hist1301 is an American history class that counts toward the American History Requirement in the degree plan and it is NOT absolutely required to graduate. Example: hist1301 is an American history class that counts toward the American History Requirement in the degree plan and it is not absolutely required to graduate (another American History course can be used to satisfy the requirement).
Add: _req(hist1301,americanHist). where americanHist is the typeOfRequirement. Add: _req(hist1301,americanHist).
Another example: govt2305 is a government class that IS required to graduate. Another example: govt2305 is a government class that is required to graduate.
Add: _req(govt2305,required). where required is the typeOfRequirement. Add: _req(govt2305,required).
For every class that could be used for a particular type of requirement in the degree plan, add a _req() rule. For every class that could be used for a particular type of requirement in the degree plan, add a _req() rule.
These rules are used to associate classes with requirements and used for counting. These rules are used to associate classes with requirements and used for counting.
...@@ -95,7 +95,7 @@ Once the req file is complete, make sure the naming convention is correct and pl ...@@ -95,7 +95,7 @@ Once the req file is complete, make sure the naming convention is correct and pl
i.e. For the B.S. Computer Science degree plan of 2015, place the req file in gradaudit/bs/cs/2015. This directory will eventually contain 5 LP files all associated with this exact degree plan. i.e. For the B.S. Computer Science degree plan of 2015, place the req file in gradaudit/bs/cs/2015. This directory will eventually contain 5 LP files all associated with this exact degree plan.
Note: A course should not satisfy more than one degree requirement. Note: A course should not satisfy more than one degree requirement.
i.e. there should not be the two facts '_req(course1,req1)' and '_req(course2,req2)' for any degree. i.e. there should not be the two facts '_req(course1,req1)' and '_req(course1,req2)' for any degree.
D. Once the _req file has been created, run the python script req_writer.py and pass three arguments in the command line in this form: D. Once the _req file has been created, run the python script req_writer.py and pass three arguments in the command line in this form:
...@@ -208,7 +208,3 @@ _meetsElectiveHours(Student,Min). ...@@ -208,7 +208,3 @@ _meetsElectiveHours(Student,Min).
_auditElectiveHours(Student,Min). _auditElectiveHours(Student,Min).
This rule is the same as auditHours except the requirement is for electives. Similar to auditHours, it will always be true. This rule is the same as auditHours except the requirement is for electives. Similar to auditHours, it will always be true.
...@@ -50,6 +50,7 @@ ENTRY_REGEX = re.compile(ENTRY_REGEX) ...@@ -50,6 +50,7 @@ ENTRY_REGEX = re.compile(ENTRY_REGEX)
EXTRACTION_REGEX = r'([A-Z]+)\s+([0-4][0-9V-][0-9-][0-9-])[\s+A-Z-&/]+([0-9])\.000\s([0-9])\.000' EXTRACTION_REGEX = r'([A-Z]+)\s+([0-4][0-9V-][0-9-][0-9-])[\s+A-Z-&/]+([0-9])\.000\s([0-9])\.000'
class TranscriptConversionError(Exception): class TranscriptConversionError(Exception):
""" """
Error during conversion of unofficial transcript (pdf) Error during conversion of unofficial transcript (pdf)
...@@ -91,10 +92,11 @@ def extract_courses(unofficial_transcript): ...@@ -91,10 +92,11 @@ def extract_courses(unofficial_transcript):
raise TranscriptConversionError( raise TranscriptConversionError(
msg=err_msg, cmd=ps2ascii, err=ascii_err) msg=err_msg, cmd=ps2ascii, err=ascii_err)
matches = ENTRY_REGEX.findall(ascii_out.decode("utf-8")) matches = ENTRY_REGEX.findall(ascii_out.decode("utf-8"))
matches = re.findall(EXTRACTION_REGEX,'\n'.join(matches)) matches = re.findall(EXTRACTION_REGEX, '\n'.join(matches))
matches = [(t[0].lower()+t[1],int(t[2]),int(t[3])) for t in matches] matches = [(t[0].lower() + t[1], int(t[2]), int(t[3])) for t in matches]
return matches return matches
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
along with Graduation Audit System. If not, see <http://www.gnu.org/licenses/>. along with Graduation Audit System. If not, see <http://www.gnu.org/licenses/>.
""" """
from __future__ import print_function from __future__ import print_function
import argparse
import sys import sys
import util import util
...@@ -28,11 +29,10 @@ def main(): ...@@ -28,11 +29,10 @@ def main():
python main_writer.py <transcript> python main_writer.py <transcript>
""" """
if len(sys.argv) != 2: parser = argparse.ArgumentParser(description='Writes main.lp')
print("Usage: python main_writer.py /path/to/transcript", file=sys.stderr) parser.add_argument('transcript')
sys.exit(1)
transcript_file = sys.argv[1] transcript_file = parser.parse_args().transcript
try: try:
transcript = util.parse_transcript(transcript_file) transcript = util.parse_transcript(transcript_file)
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
along with Graduation Audit System. If not, see <http://www.gnu.org/licenses/>. along with Graduation Audit System. If not, see <http://www.gnu.org/licenses/>.
""" """
from __future__ import print_function from __future__ import print_function
import sys import argparse
import util import util
...@@ -29,11 +29,14 @@ def main(): ...@@ -29,11 +29,14 @@ def main():
python req_writer.py <degree_type> <major> <degree_year> python req_writer.py <degree_type> <major> <degree_year>
ex: python req_writer.py bs cs 2015 ex: python req_writer.py bs cs 2015
""" """
if len(sys.argv) != 4: parser = argparse.ArgumentParser('Writes <bs/ba><major><year>req2.lp')
print("Usage: python req_writer.py <bs/ba> <major> <year>") parser.add_argument('degree_type', choices=['bs', 'ba'])
sys.exit() parser.add_argument('major')
parser.add_argument('degree_year')
(degree, major, year) = sys.argv[1:] args = parser.parse_args()
degree, major, year = args.degree_type, args.major, args.degree_year
directory = "%s/%s/%s/" % (degree, major, year) directory = "%s/%s/%s/" % (degree, major, year)
prefix = "%s%s" % (major, year) prefix = "%s%s" % (major, year)
......
...@@ -25,21 +25,23 @@ import os.path as path ...@@ -25,21 +25,23 @@ import os.path as path
Transcript = namedtuple( Transcript = namedtuple(
'Transcript', ['name', 'degree', 'major', 'year', 'spec', 'courses']) 'Transcript', ['name', 'degree', 'major', 'year', 'spec', 'courses'])
class CourseNotFoundError(Exception): class CourseNotFoundError(Exception):
""" """
Error raised an invalid course is encountered when Error raised an invalid course is encountered when
generating main.lp generating main.lp
""" """
msg = "Course {} was not found in the database.\n"\ msg = "Course {} was not found in the database.\n"\
"Make sure the class is spelled correctly or try removing this\n"\ "Make sure the class is spelled correctly or try removing this\n"\
"course and running the audit again." "course and running the audit again."
def __init__(self, course): def __init__(self, course):
self.msg = CourseNotFoundError.msg.format("'{}'".format(course)) self.msg = CourseNotFoundError.msg.format("'{}'".format(course))
def __str__(self): def __str__(self):
return self.msg return self.msg
def get_package_dir(): def get_package_dir():
""" """
Returns the directory that this package is located. Returns the directory that this package is located.
...@@ -111,7 +113,7 @@ def gen_main(transcript): ...@@ -111,7 +113,7 @@ def gen_main(transcript):
# the _taken(<name>,[c1,c2...cn]). atom # the _taken(<name>,[c1,c2...cn]). atom
taken_list = '_taken({},['.format(transcript.name) taken_list = '_taken({},['.format(transcript.name)
has_taken = str() # series of _hasTaken/2 atoms has_taken = str() # series of _hasTaken/2 atoms
try: try:
req = get_required_courses( req = get_required_courses(
transcript.degree, transcript.major, transcript.year) transcript.degree, transcript.major, transcript.year)
...@@ -119,13 +121,13 @@ def gen_main(transcript): ...@@ -119,13 +121,13 @@ def gen_main(transcript):
raise err raise err
valid_courses = get_courses() valid_courses = get_courses()
for course in transcript.courses: for course in transcript.courses:
# course not found in databse # course not found in databse
if not course in valid_courses: if not course in valid_courses:
raise CourseNotFoundError(course) raise CourseNotFoundError(course)
# include only those courses that could possibly # include only those courses that could possibly
# counted as electives i.e. those that are not required. # counted as electives i.e. those that are not required.
# in the 'taken list' (improves performance) # in the 'taken list' (improves performance)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment