예제 #1
0
def _gen_grades():
    filedir = os.path.dirname(os.path.abspath(__file__))

    if common.DEBUG: studentdir = './test/students'
    else: studentdir = '../../../students'
    studentdir = os.path.abspath(os.path.join(filedir, studentdir))

    assignmentsfile = os.path.join(studentdir, 'assignments.gen.py')
    scandir = os.path.join(studentdir, 'scans')

    # .........................................................................

    name2cwid = {
        v['github'].lower(): k
        for k, v in students.students.items() if 'github' in v
    }

    grades = {
        cwid: OrderedDict([
            ('extra credit', 0),
            ('overall', None),
            ('predictions', OrderedDict()),
        ] + [((
            g,
            s,
        ), OrderedDict()) for g, ss in standards.groups.items() for s in ss])
        for cwid in students.students
    }

    # .........................................................................
    # from github

    github = github3.GitHub()

    try:
        for r in sorted([r.name for r in github.iter_user_repos(common.org)]):
            if r in ('course-materials', ): continue
            assignment = 'a' + r[-2:]

            for cwid in students.students:
                grades[cwid][('assignment completion', '')][assignment] = None

            for pr in github.iter_repo_issues(common.org, r, state='all'):
                name = pr.user.login
                if name not in name2cwid: continue

                grades[name2cwid[name]] \
                      [('assignment completion', '')] \
                      [assignment] = True

        with open(assignmentsfile, 'w') as f:
            f.write(
                repr({
                    cwid: grades[cwid][('assignment completion', '')]
                    for cwid in grades
                }))

    except (requests.exceptions.ConnectionError, github3.models.GitHubError):
        assignments = eval(open(assignmentsfile).read())
        none = OrderedDict([(a, None)
                            for a in assignments[list(assignments.keys())[0]]])
        for cwid in grades:
            if cwid in assignments:
                grades[cwid][('assignment completion', '')] = assignments[cwid]
            else:
                grades[cwid][('assignment completion', '')] = none

    # .........................................................................
    # from scans

    for d in sorted(os.listdir(scandir)):
        if d.startswith('.'): continue

        i = Namespace()

        (i.date, i.assessment, i.standards) = d.split(',', maxsplit=2)
        i.standards = [standards.lookup(s) for s in i.standards.split(',')]

        for cwid in students.students:
            for sta in i.standards:
                grades[cwid][sta][i.assessment] = None

        for f in os.listdir(os.path.join(scandir, d)):
            if f.startswith('.'): continue

            (i.name, i.scores) = \
                f.split('.',maxsplit=1)[0].split(',', maxsplit=1)
            i.scores = i.scores.split(',')

            if '' in i.scores:
                raise Error('WARNING: empty score in' + ' "' +
                            os.path.join(d, f) + '"')
            if len(i.scores) != len(i.standards):
                raise Error('WARNING: mismatch in number of scores for' +
                            ' "' + os.path.join(d, f) + '"')

            i.scores = [
                None if s == 'x' else
                3.5 if s == '5' else 3.75 if s == '7' else int(s)
                for s in i.scores
            ]

            for sta, sco in zip(i.standards, i.scores):
                grades[students.lookup(i.name)][sta][i.assessment] = sco

    # .........................................................................
    # from file

    private = common.importfile(os.path.join(studentdir, 'grades.py'))

    for cwid in private.grades:
        if cwid in grades: grades[cwid].update(private.grades[cwid])
        else: grades[cwid] = private.grades[cwid]

    # .........................................................................

    for cwid in grades:
        overall = 0
        maximum = 0

        for sta, assessments in grades[cwid].items():
            if isinstance(sta, str): continue

            scos = [sco for sco in assessments.values() if sco is not None]

            if sta == ('assignment completion', ''):
                sco = len(scos) / len(assessments) if len(
                    assessments) > 0 else 0
                assessments['overall'] = sco
                overall += sco * standards.multipliers[sta]
                maximum += standards.multipliers[sta]
                continue

            if len(scos) == 0:
                assessments['overall'] = None

            else:
                if len(scos) == 1 or scos[-1] >= scos[-2]:
                    sco = scos[-1]

                else:  # scos[-1] < scos[-2]
                    sco = [
                        sco for sco in [1, 2, 3, 3.5, 3.75, 4]
                        if (scos[-1] + scos[-2]) / 2 <= sco
                    ][0]

                assessments['overall'] = sco
                if sco >= 3:
                    overall += sco / 4 * standards.multipliers[sta]
                maximum += standards.multipliers[sta]

        ec = grades[cwid]['extra credit'] * 0.002

        if grades[cwid]['overall'] is None:
            grades[cwid]['overall'] = overall + ec

        grades[cwid]['predictions']['current grade'] = grades[cwid]['overall']
        if maximum == 0:
            grades[cwid]['predictions']['average'] = None
            grades[cwid]['predictions']['maximum without reassessing'] = None
        else:
            grades[cwid]['predictions']['average'] = overall / maximum
            grades[cwid]['predictions']['maximum without reassessing'] = \
                1 - maximum + overall + ec

    # .........................................................................

    return grades
