コード例 #1
0
ファイル: makeabireports.py プロジェクト: gradgrind/Zeugs
def makeAbiReports (schoolyear, klass):
    """Build abitur grade reports using the grade tables defined by the
    configuration path FILE_ABITABLE.
    A template is used to construct the report files.
    The results – odt files – are placed according to the configuration
    path FILE_ABIREPORT, first removing any existing files in this folder.
    odt files are created from a template.
    Return a tuple: the output folder and a list of odt-file-names
    (without folder path).
    """
    sheetname = CONF.TABLES.ABITUR_RESULTS.GRADE_TABLE_SHEET
    infile = Paths.getYearPath (schoolyear, 'FILE_ABITABLE', klass=klass)
    filepath = Paths.getYearPath (schoolyear, 'FILE_ABIREPORT',
            klass=klass, make=-1)
    outdir = os.path.dirname (filepath)
    if os.path.isdir (outdir):
        shutil.rmtree (outdir)
    files = []
    for f in sorted (glob (infile)):
        # Extract pupil info from file-name
        try:
            _, index, pid, pname = f.rsplit ('.', 1) [0].rsplit ('-', 3)
        except:
            continue
        data = readTableData (f, table=sheetname)
        ofile = filepath.replace ('*', '{pnum}-{pid}-{name}'.format (
                pnum=index, pid=pid, name=pname))
        files.append (os.path.basename (makeAbiReport (ofile, data)))
    REPORT.Info (_MADENREPORTS, klass=klass, n=len (files), folder=outdir)
    return outdir, files
コード例 #2
0
def test_01():
    filepath = Paths.getYearPath(_year, 'FILE_SP_TEACHERS')
    REPORT.Test("\n  --------------\n%s" % repr(readSPTable(filepath)))
    filepath = Paths.getYearPath(_year, 'FILE_SP_CLASSES')
    REPORT.Test("\n  --------------\n%s" % repr(readSPTable(filepath)))
    filepath = Paths.getYearPath(_year, 'FILE_SP_SUBJECTS')
    REPORT.Test("\n  --------------\n%s" % repr(readSPTable(filepath)))
    filepath = Paths.getYearPath(_year, 'FILE_SP_LESSONS')
    REPORT.Test("\n  --------------\n%s" % repr(readSPTable(filepath)))
コード例 #3
0
ファイル: summary.py プロジェクト: gradgrind/Zeugs
def test_01():
    pdfBytes = tSheets(_year, _manager, _date)
    fpath = Paths.getYearPath(_year, 'FILE_TEACHER_REPORT_LISTS')
    with open(fpath, 'wb') as fh:
        fh.write(pdfBytes)
    REPORT.Info("Class and subject lists for each teacher:\n  {path}",
                path=fpath)
コード例 #4
0
ファイル: import_pupils.py プロジェクト: gradgrind/Zeugs
def importLatestRaw(schoolyear):
    allfiles = glob(Paths.getYearPath(schoolyear, 'FILE_PUPILS_RAW'))
    fpath = sorted(allfiles)[-1]
    REPORT.Info(_IMPORT_FROM, path=fpath)
    rpd = readRawPupils(schoolyear, fpath)
    updateFromRaw(schoolyear, rpd)
    return rpd
コード例 #5
0
def test_02():
    from glob import glob
    files = glob(Paths.getYearPath(_testyear, 'FILE_GRADE_TABLE',
                term='*'))
    for filepath in files:
        pgrades = readGradeTable(filepath)
        grades2db(_testyear, pgrades)
コード例 #6
0
def test_01 ():
    _term = '1'
    _date = '2016-01-29'
    for _klass, _pid in ('13', '200301'), ('12.RS', '200403'):
        klass = Klass(_klass)
        REPORT.Test("Reading basic grade data for class %s" % klass)
#TODO: This might not be the optimal location for this file.
        filepath = Paths.getYearPath(_testyear, 'FILE_GRADE_TABLE',
                    term=_term).replace('*', str(klass).replace('.', '-'))
        pgrades = readGradeTable(filepath)
        REPORT.Test(" ++ INFO: %s" % repr(pgrades.info))
        for pid, grades in pgrades.items():
            REPORT.Test("\n  -- %s: %s\n" % (pid, repr(grades)))

        REPORT.Test("\nReading template data for class %s" % klass)

        # Get the report type from the term and klass/stream
        _rtype = klass.match_map(CONF.GRADES.REPORT_TEMPLATES['_' + _term])
        gradedata = GradeReportData(_testyear, _rtype, klass)
        REPORT.Test("  Indexes:\n  %s" % repr(gradedata.sgroup2indexes))
        REPORT.Test("  Grade tags:\n  %s" % repr(gradedata.sgroup2sids))

        grademap = klass.match_map(CONF.MISC.GRADE_SCALE)
        REPORT.Test("\nTemplate grade map for pupil %s (using %s)" %
                (_pid, grademap))
        tagmap = gradedata.getTagmap(pgrades[_pid], "Pupil_%s" % _pid, grademap)
        REPORT.Test("  Grade tags:\n  %s" % repr(tagmap))
コード例 #7
0
def test_02():
    _term = '2'
    for ks in '10', '11.Gym', '11.RS-HS-_', '12.RS-HS', '12.Gym', '13':
        klass = Klass(ks)
        bytefile = makeGradeTable(_testyear, _term, klass, "Noten: 1. Halbjahr")
        filepath = Paths.getYearPath(_testyear, 'FILE_GRADE_FULL', make=-1,
                term=_term).replace('*', str(klass).replace('.', '-')) + '.xlsx'
        with open(filepath, 'wb') as fh:
            fh.write(bytefile)
        REPORT.Test(" --> %s" % filepath)
        bytefile = stripTable(_testyear, _term, klass, "Noten: 1. Halbjahr")
        filepath = Paths.getYearPath(_testyear, 'FILE_GRADE_INPUT', make=-1,
                term=_term).replace('*', str(klass).replace('.', '-')) + '.xlsx'
        with open(filepath, 'wb') as fh:
            fh.write(bytefile)
        REPORT.Test(" --> %s" % filepath)
コード例 #8
0
def test_01():
    klass = Klass('13')
    bytefile = choiceTable(_testyear, klass)
    filepath = Paths.getYearPath(_testyear, 'FILE_SUBJECT_CHOICE_TABLE',
            make=-1).replace('*', str(klass).replace('.', '-')) + '.xlsx'
    with open(filepath, 'wb') as fh:
        fh.write(bytefile)
    REPORT.Test(" --> %s" % filepath)
コード例 #9
0
ファイル: import_pupils.py プロジェクト: gradgrind/Zeugs
def test_04():
    """Export pupil data to a spreadsheet table.
    """
    REPORT.Test("Exporting pupil data for school-year %d" % _testyear)
    fpath = os.path.join(Paths.getYearPath(_testyear, 'DIR_SCHOOLDATA'),
                         '_test', 'export_pupils_0')
    classes = exportPupils(_testyear, fpath)
    REPORT.Test("Exported to %s" % fpath)
コード例 #10
0
 def __init__(self, schoolyear):
     l = importLessons(schoolyear)
     self.newdata = l[1]
     self.tid2name = l[2]
     self.badsubjects = l[3]
     self.filepath = Paths.getYearPath(_year, 'FILE_SUBJECTS')
     self._wb = load_workbook(self.filepath + '.xlsx')
     self._ws = self._wb.active
     self.makeStyle()
コード例 #11
0
ファイル: import_pupils.py プロジェクト: gradgrind/Zeugs
def test_03():
    """Import pupil data – an old version (to later test updates).
    The data is in a spreadsheet table.
    """
    fpath = os.path.join(Paths.getYearPath(_testyear, 'DIR_SCHOOLDATA'),
                         '_test', 'import_pupils_0')
    REPORT.Test("Importing pupil data for school-year %d from %s" %
                (_testyear, fpath))
    classes = importPupils(_testyear, fpath)
    REPORT.Test("CLASSES/PUPILS: %s" % repr(classes))
コード例 #12
0
ファイル: import_pupils.py プロジェクト: gradgrind/Zeugs
def test_06():
    """Compare new raw data with saved complete version:
    Import complete version, then perform update from raw data.
    """
    REPORT.Test("\n --1-----------------\n RESET PUPILS TABLE")
    fpath = os.path.join(Paths.getYearPath(_testyear, 'DIR_SCHOOLDATA'),
                         '_test', 'Schuelerdaten_1')
    REPORT.Test("Importing pupil data for school-year %d from %s" %
                (_testyear, fpath))

    REPORT.Test("\n --2-----------------\n COMPARE UPDATES:")
    importLatestRaw(_testyear)
コード例 #13
0
ファイル: formattedmatrix.py プロジェクト: gradgrind/Zeugs
    def __init__(self, schoolyear, filetag, klass=None, **kargs):
        """<filetag> is an entry in the PATHS config file, which may
        contain '*' (which will be replaced by the class).
        If there is already a file with this path, this will be read in
        using <readDBTable> (which adds a file extension if necessary).
        """
        self.schoolyear = schoolyear
        self.klass = klass
        # Configuration info for the options table
        self.fieldnames = CONF.TABLES.COURSE_PUPIL_FIELDNAMES

        self.filepath = Paths.getYearPath(schoolyear,
                                          filetag,
                                          make=-1,
                                          **kargs).replace('*', klass)
コード例 #14
0
ファイル: import_pupils.py プロジェクト: gradgrind/Zeugs
def test_02():
    """
    Initialise PUPILS table from "old" raw data (creation from scratch,
    no pre-existing table).
    """
    db = DB(_testyear, 'RECREATE')
    fpath = os.path.join(Paths.getYearPath(_testyear, 'DIR_SCHOOLDATA'),
                         '_test', 'pupil_data_0_raw')
    REPORT.Test(
        "Initialise with raw pupil data for school-year %d from:\n  %s" %
        (_testyear, fpath))
    rpd = readRawPupils(_testyear, fpath)
    for klass in sorted(rpd):
        REPORT.Test("\n +++ Class %s" % klass)
        for row in rpd[klass]:
            REPORT.Test("   --- %s" % repr(row))
    updateFromRaw(_testyear, rpd)
    db.renameTable('PUPILS', 'PUPILS0')
    db.deleteIndexes('PUPILS0')
    REPORT.Test("Saved in table PUPILS0")
コード例 #15
0
ファイル: attendance.py プロジェクト: gradgrind/Zeugs
def readHols (schoolyear):
    """Return a <set> of <datetime.date> instances for all valid dates in the
    holidays file (configuration item "HOLIDAYS"). The dates are in isoformat
    (YYYY-MM-DD), but also MM-DD is acceptable, in which case the year will be
    added automatically (from the current school year).
    """
    deltaday = datetime.timedelta (days=1)
    kalinfo = ConfigFile (Paths.getYearPath (schoolyear, 'FILE_HOLIDAYS'))
    hols = set ()
    for d0 in kalinfo.SINGLE_DAYS.split ('|'):
        d = getDate (schoolyear, d0, dateformat=False)
        if d:
            hols.add (d)
        else:
            raise RuntimeError ("Date Error")

    for r0 in kalinfo.RANGES.split ('|'):
        try:
            d01, d02 = kalinfo [r0].split ('|')
        except:
            REPORT.Fail ("Ungültige Ferienzeit: %s" % r0)
        d1 = getDate (schoolyear, d01, dateformat=False)
        d2 = getDate (schoolyear, d02, dateformat=False)
        if (not d1) or (not d2):
            raise RuntimeError ("Date Error")
        if d1 >= d2:
            REPORT.Fail (("Ungültige Ferienangabe: %s"
                    "Startdatum ist nach dem Enddatum") % item)
            continue
        while True:
            hols.add (d1)
            d1 += deltaday
            if d1 > d2:
                break

    return hols
コード例 #16
0
ファイル: attendance.py プロジェクト: gradgrind/Zeugs
 def save (self):
     filepath = Paths.getYearPath (self._year, 'FILE_ATTENDANCE_TABLE',
             make=-1, klass=self._class)
     self._table.save (filepath)
コード例 #17
0
def importLessons(schoolyear):
    ### classes
    class2cid = {}
    for row in readSPTable(Paths.getYearPath(schoolyear, 'FILE_SP_CLASSES')):
        #klass = row.CLASS
        #ctag = row.CTAG
        #cid = row.CID
        class2cid[row.CLASS] = row.CID

    ### subjects
    stag2sid = {}
    stag2name = {}
    for row in readSPTable(Paths.getYearPath(schoolyear, 'FILE_SP_SUBJECTS')):
        #sname = row.SNAME
        stag = row.SP
        #sid = row.SID
        if row.SID:
            stag2sid[stag] = row.SID
        stag2name[stag] = row.SNAME

    ### teachers
    tname2tid = {}
    tid2tname = {}
    for row in readSPTable(Paths.getYearPath(schoolyear, 'FILE_SP_TEACHERS')):
        #tname = row.TNAME
        #tid = row.TID
        #tclass = row.TCLASS # space-separated list
        #nz = row.NZ
        tid = (_TIDX + row.TID) if row.NZ else row.TID
        tname2tid[row.TNAME] = tid
        tid2tname[tid] = row.TNAME

    ### lessons
    table = {}
    sidtable = {}
    badsubjects = {}
    badclasses = set()
    badteachers = {}
    for row in readSPTable(Paths.getYearPath(schoolyear, 'FILE_SP_LESSONS')):
        # There can be a list of teachers
        #tnames = row.TNAMES
        #stag = row.SP
        #klass = row.CLASS
        tnames = [t.strip() for t in row.TNAMES.split(',')]
        stag = row.SP

        # The class can be a list.
        classes = []
        for c in row.CLASS.split(','):
            try:
                klass = class2cid[c.strip()]
            except KeyError:
                badclasses.add(c)
                continue
            classes.append(klass)
        if len(classes) == 0:
            continue

        try:
            sid = stag2sid[stag]
        except KeyError:
            try:
                badsubjects[stag2name[stag]].append(klass)
            except:
                badsubjects[stag2name[stag]] = [klass]
            continue

        for tname in [t.strip() for t in row.TNAMES.split(',')]:
            try:
                tid = tname2tid[tname]
            except KeyError:
                try:
                    badteachers[tname].append((row.CLASS, stag))
                except:
                    badteachers[tname] = [(row.CLASS, stag)]
                continue
            for klass in classes:
                try:
                    t2s = table[klass]
                except:
                    table[klass] = {tid: {sid}}
                else:
                    try:
                        t2s[tid].add(sid)
                    except:
                        t2s[tid] = {sid}

                try:
                    k2c = sidtable[sid]
                except:
                    sidtable[sid] = {klass: {tid}}
                else:
                    try:
                        k2c[klass].add(tid)
                    except:
                        k2c[klass] = {tid}

    if badclasses:
        REPORT.Warn(_UNKNOWN_CLASSES, cname=badclasses)
    for t, data in badteachers.items():
        REPORT.Warn(_BADTNAME, tname=t, data=data)

    return table, sidtable, tid2tname, badsubjects
コード例 #18
0
ファイル: summary.py プロジェクト: gradgrind/Zeugs
def test_02():
    pdfBytes = ksSheets(_year, _manager, _date)
    fpath = Paths.getYearPath(_year, 'FILE_CLASS_REPORT_LISTS')
    with open(fpath, 'wb') as fh:
        fh.write(pdfBytes)
    REPORT.Info("Fach-Lehrer-Zuordnung der Klassen:\n  {path}", path=fpath)
コード例 #19
0
ファイル: makeabireports.py プロジェクト: gradgrind/Zeugs
def makeAbiTables (schoolyear, klass, date):
    """Build grade tables (one for each student) for the final Abitur
    grades.
    These tables are used to prepare the grades for (automatic) entry
    into the certificates.
    The new tables are placed in a subfolder of the normal folder (see
    configuration file PATHS: FILE_ABITABLE_NEW). This is to avoid
    accidentally overwriting existing tables which already contain data.
    Most of the necessary "cleverness" is built into the template file.
    """
    template = Paths.getUserPath ('FILE_ABITUR_GRADE_TEMPLATE')
    outpath = Paths.getYearPath (schoolyear, 'FILE_ABITABLE_NEW', klass=klass)
    for f in glob (os.path.join (os.path.dirname (outpath), '*')):
        os.remove (f)
    outpath += '.xlsx'

    sheetname = CONF.TABLES.ABITUR_RESULTS.GRADE_TABLE_SHEET
    FrHr = {}
    for v in CONF.TABLES.ABITUR_RESULTS.P_FrHr:
        k, v = v.split (':')
        FrHr [k] = v

    ncourses = CONF.TABLES.ABITUR_RESULTS.NCOURSES.nat ()

    courseTables = CourseTables (schoolyear)
    pupils = Pupils (schoolyear).classPupils (klass, date)
    sid2info = courseTables.filterGrades (klass, realonly=True)
    subjects = []
    for sid, sinfo in sid2info.items ():
        subjects.append ((sid, sinfo.COURSE_NAME))

    teacherMatrix = FormattedMatrix.readMatrix (schoolyear,
            'FILE_CLASS_SUBJECTS', klass)

    i = 0       # pid index for ordering files
    files = []  # list of created files (full paths)
    for pdata in pupils:
        pid = pdata ['PID']
        pname = pdata.name ()
        i += 1
        filepath = outpath.replace ('*', '{pnum:02d}-{pid}-{name}'.format (
                pnum=i, pid=pid,
                name=Paths.asciify (pname)))

        fields = {'YEAR': str (schoolyear),
                'LASTNAME': pdata ['LASTNAME'],
                'FIRSTNAMES': pdata ['FIRSTNAMES'],
                'DOB_D': pdata ['DOB_D'],
                'POB': pdata ['POB'],
                'HOME': pdata ['HOME']}
        try:
            fields ['FrHr'] = FrHr [pdata ['SEX']]
        except:
            REPORT.Error (_BADSEXFIELD, klass=klass, pname=pname,
                    sex=pdata ['SEX'])
            fields ['FrHr'] = ' '

        f = 0
        for sid, sname in subjects:
            if not teacherMatrix [pid][sid]:
                continue
            f += 1
            fields ['F' + str (f)] = sname.split ('|') [0].rstrip ()
        if ncourses and f != ncourses:
            REPORT.Error (_NOTNCOURSES, klass=klass, pname=pname, n=f,
                    nc0=ncourses)
            continue

        unused = XLS_template (filepath, template, fields,
                sheetname=sheetname)
        files.append (filepath)

    REPORT.Info (_MADENTABLES, klass=klass, n=len (files))
    return files