Strafen können durch benannte Profile festgelegt werden

This commit is contained in:
Michael Stangl
2026-07-15 17:05:13 +02:00
parent db69f3498d
commit 4a059f32c5
5 changed files with 114 additions and 53 deletions
+35 -11
View File
@@ -437,21 +437,45 @@ class Strafliste:
return self.gibPunkte('Trennung',Gruppengroesse-1, N_Teilungen)
else:
raise IndexError("Bezeichner gibts nicht")
def laden( self, FileName ):
print("-- Strafliste laden")
def laden( self, FileName, Sektion='default' ):
"""laedt ein Strafpunkte-Profil aus einer Sektion der strafen.cfg.
Jede Sektion ist ein vollstaendiges Bewertungs-'Vorgehen' mit allen
Angaben in einem gemeinsamen Namensraum. Der Aufrufer waehlt das
Profil ueber 'Sektion' (Vorgabe 'default'); so lassen sich mehrere
Bewertungsstrategien in derselben Datei pflegen. Die Trennungs-
Straffen stehen unter den Schluesseln 'Anzahl_Trennungen_N'."""
print("-- Strafliste laden (Profil '%s')" % Sektion)
config = configparser.ConfigParser()
config.read( os.path.expanduser(FileName) )
if not config.has_section( Sektion ):
raise ValueError(
"Strafprofil '%s' nicht in %s gefunden (vorhanden: %s)"
% ( Sektion, FileName, ', '.join(config.sections()) or '-' ) )
# ast.literal_eval statt eval: die Werte sind reine Literale
# (Zahlen und Dicts wie {2:-10}), also kein Code noetig.
self.NichtNachbar = ast.literal_eval(config.get( 'Globals', 'NichtNachbar' ))
self.Allein = ast.literal_eval(config.get( 'Globals', 'Allein' ))
self.TischWert = ast.literal_eval( config.get( 'Globals', 'TischWertigkeiten' ) )
# Abschnitt [Abstand] ist optional; fehlt er, wird der Abstand
# getrennter Gruppen nicht bestraft (Faktor 0).
if config.has_section( 'Abstand' ):
self.AbstandFaktor = ast.literal_eval(config.get( 'Abstand', 'Faktor' ))
for (k,v) in config.items( 'Trennung' ):
self.GruppenTrennen[int(k)] = ast.literal_eval(v)
self.NichtNachbar = ast.literal_eval(config.get( Sektion, 'NichtNachbar' ))
self.Allein = ast.literal_eval(config.get( Sektion, 'Allein' ))
# TischWertigkeiten ist optional; fehlt der Schluessel, werden freie
# Plaetze gar nicht bestraft (leeres Dict -> gibPunkte('Tischbesetzung')
# gibt 0), wodurch mehr Teilbelegungen moeglich sind.
if config.has_option( Sektion, 'TischWertigkeiten' ):
self.TischWert = ast.literal_eval( config.get( Sektion, 'TischWertigkeiten' ) )
else:
self.TischWert = {}
# AbstandFaktor ist optional; fehlt er, wird der Abstand getrennter
# Gruppen nicht bestraft (Faktor 0).
if config.has_option( Sektion, 'AbstandFaktor' ):
self.AbstandFaktor = ast.literal_eval(config.get( Sektion, 'AbstandFaktor' ))
# Trennungs-Straffen: Schluessel 'Anzahl_Trennungen_N' -> N Trennungen.
# frisches Dict, damit nicht der (mutable) Konstruktor-Default geteilt
# wird und Reste eines frueheren laden() bleiben.
self.GruppenTrennen = {}
for (k, v) in config.items( Sektion ):
# configparser liefert Schluessel klein geschrieben
if k.startswith( 'anzahl_trennungen_' ):
N = int( k.rsplit( '_', 1 )[-1] )
self.GruppenTrennen[N] = ast.literal_eval(v)
# Sitzplatzverteilung, bestehend aus den Einzelelementen