some initial testdata again
This commit is contained in:
parent
c4ba0f5e75
commit
2e1490d98f
8 changed files with 448 additions and 96 deletions
|
@ -2,29 +2,67 @@
|
||||||
# coursebuilder
|
# coursebuilder
|
||||||
#
|
#
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
from coursebuilder.schema import Schema
|
||||||
|
|
||||||
|
|
||||||
|
class LanguageSelector:
|
||||||
|
context_lang: str
|
||||||
|
|
||||||
|
|
||||||
class Course:
|
class Course:
|
||||||
def
|
i18n_name: str = "lang.{}.yaml"
|
||||||
|
mod_name: str = "mod.yaml"
|
||||||
|
|
||||||
|
def __init__(self, *, path: Path) -> None:
|
||||||
|
with open(path) as f:
|
||||||
|
# resolve rest of bundle
|
||||||
|
self.__data = yaml.load(f, Loader=yaml.Loader)
|
||||||
|
# load i18n overlays
|
||||||
|
self.__i18n = {
|
||||||
|
f"{str(p).split('.')[1]}": yaml.load(open(p), Loader=yaml.Loader)
|
||||||
|
for p in path.parent.glob(Course.i18n_name.format("*"))
|
||||||
|
}
|
||||||
|
|
||||||
|
def validate(self, *, schema: Schema, lang: str) -> None:
|
||||||
|
print(self.__data)
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __getitem__(self, name: str, /) -> Any:
|
||||||
|
return (
|
||||||
|
self.__data[name]
|
||||||
|
if name in self.__data.keys()
|
||||||
|
else self.__i18n[LanguageSelector.context_lang][name]
|
||||||
|
)
|
||||||
|
|
||||||
|
def __getattr__(self, name: str, /) -> Any:
|
||||||
|
return self.__data[name]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"data:{self.__data}\ni18n:{self.__i18n}"
|
||||||
|
|
||||||
|
|
||||||
class StudyCourse:
|
class StudyCourse:
|
||||||
def __init__(self, data: dict | None, path: Path | None):
|
def __init__(self, *, path: Path) -> None:
|
||||||
self.path: Path | None = path
|
self.path = path
|
||||||
self.data: dict | None = data
|
|
||||||
|
|
||||||
courses: list[Course] = []
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def load(*, path: str):
|
|
||||||
with open(path) as f:
|
with open(path) as f:
|
||||||
data = yaml.load(f, Loader=yaml.Loader)
|
self.__data = yaml.load(f, Loader=yaml.Loader)
|
||||||
return StudyCourse(data=data, path=Path(path))
|
|
||||||
|
self.courses: dict[str, Course] = {
|
||||||
|
f"{c}": Course(path=self.path.parent / c / Course.mod_name)
|
||||||
|
for c in self.__data["courses"]
|
||||||
|
}
|
||||||
|
|
||||||
|
def __getattr__(self, name: str, /) -> Any:
|
||||||
|
return self.__data[name] if self.__data else None
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"path: {self.path}\ndata: {self.data}"
|
return f"path: {self.path}\ndata: {self.__data}"
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -36,16 +74,31 @@ def main():
|
||||||
"-i",
|
"-i",
|
||||||
"--input",
|
"--input",
|
||||||
type=str,
|
type=str,
|
||||||
help="folder with project data",
|
help="course file with definition of the course",
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-s",
|
||||||
|
"--schema",
|
||||||
|
type=str,
|
||||||
|
help="schema to validate against",
|
||||||
)
|
)
|
||||||
|
|
||||||
# get arguments
|
# get arguments
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# just input
|
# just input
|
||||||
if args.input:
|
if args.input and args.schema:
|
||||||
sc = StudyCourse.load(path=(Path(".") / args.input).absolute())
|
with open(args.schema) as f_schema:
|
||||||
print(sc)
|
schema = Schema(schema=yaml.load(f_schema, Loader=yaml.Loader))
|
||||||
|
sc = StudyCourse(path=(Path(".") / args.input).absolute())
|
||||||
|
|
||||||
|
LanguageSelector.context_lang = "de"
|
||||||
|
|
||||||
|
for k in schema.keys():
|
||||||
|
print(k)
|
||||||
|
for shortcode, course in sc.courses.items():
|
||||||
|
print(course[k])
|
||||||
|
|
||||||
|
|
||||||
# run as main
|
# run as main
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
import string
|
|
||||||
|
|
||||||
class Schema:
|
class Schema:
|
||||||
|
def __init__(self, *, schema: dict) -> None:
|
||||||
def __init__(self,schema) -> None:
|
|
||||||
self.__schema = schema
|
self.__schema = schema
|
||||||
|
|
||||||
def __getitem__(self, field):
|
def __getitem__(self, field):
|
||||||
|
@ -12,26 +9,39 @@ class Schema:
|
||||||
return self.__schema.keys()
|
return self.__schema.keys()
|
||||||
|
|
||||||
def is_translatable(self, field):
|
def is_translatable(self, field):
|
||||||
if 'translatable' in self.__schema[field]:
|
if "translatable" in self.__schema[field]:
|
||||||
return self.__schema[field]['translatable']
|
return self.__schema[field]["translatable"]
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def needs_spec(self, field):
|
def needs_spec(self, field):
|
||||||
if 'spec' in self.__schema[field]:
|
if "spec" in self.__schema[field]:
|
||||||
return self.__schema[field]
|
return self.__schema[field]
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_value(self,meta,field,lang):
|
def get_value(self, meta: dict, field: str, lang: str):
|
||||||
"""
|
"""
|
||||||
treats receiving the value like a variant,
|
treats receiving the value like a variant,
|
||||||
returns values with their language specific representations
|
returns values with their language specific representations
|
||||||
"""
|
"""
|
||||||
match self.__schema[field]['type']:
|
match self.__schema[field]["type"]:
|
||||||
case 'str': return meta[field][lang] if self.is_translatable(field) else meta[field]['value']
|
case "str":
|
||||||
case 'enum' | 'int' | 'num' | 'multikey' : return meta[field]['value']
|
return (
|
||||||
case 'multinum': return meta[field]['value'] if hasattr(meta[field]['value'],'__iter__') else [meta[field]['value'],] # force list!
|
meta[field][lang]
|
||||||
|
if self.is_translatable(field)
|
||||||
|
else meta[field]["value"]
|
||||||
|
)
|
||||||
|
case "enum" | "int" | "num" | "multikey":
|
||||||
|
return meta[field]["value"]
|
||||||
|
case "multinum":
|
||||||
|
return (
|
||||||
|
meta[field]["value"]
|
||||||
|
if hasattr(meta[field]["value"], "__iter__")
|
||||||
|
else [
|
||||||
|
meta[field]["value"],
|
||||||
|
]
|
||||||
|
) # force list!
|
||||||
|
|
||||||
def to_list_of_dict(self, meta, fields, lang):
|
def to_list_of_dict(self, meta, fields, lang):
|
||||||
"""
|
"""
|
||||||
|
@ -39,19 +49,31 @@ class Schema:
|
||||||
to a pandas dataframe
|
to a pandas dataframe
|
||||||
"""
|
"""
|
||||||
# list comprehension for rows
|
# list comprehension for rows
|
||||||
return [{'field' : field, # field name
|
return [
|
||||||
'lang' : lang, # language shortcode
|
{
|
||||||
'type' : self.__schema[field]['type'], # datatype
|
"field": field, # field name
|
||||||
'label' : self.__schema[field]['label'][lang], # label
|
"lang": lang, # language shortcode
|
||||||
'value' : self.get_value(meta,field,lang), # actual value
|
"type": self.__schema[field]["type"], # datatype
|
||||||
'template' : self.__schema[field]['template'][lang] if 'template' in self.__schema[field] else None,
|
"label": self.__schema[field]["label"][lang], # label
|
||||||
|
"value": self.get_value(meta, field, lang), # actual value
|
||||||
|
"template": self.__schema[field]["template"][lang]
|
||||||
|
if "template" in self.__schema[field]
|
||||||
|
else None,
|
||||||
# getting crazy with nested dict comprehension
|
# getting crazy with nested dict comprehension
|
||||||
'enum_values' : { k:v[lang] for (k,v) in self.__schema[field]['values'].items()} if 'enum' in self.__schema[field]['type'] else None,
|
"enum_values": {
|
||||||
'key_values' : { k:v[lang] for (k,v) in self.__schema[field]['keys'].items()} if 'multikey' in self.__schema[field]['type'] else None,
|
k: v[lang] for (k, v) in self.__schema[field]["values"].items()
|
||||||
'spec' : meta[field]['spec'][lang] if 'spec' in meta[field] else None
|
|
||||||
}
|
}
|
||||||
for field in fields]
|
if "enum" in self.__schema[field]["type"]
|
||||||
|
else None,
|
||||||
|
"key_values": {
|
||||||
|
k: v[lang] for (k, v) in self.__schema[field]["keys"].items()
|
||||||
|
}
|
||||||
|
if "multikey" in self.__schema[field]["type"]
|
||||||
|
else None,
|
||||||
|
"spec": meta[field]["spec"][lang] if "spec" in meta[field] else None,
|
||||||
|
}
|
||||||
|
for field in fields
|
||||||
|
]
|
||||||
|
|
||||||
def to_short_dict(self, meta, fields, lang):
|
def to_short_dict(self, meta, fields, lang):
|
||||||
"""
|
"""
|
||||||
|
@ -70,18 +92,51 @@ class Schema:
|
||||||
"""
|
"""
|
||||||
list = []
|
list = []
|
||||||
for r in self.to_list_of_dict(meta, fields, lang):
|
for r in self.to_list_of_dict(meta, fields, lang):
|
||||||
match r['type']:
|
match r["type"]:
|
||||||
case 'str' :
|
case "str":
|
||||||
list.append( (r['label'],r['value']) )
|
list.append((r["label"], r["value"]))
|
||||||
case 'int' | 'num' :
|
case "int" | "num":
|
||||||
list.append( ( r['label'], r['template'].format(value=r['value'],spec=r['spec']) if r['template'] else r['value']) )
|
list.append(
|
||||||
case 'enum' :
|
(
|
||||||
list.append( ( r['label'], r['template'].format(value=r['enum_values'][r['value']],spec=r['spec'])
|
r["label"],
|
||||||
if r['template'] else r['enum_values'][r['value']] ) )
|
r["template"].format(value=r["value"], spec=r["spec"])
|
||||||
case 'multikey' :
|
if r["template"]
|
||||||
list.append( ( r['label'], ', '.join( [r['template'].format(key=r['key_values'][k],value=v) for k,v in r['value'].items()] ) ) )
|
else r["value"],
|
||||||
case 'multinum' :
|
)
|
||||||
list.append( (r['label'], ', '.join( r['template'].format(value=v) for v in r['value'])) )
|
)
|
||||||
|
case "enum":
|
||||||
|
list.append(
|
||||||
|
(
|
||||||
|
r["label"],
|
||||||
|
r["template"].format(
|
||||||
|
value=r["enum_values"][r["value"]], spec=r["spec"]
|
||||||
|
)
|
||||||
|
if r["template"]
|
||||||
|
else r["enum_values"][r["value"]],
|
||||||
|
)
|
||||||
|
)
|
||||||
|
case "multikey":
|
||||||
|
list.append(
|
||||||
|
(
|
||||||
|
r["label"],
|
||||||
|
", ".join(
|
||||||
|
[
|
||||||
|
r["template"].format(
|
||||||
|
key=r["key_values"][k], value=v
|
||||||
|
)
|
||||||
|
for k, v in r["value"].items()
|
||||||
|
]
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
case "multinum":
|
||||||
|
list.append(
|
||||||
|
(
|
||||||
|
r["label"],
|
||||||
|
", ".join(
|
||||||
|
r["template"].format(value=v) for v in r["value"]
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
return list
|
return list
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
fields:
|
field-names:
|
||||||
- name
|
- name
|
||||||
- instructor
|
- instructor
|
||||||
- id
|
- id
|
||||||
|
|
|
@ -34,8 +34,7 @@ teaching-material: |
|
||||||
prerequisites: |
|
prerequisites: |
|
||||||
Formale Voraussetzung bestehen nicht. Für eine erfolgreiche Teilnahme sollte das Modul „Grundlagen der Computergrafik“ im Vorfeld belegt werden.
|
Formale Voraussetzung bestehen nicht. Für eine erfolgreiche Teilnahme sollte das Modul „Grundlagen der Computergrafik“ im Vorfeld belegt werden.
|
||||||
|
|
||||||
author-of-indenture:
|
form-of-exam:
|
||||||
|
spec: abzugebende Projektarbeit (70%) und mündliche Prüfung (30% ~20min)
|
||||||
|
|
||||||
workload: "150h Insgesamt bestehend aus 60 Stunden Präsenzzeit, 60 Stunden Selbststudium, 30h Prüfung und Prüfungsvorbereitung"
|
workload: "150h Insgesamt bestehend aus 60 Stunden Präsenzzeit, 60 Stunden Selbststudium, 30h Prüfung und Prüfungsvorbereitung"
|
||||||
|
|
||||||
remarks:
|
|
|
@ -29,5 +29,3 @@ workload: "overall 150h comprising of 60h in-person training, 60h of self-study
|
||||||
|
|
||||||
form-of-exam:
|
form-of-exam:
|
||||||
spec: submitted project (70%) and oral exam (30% ~20min)
|
spec: submitted project (70%) and oral exam (30% ~20min)
|
||||||
|
|
||||||
remarks:
|
|
|
@ -1,9 +1,9 @@
|
||||||
|
id: 3DCC
|
||||||
|
|
||||||
name: 3D Content Creation
|
name: 3D Content Creation
|
||||||
|
|
||||||
instructor: Prof. Hartmut Seichter, PhD
|
instructor: Prof. Hartmut Seichter, PhD
|
||||||
|
|
||||||
id: 3DCC
|
|
||||||
|
|
||||||
form-of-instruction:
|
form-of-instruction:
|
||||||
- seminar: 2
|
- seminar: 2
|
||||||
- exersise: 2
|
- exersise: 2
|
||||||
|
@ -12,7 +12,12 @@ credits: 5
|
||||||
|
|
||||||
form-of-exam:
|
form-of-exam:
|
||||||
type: alternative
|
type: alternative
|
||||||
spec: abzugebende Projektarbeit (70%) und mündliche Prüfung (30% ~20min)
|
|
||||||
|
|
||||||
duration:
|
duration:
|
||||||
value: 1
|
value: 1
|
||||||
|
|
||||||
|
author-of-indenture:
|
||||||
|
|
||||||
|
kind: elective
|
||||||
|
|
||||||
|
remarks:
|
||||||
|
|
|
@ -1,4 +1,15 @@
|
||||||
|
# shortcode
|
||||||
shortcode: maacs
|
shortcode: maacs
|
||||||
|
|
||||||
|
# name
|
||||||
name: Applied Computer Science (Master of Science)
|
name: Applied Computer Science (Master of Science)
|
||||||
|
|
||||||
|
# validation schema
|
||||||
|
schema: schema.yaml
|
||||||
|
|
||||||
|
# languages (oder defines the order of overlay)
|
||||||
|
languages: [de, en]
|
||||||
|
|
||||||
|
# courses
|
||||||
courses:
|
courses:
|
||||||
- 3dcc
|
- 3dcc
|
||||||
|
|
231
test/maacs/v2/schema.yaml
Normal file
231
test/maacs/v2/schema.yaml
Normal file
|
@ -0,0 +1,231 @@
|
||||||
|
# fields in curricular description
|
||||||
|
# leaning on methods in OpenAPI 3.0
|
||||||
|
|
||||||
|
#
|
||||||
|
# Modulname
|
||||||
|
#
|
||||||
|
name:
|
||||||
|
type: str
|
||||||
|
label:
|
||||||
|
de: "Modulname"
|
||||||
|
en: "name of course"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Modulverantwortliche:r
|
||||||
|
#
|
||||||
|
instructor:
|
||||||
|
type: str
|
||||||
|
label:
|
||||||
|
de: "Modulverantwortlicher / Modulverantwortliche"
|
||||||
|
en: "module instructor"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Kürzel / ID
|
||||||
|
#
|
||||||
|
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
|
||||||
|
# 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
|
||||||
|
# für Deutsche Hochschulabschlüsse orientieren und Inhaltswiederholungen vermeiden.
|
||||||
|
#
|
||||||
|
# Des Weiteren finden Sie im QM-Portal die „Handreichung zur Beschreibung von Lernzielen“
|
||||||
|
# als Formulierungshilfe.
|
||||||
|
|
||||||
|
goal:
|
||||||
|
type: str
|
||||||
|
label: { de: "Qualifikationsziele", en: "educational goal" }
|
||||||
|
|
||||||
|
#
|
||||||
|
# Modulinhalte
|
||||||
|
#
|
||||||
|
|
||||||
|
# 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" }
|
||||||
|
|
||||||
|
#
|
||||||
|
# Lehrform
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# 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" }
|
||||||
|
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)"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Voraussetzungen für die Teilnahme
|
||||||
|
#
|
||||||
|
|
||||||
|
# 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
|
||||||
|
# Teilnahme im Vorfeld zu belegen sind.
|
||||||
|
|
||||||
|
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",
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Lehrbriefautor
|
||||||
|
#
|
||||||
|
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" }
|
||||||
|
|
||||||
|
#
|
||||||
|
# Arbeitsaufwand
|
||||||
|
#
|
||||||
|
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",
|
||||||
|
}
|
||||||
|
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" }
|
||||||
|
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})"
|
||||||
|
|
||||||
|
#
|
||||||
|
# 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" },
|
||||||
|
# }
|
||||||
|
|
||||||
|
#
|
||||||
|
# Dauer des Angebots
|
||||||
|
#
|
||||||
|
# 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)",
|
||||||
|
}
|
||||||
|
values:
|
||||||
|
{
|
||||||
|
"compulsory": { de: "Pflicht", en: "compulsory" },
|
||||||
|
"elective": { de: "Wahl/Wahlpflicht", en: "elective" },
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Freiform Bemerkungen
|
||||||
|
#
|
||||||
|
remarks:
|
||||||
|
type: str
|
||||||
|
label: { de: "Besonderes", en: "remarks" }
|
Loading…
Add table
Add a link
Reference in a new issue