Strafen können durch benannte Profile festgelegt werden
This commit is contained in:
+35
-11
@@ -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
|
||||
|
||||
+9
-1
@@ -51,6 +51,10 @@ if __name__ == '__main__':
|
||||
parser.add_option( "--zyklus-art", dest="zyklusart", default="Adaptiv",
|
||||
help="Name des GA-Profils in zyklus.cfg (Vorgabe: Adaptiv). "
|
||||
"Weitere mitgelieferte Profile: Easy, Simple" )
|
||||
parser.add_option( "--strafen", dest="strafen", default="default",
|
||||
help="Name des Strafpunkte-Profils (Sektion in strafen.cfg; "
|
||||
"Vorgabe: default). Erlaubt mehrere Bewertungs-Vorgehen in einer "
|
||||
"Datei, z.B. --strafen locker" )
|
||||
parser.add_option( "--seed", dest="seed", type="int", default=None,
|
||||
help="Zufalls-Startwert (int) fuer random.seed(), macht den Lauf "
|
||||
"reproduzierbar. Ohne Angabe laeuft der GA nichtdeterministisch. "
|
||||
@@ -83,6 +87,7 @@ if __name__ == '__main__':
|
||||
Zyklusconfig = os.path.join( CfgDir, 'zyklus.cfg' )
|
||||
Zyklusart = options.zyklusart
|
||||
Strafenconfig = os.path.join( CfgDir, 'strafen.cfg' )
|
||||
Strafenart = options.strafen
|
||||
|
||||
# lade Eingabedateien
|
||||
Tischconfig = os.path.join( InDir, 'tische.ini' )
|
||||
@@ -99,7 +104,10 @@ if __name__ == '__main__':
|
||||
Z.laden( Zyklusconfig, Zyklusart )
|
||||
print(Z)
|
||||
SL = Strafliste()
|
||||
SL.laden( Strafenconfig )
|
||||
try:
|
||||
SL.laden( Strafenconfig, Strafenart )
|
||||
except ValueError as Fehler:
|
||||
parser.error( str(Fehler) )
|
||||
print(SL)
|
||||
TE = Tische()
|
||||
TE.laden( Tischconfig )
|
||||
|
||||
Reference in New Issue
Block a user