예제 #2
0
def _gen_students():

    filedir = os.path.dirname(os.path.abspath(__file__))

    if common.DEBUG: studentdir = './test/students'
    else: studentdir = '../../../students'
    studentdir = os.path.abspath(os.path.join(filedir, studentdir))

    titandir = os.path.join(studentdir, 'titan-online')

    # .........................................................................

    # - for data copied and pasted from Titan Online into TextEdit, and saved
    #   as HTML
    student = re.compile(
        r'<tr>' + r'.*?<td.*?</td>' + r'.*?<td.*?</td>' +
        r'.*?<td.*?>(?P<cwid>\d{9})<.*?</td>' +
        r'.*?<td.*?<a href="mailto:(?P<email>[^"]+)">(?P<name>[^<]+)<.*?</td>'
        + r'.*?<td.*?</td>' + r'.*?<td.*?</td>' + r'.*?<td.*?</td>' +
        r'.*?<td.*?</td>' + r'.*?<td.*?</td>' + r'.*?</tr>*?',
        re.DOTALL,
    )

    students = {}

    # .........................................................................

    for entry in os.scandir(titandir):
        if entry.name.startswith('.') or not entry.is_file():
            continue

        path = os.path.join(titandir, entry.name)
        for m in student.finditer(open(path).read()):
            section = entry.name.split('.')[0]
            cwid = m.group('cwid')
            email = m.group('email')
            name = ' '.join(reversed(m.group('name').split(',', maxsplit=1)))

            alias = name.split()
            if len(alias) == 1:
                alias = alias[0]
            elif alias[-1] in (
                    'I',
                    'II',
                    'III',
                    'IV',
            ) and len(alias) > 2:
                alias = ' '.join([alias[0], alias[-2]])
            else:
                alias = ' '.join([alias[0], alias[-1]])

            students[cwid] = {
                'section': section,
                'email': email,
                'name': name,
                'alias': alias,
            }

    # .........................................................................

    private = common.importfile(os.path.join(studentdir, 'students.py'))

    for cwid in private.students:
        if cwid in students: students[cwid].update(private.students[cwid])
        else: students[cwid] = private.students[cwid]

    # .........................................................................

    return students
예제 #3
0
# Project located at <https://github.com/benblazak/text-processing-utilities>
# -----------------------------------------------------------------------------
"""A script to print out some subset of student names and emails, in a format
suitable for the `openEmail` function in `open-email.applescript`.
"""

import os.path
import sys

import common

# .............................................................................

filedir = os.path.dirname(os.path.abspath(__file__))

students = common.importfile(os.path.join(filedir, '../students.py'))

# -----------------------------------------------------------------------------

if len(sys.argv) == 1:
    arg = 'all'
elif len(sys.argv) == 2:
    arg = sys.argv[1]
else:
    print('ERROR: too many arguments')
    sys.exit(1)

# .............................................................................

vs = students.students.values()
예제 #4
0
"""A script to print out some subset of student names and emails, in a format
suitable for the `openEmail` function in `open-email.applescript`.
"""

import os
import os.path
import subprocess
import sys
import textwrap
import time

import common

filedir = os.path.dirname(os.path.abspath(__file__))

students = common.importfile( os.path.join(filedir, '../students.py') )

# -----------------------------------------------------------------------------

if len(sys.argv) == 1:
    arg = 'all'
elif len(sys.argv) == 2:
    arg = sys.argv[1]
else:
    print('ERROR: too many arguments')
    sys.exit(1)

# .............................................................................

cwids = []
def _gen_students():

    filedir = os.path.dirname(os.path.abspath(__file__))

    if common.DEBUG: studentdir = './test/students'
    else:            studentdir = '../../../students'
    studentdir = os.path.abspath(os.path.join(filedir, studentdir))

    titandir = os.path.join(studentdir, 'titan-online')

    # .........................................................................

    # - for data copied and pasted from Titan Online into TextEdit, and saved
    #   as HTML
    student = re.compile(
        r'<tr>'
        + r'.*?<td.*?</td>'
        + r'.*?<td.*?</td>'
        + r'.*?<td.*?>(?P<cwid>\d{9})<.*?</td>'
        + r'.*?<td.*?<a href="mailto:(?P<email>[^"]+)">(?P<name>[^<]+)<.*?</td>'
        + r'.*?<td.*?</td>'
        + r'.*?<td.*?</td>'
        + r'.*?<td.*?</td>'
        + r'.*?<td.*?</td>'
        + r'.*?<td.*?</td>'
        + r'.*?</tr>*?',
        re.DOTALL,
    )

    students = {}

    # .........................................................................

    for entry in os.scandir(titandir):
        if entry.name.startswith('.') or not entry.is_file():
            continue

        path = os.path.join(titandir, entry.name)
        for m in student.finditer(open(path).read()):
            section = entry.name.split('.')[0]
            cwid = m.group('cwid')
            email = m.group('email')
            name = ' '.join(reversed( m.group('name').split(',', maxsplit=1) ))

            alias = name.split()
            if len(alias) == 1:
                alias = alias[0]
            elif alias[-1].lower() in ( 'i', 'ii', 'iii', 'iv', 'v', 'vi', 'vii', 'jr' ) and len(alias) > 2:
                alias = ' '.join([ alias[0], alias[-2] ])
            else:
                alias = ' '.join([ alias[0], alias[-1] ])

            students[cwid] = {
                'section': section,
                'email': email,
                'name': name,
                'alias': alias,
            }

    # .........................................................................

    private = common.importfile(os.path.join(studentdir, 'students.py'))

    for cwid in private.students:
        if cwid in students: students[cwid].update(private.students[cwid])
        else:                students[cwid] = private.students[cwid]

    # .........................................................................

    return students
예제 #6
0
def _gen_grades():
    filedir = os.path.dirname(os.path.abspath(__file__))

    if common.DEBUG: studentdir = './test/students'
    else:            studentdir = '../../../students'
    studentdir = os.path.abspath(os.path.join(filedir, studentdir))

    assignmentsfile = os.path.join(studentdir, 'assignments.gen.py')
    scandir = os.path.join(studentdir, 'scans')

    # .........................................................................

    name2cwid = {
        v['github'].lower():k
        for k,v in students.students.items()
        if 'github' in v
    }

    grades = {
        cwid: OrderedDict( [
            ('extra credit', 0),
            ('overall', None),
            ('predictions', OrderedDict()),
        ] + [
            ((g,s,),OrderedDict())
            for g,ss in standards.groups.items()
            for s in ss
        ] )
        for cwid in students.students
    }

    # .........................................................................
    # from github

    github = github3.GitHub()

    try:
        for r in sorted([ r.name for r in github.iter_user_repos(common.org) ]):
            if r in ( 'course-materials', ): continue
            assignment = 'a' + r[-2:]

            for cwid in students.students:
                grades[cwid][('assignment completion', '')][assignment] = None

            for pr in github.iter_repo_issues(common.org, r, state='all'):
                name = pr.user.login.lower()
                if name not in name2cwid: continue

                grades[name2cwid[name]] \
                      [('assignment completion', '')] \
                      [assignment] = True

        with open(assignmentsfile, 'w') as f:
            f.write(repr({
                cwid: grades[cwid][('assignment completion', '')]
                for cwid in grades
            }))

    except (requests.exceptions.ConnectionError, github3.models.GitHubError):
        assignments = eval(open(assignmentsfile).read())
        none = OrderedDict([
            (a, None) for a in assignments[list(assignments.keys())[0]]
        ])
        for cwid in grades:
            if cwid in assignments:
                grades[cwid][('assignment completion', '')] = assignments[cwid]
            else:
                grades[cwid][('assignment completion', '')] = none

    # .........................................................................
    # from scans
    
    for d in sorted(os.listdir(scandir)):
        if d.startswith('.'): continue

        i = Namespace()

        (i.date, i.assessment, i.standards) = d.split(',', maxsplit=2)
        i.standards = [ standards.lookup(s) for s in i.standards.split(',') ]

        for cwid in students.students:
            for sta in i.standards:
                grades[cwid][sta][i.assessment] = None

        for f in os.listdir(os.path.join(scandir, d)):
            if f.startswith('.'): continue

            (i.name, i.scores) = \
                f.split('.',maxsplit=1)[0].split(',', maxsplit=1)
            i.scores = i.scores.split(',')

            if '' in i.scores:
                raise Error(
                    'WARNING: empty score in'
                    + ' "' + os.path.join(d, f) + '"' )
            if len(i.scores) != len(i.standards):
                raise Error(
                    'WARNING: mismatch in number of scores for'
                    + ' "' + os.path.join(d, f) + '"' )

            i.scores = [
                None if s == 'x' else
                3.5 if s == '5' else
                3.75 if s == '7' else
                int(s)
                for s in i.scores
            ]

            for sta,sco in zip(i.standards,i.scores):
                grades[students.lookup(i.name)][sta][i.assessment] = sco

    # .........................................................................
    # from file

    private = common.importfile(os.path.join(studentdir, 'grades.py'))

    for cwid in private.grades:
        if cwid in grades: grades[cwid].update(private.grades[cwid])
        else:              grades[cwid] = private.grades[cwid]

    # .........................................................................

    for cwid in grades:
        overall = 0
        maximum = 0

        for sta,assessments in grades[cwid].items():
            if isinstance(sta, str): continue

            scos = [ sco for sco in assessments.values() if sco is not None ]

            if sta == ('assignment completion', ''):
                sco = len(scos)/len(assessments) if len(assessments) > 0 else 0
                assessments['overall'] = sco
                overall += sco * standards.multipliers[sta]
                maximum += standards.multipliers[sta]
                continue

            if len(scos) == 0:
                assessments['overall'] = None

            else:
                if len(scos) == 1 or scos[-1] >= scos[-2]:
                    sco = scos[-1]

                else:  # scos[-1] < scos[-2]
                    sco = [ sco for sco in [1, 2, 3, 3.5, 3.75, 4]
                            if (scos[-1]+scos[-2])/2 <= sco ][0]

                assessments['overall'] = sco
                if sco >= 3:
                    overall += sco / 4 * standards.multipliers[sta]
                maximum += standards.multipliers[sta]

        ec = grades[cwid]['extra credit'] * 0.002

        if grades[cwid]['overall'] is None:
            grades[cwid]['overall'] = overall + ec

        grades[cwid]['predictions']['current grade'] = grades[cwid]['overall']
        if maximum == 0:
            grades[cwid]['predictions']['average'] = None
            grades[cwid]['predictions']['maximum without reassessing'] = None
        else:
            grades[cwid]['predictions']['average'] = overall / maximum
            grades[cwid]['predictions']['maximum without reassessing'] = \
                1 - maximum + overall + ec

    # .........................................................................

    return grades