small update to get better query mode working
This commit is contained in:
parent
ef011cda55
commit
d41712e010
4 changed files with 164 additions and 234 deletions
|
@ -1,11 +1,11 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
CourseBuilder
|
||||
CourseBuilder
|
||||
|
||||
Coursebuilder is a preprocessor tool for [pandoc](https://pandoc.org)
|
||||
to generate multi-lingual curricula documentation tables from
|
||||
structured representations as a flatfile database. Data scheme and
|
||||
Coursebuilder is a preprocessor tool for [pandoc](https://pandoc.org)
|
||||
to generate multi-lingual curricula documentation tables from
|
||||
structured representations as a flatfile database. Data scheme and
|
||||
actual values are kept in YAML files in order to version them with git.
|
||||
|
||||
"""
|
||||
|
@ -27,7 +27,7 @@ class CourseBuilder:
|
|||
@staticmethod
|
||||
def generate(args):
|
||||
if args.schema and args.meta:
|
||||
|
||||
|
||||
# get actual fields
|
||||
actual_fields = None
|
||||
|
||||
|
@ -37,8 +37,8 @@ class CourseBuilder:
|
|||
actual_fields = yaml.load(ff,Loader=yaml.Loader)['fields']
|
||||
else:
|
||||
# seem we have a list or None
|
||||
actual_fields = args.fields
|
||||
|
||||
actual_fields = args.fields
|
||||
|
||||
# get schema
|
||||
schema = None
|
||||
with open(args.schema) as f:
|
||||
|
@ -66,12 +66,12 @@ class CourseBuilder:
|
|||
title_template=args.title,
|
||||
first_colwidth=args.leftcol)
|
||||
elif args.query:
|
||||
|
||||
|
||||
lot = schema.to_short_dict(
|
||||
meta=yaml.load(fm,Loader=yaml.Loader),
|
||||
fields=actual_fields,
|
||||
lang=args.lang)
|
||||
|
||||
|
||||
result_df.append(pd.DataFrame([lot]))
|
||||
else:
|
||||
MarkdownGenerator.generate_table(
|
||||
|
@ -85,16 +85,17 @@ class CourseBuilder:
|
|||
|
||||
# query mode
|
||||
if args.query and len(result_df):
|
||||
|
||||
|
||||
# got the list
|
||||
df = pd.concat(result_df,ignore_index=True)
|
||||
|
||||
|
||||
# generate a dataframe
|
||||
df_q = df.query(args.query)
|
||||
|
||||
# generate a compound column --query-compound column:sum
|
||||
if args.query_compound:
|
||||
df_q.loc[:,'form-of-instruction.sum'] = df_q['form-of-instruction'].apply(lambda x: sum(list(x.values())))
|
||||
print(args.query_compound)
|
||||
df_q.loc[:,'form-of-instruction.sum'] = df_q['form-of-instruction'].apply(lambda x: sum(list(x.values())))
|
||||
|
||||
# --query-sort is parameterized as min:credits - hence direction:column
|
||||
if args.query_sort:
|
||||
|
@ -111,7 +112,8 @@ class CourseBuilder:
|
|||
|
||||
# set value transforms
|
||||
if args.query_template:
|
||||
|
||||
|
||||
# no idea yet how to parameterize this
|
||||
ww = 'written'
|
||||
#df_q['form-of-exam'] = 'Schriftlich' if df_q.loc[:,'form-of-exam'] == 'written' else 'was anderes'
|
||||
# mm = Template("{'written':'S','oral':'mündlich'}[${v}]")?
|
||||
|
@ -121,8 +123,8 @@ class CourseBuilder:
|
|||
df_summary = pd.DataFrame([{
|
||||
'sum.credits': df_q['credits'].sum()
|
||||
}])
|
||||
|
||||
# set labels
|
||||
|
||||
# set labels directly!
|
||||
if args.query_labels:
|
||||
df_q.columns = args.query_labels
|
||||
|
||||
|
@ -135,7 +137,7 @@ class CourseBuilder:
|
|||
|
||||
@staticmethod
|
||||
def run():
|
||||
|
||||
|
||||
# arguments
|
||||
parser = ArgumentParser(description='versatile curricula generator')
|
||||
|
||||
|
@ -144,7 +146,7 @@ class CourseBuilder:
|
|||
parser.add_argument('-l','--lang',help="Language to parse from meta file (use de or en)",default='de')
|
||||
parser.add_argument('-f','--fields',help="Fields to be used, the table will be build accordingly",action="extend", nargs="+", type=str)
|
||||
parser.add_argument('-s','--schema', help="using provided schema")
|
||||
|
||||
|
||||
# query mode
|
||||
parser.add_argument('-q','--query', type=str, default=None, help="compound query to select items")
|
||||
parser.add_argument('-qs','--query-sort',type=str,default=None,help="sort query with a min/max over a column like min:credits")
|
||||
|
@ -152,8 +154,8 @@ class CourseBuilder:
|
|||
parser.add_argument('-qf','--query-filter',type=str,default=[],action="extend", nargs="+",help="filter final list of columns for output")
|
||||
parser.add_argument('-ql','--query-labels',type=str,default=[],action="extend", nargs="+",help="new labels for query like")
|
||||
parser.add_argument('-qt','--query-template',type=str,default=[],action="extend", nargs="+",help="templates for values in the form of {value}")
|
||||
|
||||
|
||||
|
||||
|
||||
# create pagebreaks
|
||||
parser.add_argument('-p','--pagebreak',action="store_true",help="add a pagebreak after each module")
|
||||
parser.add_argument('--title',type=str,default=None,help="template for title - use curly brackets (i.e. {}) to mark where the title string is inserted")
|
||||
|
@ -163,22 +165,22 @@ class CourseBuilder:
|
|||
parser.add_argument('--template',type=str,default=None,help='defines a template to be used with fields')
|
||||
parser.add_argument('-o','--out',type=str,default=None,help='set the output type')
|
||||
parser.add_argument('--legacy',action="store_true",help="use legacy generator mode for compatibility")
|
||||
|
||||
|
||||
parser.add_argument('--leftcol',type=int,default=35,help='maximum size of left column')
|
||||
|
||||
# get arguments
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
if args.table_gen:
|
||||
|
||||
tg = TableGenerator()
|
||||
tg = TableGenerator()
|
||||
tg.generate_table(args.table_gen)
|
||||
|
||||
return
|
||||
|
||||
# book mode with predefined setting from a book file
|
||||
if args.book and args.schema:
|
||||
|
||||
|
||||
with open(args.book) as bf:
|
||||
|
||||
actual_fields = []
|
||||
|
@ -199,13 +201,13 @@ class CourseBuilder:
|
|||
|
||||
# gernerate section wise parts
|
||||
if 'modules' in section:
|
||||
|
||||
|
||||
# override fields
|
||||
args.fields = actual_fields
|
||||
|
||||
|
||||
# expand filenames to be relative to the book
|
||||
args.meta = [os.path.join(os.path.dirname(book_path),mod_path) for mod_path in section['modules']]
|
||||
|
||||
|
||||
CourseBuilder.generate(args=args)
|
||||
|
||||
# verbose command line mode
|
||||
|
@ -217,6 +219,6 @@ class CourseBuilder:
|
|||
# run as main
|
||||
if __name__ == '__main__':
|
||||
# recommended setting for pandas
|
||||
pd.options.mode.copy_on_write = True
|
||||
pd.options.mode.copy_on_write = True
|
||||
# run
|
||||
CourseBuilder.run()
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
# Concept
|
||||
# concept
|
||||
|
||||
The concept behind coursebuilder is to store curricula descriptions in `YAML` files that can be versioned in a git repository. Unlike classic databases an observable and well defined versioning is paramount in these descriptions as they are the legal foundation for study and exam regulations.
|
||||
The concept behind coursebuilder is to store curricula descriptions in `YAML` files that can be versioned in a git repository. Unlike classic databases, an observable and well defined versioning is paramount in these descriptions as they are the legal foundation for study and exam regulations.
|
||||
|
||||
The following pieces play together here:
|
||||
|
||||
- `schema` files, usually a `schema.yaml`
|
||||
- `mod` files, usually something along the lines of `mod.coursecode.yaml`
|
||||
- `mod` files, usually something along the lines of `mod.coursecode.yaml`
|
||||
- `book` files describing a whole regulation set and course global details
|
||||
- some sort of transformation with `coursebuilder` into Markdown that is piped through [pandoc](https://pandoc.org) in order to generate PDF, HTML and other representation from this code
|
||||
- some sort of transformation with `coursebuilder` into Markdown that is piped through [pandoc](https://pandoc.org) in order to generate PDF, HTML and other representation from this code
|
||||
|
||||
# schema files
|
||||
# schema files
|
||||
|
||||
Schema files are responsible to describe the used structures in a database. The following datatypes are supported:
|
||||
|
||||
- `str` a simple string, can be accompanied with a `template`
|
||||
- `enum` a classic enum datatype with a fixed set of values
|
||||
- `num` a numeric datatype
|
||||
- `num` a numeric datatype
|
||||
- `multinum` an array type with the possibility to `spec` each value
|
||||
- `multikey` a key-value type with additional numeric data associated with each key instance
|
||||
- `multikey` a key-value type with additional numeric data associated with each key instance
|
||||
|
||||
# mod files (modules)
|
||||
|
||||
|
@ -31,11 +31,11 @@ Modules describe a course in detail and implement an instance of the schema file
|
|||
```yaml
|
||||
# this would reside in a schema field on top level
|
||||
# a field of name 'id'
|
||||
id: # name of the field
|
||||
id: # name of the field
|
||||
type: str # sets the datatype to str
|
||||
translatable: false # enforces the value is not translatable (default is true)
|
||||
label: { # label describes the meaning of the datatype in regards of the schema
|
||||
de: "Kürzel", # translation of the label in German (de)
|
||||
en: "code" # translation of the label in English (en)
|
||||
}
|
||||
```
|
||||
```
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
# debug make file for testing
|
||||
build_dir := build
|
||||
target_en := ${build_dir}/table.en.pdf
|
||||
target_de := ${build_dir}/table.de.pdf
|
||||
|
@ -25,7 +25,7 @@ ${target_de}: mod.cg.yaml
|
|||
${target_de_book}: *.yaml
|
||||
python ${coursebuilder} -s schema.yaml -b book.yaml -p --title "### {}" -l de --leftcol 25 --legacy | pandoc ${target_flags} -V toc:true -V lang:de -o ${target_de_book}
|
||||
|
||||
clean:
|
||||
clean:
|
||||
rm -f ${targets}
|
||||
|
||||
debug:
|
||||
|
@ -38,4 +38,4 @@ debug-query:
|
|||
debug-query-book:
|
||||
python ${coursebuilder} -s schema.yaml -b book.yaml -q "kind=='compulsory'" -qs min:credits -qc form-of-instruction -qf name credits form-of-instruction -ql Modulname Kürzel Kreditpunkte
|
||||
|
||||
.PHONY: clean
|
||||
.PHONY: clean
|
||||
|
|
318
test/schema.yaml
318
test/schema.yaml
|
@ -1,300 +1,228 @@
|
|||
# fields in curricular description
|
||||
# leaning on methods in OpenAPI 3.0
|
||||
# leaning on methods in OpenAPI 3.0
|
||||
|
||||
#
|
||||
# Modulname
|
||||
#
|
||||
name:
|
||||
type: str
|
||||
label:
|
||||
de: "Modulname"
|
||||
en: "name of course"
|
||||
type: str
|
||||
label:
|
||||
de: "Modulname"
|
||||
en: "name of course"
|
||||
|
||||
#
|
||||
# Modulverantwortliche:r
|
||||
#
|
||||
instructor:
|
||||
type: str
|
||||
label:
|
||||
de: "Modulverantwortlicher / Modulverantwortliche"
|
||||
en: "module instructor"
|
||||
|
||||
instructor:
|
||||
type: str
|
||||
label:
|
||||
de: "Modulverantwortlicher / Modulverantwortliche"
|
||||
en: "module instructor"
|
||||
|
||||
#
|
||||
# Kürzel / ID
|
||||
#
|
||||
id:
|
||||
type: str
|
||||
translatable: false
|
||||
label: {
|
||||
de: "Kürzel",
|
||||
en: "code"
|
||||
}
|
||||
|
||||
id:
|
||||
type: str
|
||||
translatable: false
|
||||
label: { de: "Kürzel", en: "code" }
|
||||
|
||||
#
|
||||
# Qualifikationsziele
|
||||
#
|
||||
|
||||
# Welche fachbezogenen, methodischen, fachübergreifende Kompetenzen,
|
||||
# Schlüsselqualifikationen - werden erzielt (erworben)? Diese sind
|
||||
# Welche fachbezogenen, methodischen, fachübergreifende Kompetenzen,
|
||||
# Schlüsselqualifikationen - werden erzielt (erworben)? Diese sind
|
||||
# an der zu definierenden Gesamtqualifikation (angestrebter Abschluss) auszurichten.
|
||||
#
|
||||
#
|
||||
# Lernergebnisse sind Aussagen darüber, was ein Studierender nach Abschluss des Moduls weiß,
|
||||
# versteht und in der Lage ist zu tun. Die Formulierung sollte sich am Qualifikationsrahmen
|
||||
# versteht und in der Lage ist zu tun. Die Formulierung sollte sich am Qualifikationsrahmen
|
||||
# für Deutsche Hochschulabschlüsse orientieren und Inhaltswiederholungen vermeiden.
|
||||
#
|
||||
# Des Weiteren finden Sie im QM-Portal die „Handreichung zur Beschreibung von Lernzielen“
|
||||
#
|
||||
# Des Weiteren finden Sie im QM-Portal die „Handreichung zur Beschreibung von Lernzielen“
|
||||
# als Formulierungshilfe.
|
||||
|
||||
goal:
|
||||
type: str
|
||||
label: {
|
||||
de: "Qualifikationsziele",
|
||||
en: "educational goal"
|
||||
}
|
||||
type: str
|
||||
label: { de: "Qualifikationsziele", en: "educational goal" }
|
||||
|
||||
#
|
||||
# Modulinhalte
|
||||
#
|
||||
|
||||
# Welche fachlichen, methodischen, fachpraktischen und fächerübergreifenden
|
||||
# Inhalte sollen vermittelt werden?
|
||||
#
|
||||
# Welche fachlichen, methodischen, fachpraktischen und fächerübergreifenden
|
||||
# Inhalte sollen vermittelt werden?
|
||||
#
|
||||
# Es ist ein stichpunktartiges Inhaltsverzeichnis zu erstellen.
|
||||
|
||||
content:
|
||||
type: str
|
||||
label: {
|
||||
de: "Modulinhalte",
|
||||
en: "content"
|
||||
}
|
||||
content:
|
||||
type: str
|
||||
label: { de: "Modulinhalte", en: "content" }
|
||||
|
||||
#
|
||||
# Lehrform
|
||||
#
|
||||
|
||||
#
|
||||
# Welche Lehr- und Lernformen werden angewendet?
|
||||
# (Vorlesungen, Übungen, Seminare, Praktika,
|
||||
# Welche Lehr- und Lernformen werden angewendet?
|
||||
# (Vorlesungen, Übungen, Seminare, Praktika,
|
||||
# Projektarbeit, Selbststudium)
|
||||
#
|
||||
# Es sind nur Werte aus der Prüfungsordung zugelassen
|
||||
#
|
||||
form-of-instruction:
|
||||
type: multikey
|
||||
label: {
|
||||
de: "Lehrform(en)",
|
||||
en: "form of instruction"
|
||||
#
|
||||
form-of-instruction:
|
||||
type: multikey
|
||||
label: { de: "Lehrform(en)", en: "form of instruction" }
|
||||
keys:
|
||||
{
|
||||
"lecture": { de: "Vorlesung", en: "lecture" },
|
||||
"lecture_seminar":
|
||||
{ de: "Seminaristische Vorlesung", en: "lecture and seminar" },
|
||||
"seminar": { de: "Seminar", en: "seminar" },
|
||||
"exersise": { de: "Übung", en: "lab exersise" },
|
||||
"pc_lab": { de: "Rechnergestütztes Praktikum", en: "PC exersise" },
|
||||
"project": { de: "Project", en: "project" },
|
||||
}
|
||||
keys: {
|
||||
'lecture' : {
|
||||
de: "Vorlesung",
|
||||
en: "lecture"
|
||||
},
|
||||
'lecture_seminar' : {
|
||||
de: "Seminaristische Vorlesung",
|
||||
en: "lecture and seminar"
|
||||
},
|
||||
'seminar' : {
|
||||
de: "Seminar",
|
||||
en: "seminar"
|
||||
},
|
||||
'exersise' : {
|
||||
de: "Übung",
|
||||
en: "lab exersise"
|
||||
},
|
||||
'pc_lab' : {
|
||||
de: "Rechnergestütztes Praktikum",
|
||||
en: "PC exersise"
|
||||
},
|
||||
'project' : {
|
||||
de: "Project",
|
||||
en: "project"
|
||||
}
|
||||
}
|
||||
template:
|
||||
de: "{key} ({value}SWS)"
|
||||
en: "{key} ({value}SWS)"
|
||||
template:
|
||||
de: "{key} ({value}SWS)"
|
||||
en: "{key} ({value}SWS)"
|
||||
|
||||
#
|
||||
# Voraussetzungen für die Teilnahme
|
||||
#
|
||||
|
||||
# Für jedes Modul sind die Voraussetzungen für die Teilnahme zu beschreiben.
|
||||
# Für jedes Modul sind die Voraussetzungen für die Teilnahme zu beschreiben.
|
||||
# Welche Kenntnisse, Fähigkeiten und Fertigkeiten sind für eine
|
||||
# erfolgreiche Teilnahme vorauszusetzen?
|
||||
#
|
||||
# Alternativ können die Module benannt werden welche für die erfolgreiche
|
||||
#
|
||||
# Alternativ können die Module benannt werden welche für die erfolgreiche
|
||||
# Teilnahme im Vorfeld zu belegen sind.
|
||||
|
||||
prerequisites:
|
||||
type: str
|
||||
label: {
|
||||
de: "Voraussetzungen für die Teilnahme",
|
||||
en: "prerequisites"
|
||||
}
|
||||
prerequisites:
|
||||
type: str
|
||||
label: { de: "Voraussetzungen für die Teilnahme", en: "prerequisites" }
|
||||
|
||||
#
|
||||
# Literatur und multimediale Lehr- und Lernprogramme
|
||||
#
|
||||
#
|
||||
#
|
||||
# Wie können die Studierenden sich auf die Teilnahme an diesem Modul vorbereiten?
|
||||
#
|
||||
teaching-material:
|
||||
type: str
|
||||
label: {
|
||||
de: "Literatur und multimediale Lehr- und Lernprogramme",
|
||||
en: "media of instruction"
|
||||
#
|
||||
teaching-material:
|
||||
type: str
|
||||
label:
|
||||
{
|
||||
de: "Literatur und multimediale Lehr- und Lernprogramme",
|
||||
en: "media of instruction",
|
||||
}
|
||||
|
||||
#
|
||||
# Lehrbriefautor
|
||||
#
|
||||
author-of-indenture:
|
||||
type: str
|
||||
label: {
|
||||
de: "Lehrbriefautor",
|
||||
en: "author of indenture"
|
||||
}
|
||||
author-of-indenture:
|
||||
type: str
|
||||
label: { de: "Lehrbriefautor", en: "author of indenture" }
|
||||
|
||||
#
|
||||
# Verwendung in (Studienprogramm)
|
||||
#
|
||||
used-in:
|
||||
type: str
|
||||
label: {
|
||||
de: "Verwendung",
|
||||
en: "used in study programs"
|
||||
}
|
||||
type: str
|
||||
label: { de: "Verwendung", en: "used in study programs" }
|
||||
|
||||
#
|
||||
# Arbeitsaufwand
|
||||
#
|
||||
workload:
|
||||
type: str
|
||||
label: {
|
||||
de: "Arbeitsaufwand / Gesamtworkload",
|
||||
en: "workload"
|
||||
}
|
||||
type: str
|
||||
label: { de: "Arbeitsaufwand / Gesamtworkload", en: "workload" }
|
||||
#
|
||||
# credits/ECTS
|
||||
#
|
||||
credits:
|
||||
type: num
|
||||
unit: ECTS
|
||||
label: {
|
||||
en: "credits and weight of mark",
|
||||
de: "Kreditpunkte und Gewichtung der Note in der Gesamtnote"
|
||||
type: num
|
||||
unit: ECTS
|
||||
label:
|
||||
{
|
||||
en: "credits and weight of mark",
|
||||
de: "Kreditpunkte und Gewichtung der Note in der Gesamtnote",
|
||||
}
|
||||
template:
|
||||
de: "{value}CP, Gewichtung: {value}CP von 120CP "
|
||||
en: "{value}CP, weight: {value} / 120 "
|
||||
|
||||
template:
|
||||
de: "{value}CP, Gewichtung: {value}CP von 120CP "
|
||||
en: "{value}CP, weight: {value} / 120 "
|
||||
|
||||
#
|
||||
# Leistungsnachweis
|
||||
#
|
||||
form-of-exam:
|
||||
type: enum
|
||||
label: {
|
||||
de: "Leistungsnachweis",
|
||||
en: "form of examination"
|
||||
form-of-exam:
|
||||
type: enum
|
||||
label: { de: "Leistungsnachweis", en: "form of examination" }
|
||||
values:
|
||||
{
|
||||
"written": { de: "Schriftliche Prüfung", en: "written exam" },
|
||||
"oral": { de: "Mündliche Prüfung", en: "oral exam" },
|
||||
"alternative":
|
||||
{ de: "Alternative Prüfungunsleistung", en: "alternative examination" },
|
||||
}
|
||||
values: {
|
||||
'written' : {
|
||||
de: "Schriftliche Prüfung",
|
||||
en: "written exam"
|
||||
},
|
||||
'oral' : {
|
||||
de: "Mündliche Prüfung",
|
||||
en: "oral exam"
|
||||
},
|
||||
'alternative' : {
|
||||
de: "Alternative Prüfungunsleistung",
|
||||
en: "alternative examination"
|
||||
}
|
||||
}
|
||||
spec: true
|
||||
template:
|
||||
de: "{value} ({spec})"
|
||||
en: "{value} ({spec})"
|
||||
|
||||
spec: true
|
||||
template:
|
||||
de: "{value} ({spec})"
|
||||
en: "{value} ({spec})"
|
||||
|
||||
#
|
||||
# Semester
|
||||
#
|
||||
term:
|
||||
type: multinum
|
||||
label: {
|
||||
de: "Semester",
|
||||
en: "term"
|
||||
}
|
||||
template:
|
||||
de: "{value}\\. Semester"
|
||||
en: "{value}\\. semester"
|
||||
term:
|
||||
type: multinum
|
||||
label: { de: "Semester", en: "term" }
|
||||
template:
|
||||
de: "{value}\\. Semester"
|
||||
en: "{value}\\. semester"
|
||||
|
||||
#
|
||||
# Häufigkeit des Angebots
|
||||
#
|
||||
frequency:
|
||||
type: enum
|
||||
label: {
|
||||
de: "Häufigkeit des Angebots",
|
||||
en: "frequency of Offer"
|
||||
}
|
||||
values: {
|
||||
'once_per_term' : {
|
||||
de: "jedes Semester",
|
||||
en: "every semester"
|
||||
},
|
||||
'once_per_year' : {
|
||||
de: "einmal im Studienjahr",
|
||||
en: "once per study year"
|
||||
}
|
||||
frequency:
|
||||
type: enum
|
||||
label: { de: "Häufigkeit des Angebots", en: "frequency of Offer" }
|
||||
values:
|
||||
{
|
||||
"once_per_term": { de: "jedes Semester", en: "every semester" },
|
||||
"once_per_year":
|
||||
{ de: "einmal im Studienjahr", en: "once per study year" },
|
||||
}
|
||||
|
||||
#
|
||||
# Dauer des Angebots
|
||||
#
|
||||
duration:
|
||||
type: int
|
||||
label:
|
||||
de: Dauer
|
||||
en: duration
|
||||
template:
|
||||
de: "{value} Semester"
|
||||
en: "{value} term(s)"
|
||||
duration:
|
||||
type: int
|
||||
label:
|
||||
de: Dauer
|
||||
en: duration
|
||||
template:
|
||||
de: "{value} Semester"
|
||||
en: "{value} term(s)"
|
||||
|
||||
#
|
||||
# Art der Veranstaltung
|
||||
#
|
||||
kind:
|
||||
type: enum
|
||||
label: {
|
||||
de: 'Art der Veranstaltung (Pflicht, Wahl, etc.)',
|
||||
en: 'kind of module (compulsory, elective)'
|
||||
type: enum
|
||||
label:
|
||||
{
|
||||
de: "Art der Veranstaltung (Pflicht, Wahl, etc.)",
|
||||
en: "kind of module (compulsory, elective)",
|
||||
}
|
||||
values: {
|
||||
'compulsory': {
|
||||
de: "Pflicht",
|
||||
en: "compulsory"
|
||||
},
|
||||
'elective' : {
|
||||
de: "Wahl/Wahlpflicht",
|
||||
en: "elective"
|
||||
}
|
||||
values:
|
||||
{
|
||||
"compulsory": { de: "Pflicht", en: "compulsory" },
|
||||
"elective": { de: "Wahl/Wahlpflicht", en: "elective" },
|
||||
}
|
||||
|
||||
#
|
||||
# Freiform Bemerkungen
|
||||
#
|
||||
remarks:
|
||||
type: str
|
||||
label: {
|
||||
de: "Besonderes",
|
||||
en: "remarks"
|
||||
}
|
||||
|
||||
|
||||
|
||||
remarks:
|
||||
type: str
|
||||
label: { de: "Besonderes", en: "remarks" }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue