Files
platz/libs/Strukturdaten.py
Michael Stangl 97382c8e9d Initial import from SVN (svn://129.187.65.205/platz/trunk, r1)
Converted from SVN working copy. Original SVN server no longer available.
Original commit date: 2006-05-03, author: sm
2006-05-03 22:21:24 +02:00

1093 lines
32 KiB
Python
Executable File

"""
Enthaelt alle Datenstrukturen um die noetigen Hierarchien zur Beschreibung einer Sitzplatzverteilung aufzubauen
"""
__author__ = "Michael Stangl"
__version__ = "$Revision: $"
__date__ = "$Date: $"
__copyright__ = "Copyright (c) 2005 Michael Stangl"
__license__ = "Python"
from sets import Set
from itertools import chain
from UserList import UserList
from random import *
import ConfigParser, os
import copy
from xml.dom import minidom
# Strukturklassen: Person, Gruppe, Tisch
class Person:
"""enthaelt alle Daten zu einer Person die noetig sind"""
def __init__(self, Id, Vorname, Name, Titel=''):
self.Id = Id
self._Vorname = Vorname
self._Name = Name
self._Titel = Titel
def __repr__(self):
return ' Person %s: "%s %s %s"' % ( self.Id, self._Titel,
self._Vorname, self._Name)
print self.__repr__
class Gruppe:
"""enthalt alle Daten zu einer Gruppe"""
Art = 'Gruppe'
def __init__(self, Id, Personen=[]):
self.Id = Id
self._Personen = Set()
self._Anzahl = 0
self.PvonId = {}
for P in Personen:
self.Person_dazu( P )
def __repr__(self):
result = '+ %s %s: Ids: ' % (self.Art, self.Id)
for P in self._Personen:
result = result + repr(P.Id) + ','
result = result + ' %s Person(en)' % (self._Anzahl)
return result
print self
for P in self._Personen:
print P
def Person_dazu(self, P):
self._Personen.add(P)
self._Anzahl = self._Anzahl + 1
self.PvonId[ P.Id ] = P
def Person_weg(self, P):
if P in self._Personen :
self._Personen.remove(P)
self._Anzahl = self._Anzahl - 1
else:
raise KeyError, "Person ist nicht enthalten"
def teilen(self, NeueGroesse=0):
if self._Anzahl == 1:
raise IndexError, "Gruppe ist nur noch einer"
if NeueGroesse == 0:
NeueGroesse = int(self._Anzahl/2)
one = Gruppe( self.Id, self._Personen )
two = Gruppe( self.Id, self._Personen )
two._Personen.clear()
for i in xrange(NeueGroesse):
two._Personen.add(one._Personen.pop())
one._Anzahl = len(one._Personen)
two._Anzahl = len(two._Personen)
return [one,two]
def PersonVonPid(self, SearchedId):
return self.PvonId[SearchedId]
def Anzahl(self):
return self._Anzahl
def __contains__(self, P):
return P in self._Personen
def __iter__(self):
for P in self._Personen:
yield(P)
def __cmp__(self,other):
if self._Anzahl < other._Anzahl: return -1
elif self._Anzahl == other._Anzahl: return 0
else: return 1
def __getattr__(self, attrname):
if attrname == 'Anzahl':
return self._Anzahl
elif attrname == 'Id':
return self.Id
else:
raise AttributeError, attrname
class Tisch(Gruppe):
"""enthalt alle Daten zu einem Tisch"""
Art = 'Tisch'
def __init__(self, Id, Plaetze=1, Koordinaten=(0,0), pids=[], Nachbarliste=[], Hof=0, Nummer=0 ):
self._Plaetze = Plaetze
self.Hof = Hof
self.Nummer = Nummer
self.X_Koordinate = Koordinaten[0]
self.Y_Koordinate = Koordinaten[1]
self.Nachbarn = Set(Nachbarliste)
Gruppe.__init__( self, Id, pids )
def istvoll(self, n=0):
if ((self._Anzahl + n) == self._Plaetze ):
return True
else:
return False
def istleer(self):
if (self._Anzahl == 0 ):
return True
else:
return False
def istNachbar(self,Tid):
if Tid in self.Nachbarn:
return True
else:
return False
def freiePlaetze(self):
return int( self._Plaetze - self._Anzahl )
def besetztePlaetze(self):
return self._Anzahl
def Person_dazu(self, P):
if (self._Anzahl == self._Plaetze ):
raise IndexError, "Tisch voll"
else:
Gruppe.Person_dazu( self, P )
def Person_weg(self, P):
if (self._Anzahl == 0 ):
raise IndexError, "Tisch schon leer"
else:
Gruppe.Person_weg( self, P )
def teilen(self):
pass
def __repr__(self):
result = ( Gruppe.__repr__( self ) +
' fuer [%s], %s noch frei,' %
(self._Plaetze,
self._Plaetze - self._Anzahl)
)
result = result + " Nachbarn:"
for N in chain(self.Nachbarn):
result = result + repr(N)
return result
def __getattr__(self, attrname):
if attrname == 'Anzahl':
return self._Anzahl
if attrname == 'Plaetze':
return self._Plaetze
elif attrname == 'Id':
return self.Id
else:
raise AttributeError, attrname
# Containerklassen Personen, Gruppen, Tische, Plaetze
class Personen:
"""ein Pool mit mehreren Personen"""
def __init__( self, Personen=[] ):
self._Personen = Set(Personen)
self.PvonId = {}
for P in Personen:
self.PvonId[ P.Id ] = P
def __repr__( self):
result = '+ PersonenListe:\n'
for P in self._Personen:
result = result + repr(P) + '\n'
return result
def PersonVonPid( self, SearchedId ):
return self.PvonId[SearchedId]
def PersonAdd( self, Person ):
self._Personen.add( Person )
Pid = Person.Id
self.PvonId[ Pid ] = Person
def ListeVonIds( self, PersonenIds ):
PersonenListe = []
for Id in PersonenIds:
PersonenListe.append( self.PersonVonPid( Id ) )
return PersonenListe
class Gruppen:
"""Containerklasse fuer Gruppenzusammenstellung """
Art = 'Gruppen'
def __init__( self, GruppenListe=[]):
self.GruppenListe = []
self.PvonPid = {}
self.GvonPid = {}
self.NLeute = 0
for G in chain( GruppenListe ):
self.Gruppe_dazu( G )
print "gruppen hinzugefuegt"
def __iter__( self):
sortiert = self.GruppenListe[:]
sortiert.sort()
for G in sortiert:
yield(G)
def __repr__( self):
result = "-- "+self.Art+"aufstellung:\n"
for G in chain( self.GruppenListe):
result = result + repr(G)+ '\n'
result = result + "Gesamtanzahl der Leute: " + repr(self.NLeute) + "\n"
return result
def vonId(self, SearchedId):
for G in chain(self.GruppenListe):
if ( int(G.Id) == SearchedId ):
return G
def PersonVonPid(self, SearchedId):
return self.PvonPid[SearchedId]
def GruppeVonPid(self, SearchedId):
return self.GvonPid[SearchedId]
def Gruppe_dazu(self, G):
self.GruppenListe.append( G )
self.NLeute = self.NLeute + G._Anzahl
for P in G:
self.PvonPid[ P.Id ] = P
self.GvonPid[ P.Id ] = G
class Tische:
"""Containerklasse fuer Tischaufstellung """
Art = 'Tisch'
def __init__( self, TischListe =[] ):
self.TischListe = TischListe
self.Groesster = 0
self.NStuehle = 0
self.IdGroesster = 0
# stelle den groessten Tisch fest
# und zaehle die Plaetze
for T in chain( TischListe ):
self.NStuehle = self.NStuehle + T.Plaetze
if (T.Plaetze > self.Groesster ):
self.Groesster = T.Plaetze
self.IdGroesster = T.Id
def __repr__( self ):
result = "-- "+self.Art+"aufstellung:\n"
for T in chain(self.TischListe):
result = result + repr(T)+ '\n'
result = ( result + " Groesster Tisch: "
+ repr(self.IdGroesster)
+ "( " + repr(self.Groesster) + " )\n" )
return result
def Tisch_dazu(self, T):
self.NStuehle = self.NStuehle + T.Plaetze
self.TischListe.append( T )
if (T.Plaetze > self.Groesster ):
self.Groesster = T.Plaetze
self.IdGroesster = T.Id
def __iter__( self):
sortiert = self.TischListe[:]
sortiert.sort()
for T in sortiert:
yield(T)
def laden( self, FileName ):
## print "-- Tische laden"
config = ConfigParser.ConfigParser()
config.read( os.path.expanduser(FileName) )
for section in config.sections():
Tid = int(section)
Nummer = eval(config.get( section, 'Nummer' ))
nPl = eval(config.get( section, 'Plaetze' ))
Koords = eval(config.get( section, 'Koordinaten' ))
Nachbarn = eval(config.get( section, 'Nachbarliste' ))
Hofid = eval(config.get( section, 'Hof' ))
T = Tisch( Tid, Plaetze=nPl, Koordinaten=Koords, Nachbarliste=Nachbarn, Hof=Hofid, Nummer=Nummer )
self.Tisch_dazu( T )
def vonId(self, SearchedId):
for T in chain(self.TischListe):
if ( int(T.Id) == SearchedId ):
return T
def deepcopy(self):
NeueTischliste = []
for T in chain( self.TischListe ):
TNeu = copy.deepcopy( T )
NeueTischliste.append( TNeu )
NeueTische = Tische( NeueTischliste )
return NeueTische
# Klasse fuer Information der Verteilung der Sitze
class Plaetze:
"""Informationen ueber freie oder benachbarte Plaetze"""
def __init__(self, Tische):
# mache Listen mit den Tischen mit n Freien Plaetzen
self.__TIDsNFreie = []
self.__Groesster = Tische.Groesster
self.__Tische = Tische
for i in range( self.__Groesster + 1 ):
self.__TIDsNFreie.append( Set() )
for T in Tische.TischListe:
n_freie = T.freiePlaetze()
self.__TIDsNFreie[n_freie].add(T.Id)
def __repr__(self):
result = "\n-- Tische mit n Freien Plaetzen:\n"
for i in xrange(self.__Groesster+1):
result = result + " " +repr(i) + " :" + repr(self.__TIDsNFreie[i]) + "\n"
return result
def IdsnFreie(self, n_freie):
"""gibt ein Set mit allen Tischids zurueck, wo noch X freie Plaetze sind"""
return self.__TIDsNFreie[n_freie]
def nFreie(self, n_freie):
"""gibt einen Tisch zurueck, wo noch X freie Plaetze sind"""
try:
TischId = int(self.__TIDsNFreie[n_freie].pop())
# aber veraendere deswegen die Liste nicht
self.__TIDsNFreie[n_freie].add(TischId)
return self.__Tische.vonId(TischId)
except KeyError:
return None
def mindestensNFreie(self, n_freie):
"""gibt einen Tisch zurueck, wo noch X oder mehr freie Plaetze sind"""
## print "-- Plaetze.mindestensNFreie", n_freie
## print "-- Plaetze.mindestensNFreie.Groesster", self.__Groesster
N = n_freie
if n_freie > self.__Groesster:
return None
while N < self.__Groesster+1:
T = self.nFreie(N)
if T is None:
N = N + 1
else:
return T
return None
def NachbarTische(self, n1, n2):
"""gibt zwei Nachbartische zurueck, wo zwei Gruppen hinpassen
falls durch eine Gruppe ein Tisch voll werden wuerde, ist voll=1
falls beide Tisch gefuellt werden wuerden, ist voll=2
"""
# zuerst versuchen einen Tisch fuer die groessere der beiden Gruppen zu finden
# falls es nicht klappt, wirds auch keine Nachbarn geben...
n = max([n1,n2])
T = self.mindestensNFreie( n )
if T is None:
return [None,None]
T1 = self.mindestensNFreie(n1)
# davon nun die Nachbarn abklappern, ob ein Tisch dabei ist,
# wo noch genuegend Plaetze frei sind
n_Nachbar = n2
IdNachbarTisch = 0
while n_Nachbar < self.__Groesster+1:
# ein Set bauen, das aus Tischids besteht, die sowohl Nachbarn sind,
# als auch mindestens die gewuenschte Anzahl von Plaetzen frei hat
NeueNachbarn = self.__TIDsNFreie[n_Nachbar] & T1.Nachbarn
try:
IdNachbarTisch = NeueNachbarn.pop()
T2 = self.__Tische.vonId( IdNachbarTisch )
return [T1,T2]
except KeyError:
n_Nachbar = n_Nachbar + 1
return [None,None]
def update(self, Tisch, n_freivorher):
"""aktualisiere die aktuelle Platzverteilung"""
## print "----------------"
## print "Plaetze.update"
self.__TIDsNFreie[n_freivorher].remove(Tisch.Id)
freiPlaetze = Tisch.freiePlaetze()
self.__TIDsNFreie[freiPlaetze].add(Tisch.Id)
## print "freie Plaetze: ", freiPlaetze, "Tischid", Tisch.Id, "\n"
# Strafliste. Was ist wie schlecht?
class Strafliste:
"""enthaelt die Informationen zur Vergabe der Wertigkeit einer Sitzplatzverteilung"""
def __init__(self, GruppenTrennen={}, NichtNachbar=-5, Allein=-20, TischWert={}):
self.GruppenTrennen = GruppenTrennen
self.NichtNachbar = NichtNachbar
self.Allein = Allein
self.TischWert = TischWert
def __repr__(self):
"""Drucke alle Bestrafungen auf der Konsole aus"""
return ("+ Strafliste:\n"
"Trennen von Gruppen (Groesse:Strafe): %s\n"
"Strafe kein Gruppenmitglied am Nachbartisch : %s\n"
"Strafe fuer eine Person allein: %s"
% ( self.GruppenTrennen,
self.NichtNachbar,
self.Allein) )
def gibPunkte(self, Typ, Gruppengroesse=0, N_Teilungen=0, freiePlaetze=0):
if cmp(Typ,'allein') == 0:
return self.Allein
elif cmp(Typ,'nichtNachbar')== 0:
return self.NichtNachbar
elif cmp(Typ,'Tischbesetzung')== 0:
try:
return self.TischWert[freiePlaetze]
except KeyError:
return 0
elif cmp(Typ,'Trennung')== 0:
if (N_Teilungen == 0):
return 0
elif (N_Teilungen == 1) & (Gruppengroesse < 2):
raise IndexError, "Gruppe sind mindestens zwei Leute"
elif (N_Teilungen == 2) & (Gruppengroesse < 3):
raise IndexError, "mindestens drei Leute noetig"
elif (N_Teilungen > 2):
return -50
if self.GruppenTrennen[N_Teilungen].has_key(Gruppengroesse):
return self.GruppenTrennen[N_Teilungen][Gruppengroesse]
else:
return self.gibPunkte('Trennung',Gruppengroesse-1, N_Teilungen)
else:
raise IndexError, "Bezeichner gibts nicht"
def laden( self, FileName ):
print "-- Strafliste laden"
config = ConfigParser.ConfigParser()
config.read( os.path.expanduser(FileName) )
self.NichtNachbar = eval(config.get( 'Globals', 'NichtNachbar' ))
self.Allein = eval(config.get( 'Globals', 'Allein' ))
self.TischWert = eval( config.get( 'Globals', 'TischWertigkeiten' ) )
for (k,v) in config.items( 'Trennung' ):
self.GruppenTrennen[int(k)] = eval(v)
# Sitzplatzverteilung, bestehend aus den Einzelelementen
class Sitzplatzverteilung:
"""Loesungsvorschlag fuer eine Sitzplatzordung"""
# Aenderung der Sitzplatzverteilung (Aktion)
def __init__(self, Tische=[], Gruppen=[], Strafen='', VIPListe={}, VIPs=[] ):
"""erzeugt eine Sitzplatzverteilung nach dem Zufallsprinzip
Zufallgenerator, um zu entscheiden, nach welcher
Verteilungsart verfahren wird:
- zuerst die groessten Gruppen auf die passenden Tische
verteilen, solange sie noch an einen Tisch passen
oder
- zuerst alle kleinsten Gruppen, da man die nicht mehr teilen
sollte
"""
#print "+ Sitzplatzverteilung\n"
if Gruppen.NLeute > Tische.NStuehle:
print "Anzahl der Leute:", Gruppen.NLeute
print "Anzahl der Plaetze:", Tische.NStuehle
raise IndexError, "zu wenig Stuehle"
self.MutationsGroesse = 2
self.VIP = VIPs
self.VIPListe = VIPListe
self.Gruppen = Gruppen
self.Strafen = Strafen
self.Tische = Tische.deepcopy()
## self.Tische = Tische
self.Groesster = Tische.Groesster
self.value = 0
self.Tid_Value = {}
self.Gid_Value = {}
self.Gid_Tid = {}
# zuerst die VIPs an die richtigen Tische setzen
self.VIPsSetzen( VIPListe, VIPs, self.Tische )
# fuehre Buch ueber die ab jetzt freien Plaetze
self.info = Plaetze( self.Tische )
# alle Gruppen auf die Tische verteilen
self.GruppenSetzen( Gruppen )
# die Sitzplatzverteilung bepunkten
self.bewerten()
print "erzeugt: ", self.value
def __repr__(self):
"""Ausgabe der Sitzplatzverteilung an der Konsole"""
r = "-- Sitzplatzverteilung:\n"
Tids = []
for T in self.Tische:
Tids.append(T.Id)
Tids.sort()
for Tid in Tids:
T = self.Tische.vonId(Tid)
r = r + repr(T) + "\n"
r = r + " Gruppenwertigkeiten:\n"
Gids = []
for G in self.Gruppen:
Gids.append(G.Id)
Gids.sort()
for Gid in Gids:
G = self.Gruppen.vonId(Gid)
r = r + " Gruppe " + repr(G.Id) + " (" + repr(self.GruppenWertGet(G)) + ")"
r = r + ", Teilungen: " + repr(self.GruppenTeilungGet(G)) + "\n"
r = r + " Tischwertigkeiten:\n"
for Tid in Tids:
T = self.Tische.vonId(Tid)
r = r + " Tisch " + repr(T.Id) + " (" + repr(self.TischWertGet(T)) + ")\n"
r = r + "Wertigkeit:" + repr(self.value) + "\n"
return r
def speichern(self, OutputTP, OutputPT ):
"""Ausgabe der Sitzplatzverteilung in ein File"""
Tids = []
for T in self.Tische:
Tids.append(T.Id)
Tids.sort()
Liste = []
# rausschreiben Tisch -> Personen
fout = open( OutputTP, 'w+')
for Tid in Tids:
T = self.Tische.vonId(Tid)
fout.write( "["+ repr(T.Id)+ "]\n" )
PlatzNummer = 1
for P in T:
str = ""
str = str + P._Titel + " "
str = str + P._Vorname + " "
str = str + P._Name + " = "
str = str + "Hof " + repr(T.Hof) + ", "
str = str + "Tisch "+ repr( T.Nummer ) + ", "
str = str + "Nummer "+ repr( PlatzNummer )
str = str + "\n"
PlatzNummer = PlatzNummer + 1
fout.write( str )
str = ""
str = str + P._Name + ", "
str = str + P._Vorname + ", "
str = str + P._Titel + " = "
str = str + "Hof " + repr(T.Hof) + ", "
str = str + "Tisch "+ repr( T.Nummer ) + ", "
str = str + "Nummer "+ repr( PlatzNummer )
str = str + "\n"
Liste.append( str )
fout.write( "\n" )
fout.close()
# rausschreiben Personen -> Tisch
Liste.sort()
fout = open( OutputPT, 'w+')
fout.writelines( Liste )
fout.close()
def mutieren(self):
"""Aendert die vorhandene Sitzplatzverteilung hoffentlich zum Besseren"""
[IdsSchlechteGruppen, Wertigkeiten] = self.SchlechteGruppenTopX(Anzahl=self.MutationsGroesse)
SchlechteGruppen = []
for Gid in IdsSchlechteGruppen:
G = self.Gruppen.vonId(Gid)
self.GruppeEntfernen(G)
SchlechteGruppen.append(G)
self.GruppenSetzen( SchlechteGruppen )
self.bewerten()
print "mutiert: ", self.value
return self
def __cmp__(self,other):
if self.value < other.value: return -1
elif self.value == other.value: return 0
else: return 1
def bewerten(self):
"""Errechnet die momentane Wertigkeit der Sitzplaetze"""
self.GesamtWertSet( 0 )
# Tische bewerten
for T in self.Tische:
#print T
n_freie = T.freiePlaetze()
Strafpunkte = self.Strafen.gibPunkte( 'Tischbesetzung', freiePlaetze=n_freie )
self.TischWertSet( T, Strafpunkte )
self.GesamtWertAdd( Strafpunkte )
#self.GruppenWertAdd( Gruppe, self.Strafen.gibPunkte( 'nichtNachbar') )
# schauen wie oft eine Gruppe getrennt wurde
for G in self.Gruppen:
NTeilungen = self.GruppenTeilungGet(G)
Strafpunkte = self.Strafen.gibPunkte( 'Trennung', G.Anzahl(), NTeilungen )
self.GruppenWertSet( G, Strafpunkte )
self.GesamtWertAdd( Strafpunkte )
# schauen ob Leute an einem Tisch allein sind
Strafpunkte = self.Strafen.gibPunkte( 'allein' )
for T in self.Tische:
Gids = self.LeuteAllein( T )
for Gid in Gids:
G = self.Gruppen.vonId( Gid )
self.GruppenWertAdd( G, Strafpunkte )
self.GesamtWertAdd( Strafpunkte )
def Wertigkeit(self):
"""Ausgabe der Guete der Sitzplatzverteilung an der Konsole"""
return ' L '+ repr(self.value)
# Personenspezifische Funktionen
def PersonSetzen(self, Person, Tisch):
"""setzt eine Person an den Tisch"""
Tisch.Person_dazu( Person )
def PersonEntfernen(self, Person, Tisch):
"""entfernt eine Person von dem Tisch"""
Tisch.Person_weg( Person )
FreiVorher = Tisch.freiePlaetze()
# der Tisch hat jetzt weniger freie Plaetze
self.info.update( Tisch, FreiVorher )
def PlatzTauschen(self, neuePerson, altePerson, Tisch):
"""Tauscht zwischen zwei Personen den Sitzplatz"""
self.PersonEntfernen( altePerson, Tisch )
self.PersonSetzen( neuePerson, Tisch )
# Gruppenspezifische Funktionen
def GruppenSetzen(self, Gruppen ):
"""setzt mal die grossen mal die kleinen Gruppen auf beliebige Plaetze"""
# Mache Liste der Gruppen, der Groesse nach sortiert
Gruppenliste = []
for G in Gruppen:
Gruppenliste.append(G)
# uns setzte sie auf freie Plaetze
while len(Gruppenliste) > 0:
wahl = choice(['grosse', 'kleine'])
if cmp(wahl,'grosse')== 0:
G = Gruppenliste.pop(0)
else:
G = Gruppenliste.pop(-1)
self.GruppeSetzen(G)
def GruppeSetzen(self, Gruppe, Tisch=None ):
"""setzt eine Gruppe irgendwohin wo Platz ist
oder an einen gewuenschten Tisch
"""
## print "---------------------"
## print "GruppeSetzen: Gruppe:", Gruppe
if Tisch is None:
Tisch = self.info.mindestensNFreie(Gruppe.Anzahl())
# kein Tisch mehr in der gewuenschten groesse frei.
# also Gruppe trennen
if Tisch is None:
# neue Gruppengroesse zufaellig bestimmen
Teil1 = choice( range(Gruppe.Anzahl()) )
[G1, G2] = Gruppe.teilen( Teil1 )
# Benachbarte Tische suchen die gross genug sind
n1 = G1.Anzahl()
n2 = G2.Anzahl()
[TA,TNA] = self.info.NachbarTische(n1, n2)
[TB,TNB] = self.info.NachbarTische(n2, n1)
if TA is None and TB is None:
# keine Nachbarn gefunden, also irgendwo hinsetzen
self.GruppeSetzen(G1)
self.GruppeSetzen(G2)
elif TA is None:
self.GruppeSetzen(G2,TB)
self.GruppeSetzen(G1,TNB)
elif TB is None:
self.GruppeSetzen(G1,TA)
self.GruppeSetzen(G2,TNA)
else:
# nimm die Kombination, die die Tische am besten fuellt
vollA = 0
vollB = 0
if TA.istvoll(n1): vollA = vollA + 1
if TNA.istvoll(n2): vollA = vollA + 1
if TB.istvoll(n2): vollB = vollB + 1
if TNB.istvoll(n1): vollB = vollB + 1
if vollA > vollB:
self.GruppeSetzen(G1,TA)
self.GruppeSetzen(G2,TNA)
else:
self.GruppeSetzen(G2,TB)
self.GruppeSetzen(G1,TNB)
else:
FreiVorher = Tisch.freiePlaetze()
for P in Gruppe:
self.PersonSetzen(P, Tisch)
# der Tisch hat jetzt weniger freie Plaetze
self.info.update( Tisch, FreiVorher )
# zur Gruppe merken, an welchen Tischen sie jetzt sitzt
try:
Ids = self.Gid_Tid[Gruppe.Id]
Ids.add(Tisch.Id)
except KeyError:
s = Set()
s.add(Tisch.Id)
self.Gid_Tid[Gruppe.Id] = s
def GruppeEntfernen(self, Gruppe):
"""entfernt eine Gruppe von Ihren Tischen"""
TischIds = self.Gid_Tid[Gruppe.Id]
for Tid in TischIds:
T = self.Tische.vonId(Tid)
FreiVorher = T.freiePlaetze()
for P in Gruppe:
#print "P:", P
try:
self.PersonEntfernen( P, T )
except IndexError:
pass
except KeyError:
pass
self.info.update( T, FreiVorher )
del self.Gid_Tid[Gruppe.Id]
# der Tisch hat jetzt weniger freie Plaetze
# print self.Tische
# Bewertungsfunktionen (Evaluation)
# entscheiden bei der Mutation der Sitzplatzverteilung welche Tische als
# erstes wieder aufgeloest werden und welche nicht so schnell
def GesamtWertSet(self, Wert):
"""setzt die Gesamtwertung auf einen bestimmten Wert"""
self.value = Wert
def GesamtWertGet(self):
"""gibt den Wert der Gesamtwertung zurueck"""
return self.value
def GesamtWertAdd(self, Wert):
"""fuegt den Wert zur Gesamtwertung hinzu"""
self.value = self.value + Wert
def GruppenWertSet(self, Gruppe, Wert):
self.Gid_Value[Gruppe.Id] = Wert
def GruppenWertGet(self, Gruppe):
"""gibt die Zufriedenheit einer Gruppe zurueck
je nachdem, wie oft die Gruppe oft geteilt wurde
(je nach deren Groesse, bei grossen laesst es sich nicht vermeiden)
"""
try:
return self.Gid_Value[Gruppe.Id]
except KeyError:
return 0
def GruppenWertAdd(self, Gruppe, Wert):
"""fuegt den Wert der Gruppenwertigkeit hinzu """
try:
self.Gid_Value[Gruppe.Id] = self.Gid_Value[Gruppe.Id] + Wert
except KeyError:
self.Gid_Value[Gruppe.Id] = Wert
def TischWertSet(self, Tisch, Wert):
"""setzt die Wertigkeit dieses Tisches auf einen bestimmten Wert"""
self.Tid_Value[Tisch.Id] = Wert
def TischWertGet(self, Tisch):
"""Gib die Wertigkeit eines Tisches zurueck
- wenn viele unzufriedene Leute an dem Tisch sitzen,
ist die Wertigkeit schlecht
- wenn nur noch ein Platz frei ist,
ist die Wertigkeit des Tisches ebenfalls schlecht
weil man niemanden mehr dort hinsetzen kann
- wenn die Leute der eigenen Gruppe nicht an den Nachbartischen sitzen,
ist die Wertigkeit auch nicht gut
"""
try:
return self.Tid_Value[Tisch.Id]
except KeyError:
return 0
def LeuteAllein(self, Tisch):
"""Stellt fest wieviele Leute an diesem Tisch alleine sind,
weil sie zu einer Gruppe gehoeren,
die an diesem Tisch nicht vertreten ist
"""
Anzahl_von_Gid = {}
Gids = []
for P in Tisch:
G = self.Gruppen.GruppeVonPid(P.Id)
try:
Anzahl_von_Gid[G.Id] = Anzahl_von_Gid[G.Id] + 1
except KeyError:
Anzahl_von_Gid[G.Id] = 1
for Gid, Anzahl in Anzahl_von_Gid.iteritems():
if Anzahl == 1:
Gids.append(Gid)
return Gids
# Funktionen fuer mehrere Einheiten (Information)
def SchlechteTischeTopX(self, Anzahl=-1):
"""gibt eine List mit X Tischids zurueck, die schlechte Wertungen haben"""
return self.TopX( self.Tid_Value, Anzahl )
def SchlechteGruppenTopX(self, Anzahl=-1):
"""gibt eine List mit X Gruppenids zurueck, die schlechte Wertungen haben"""
return self.TopX( self.Gid_Value, Anzahl )
# Hilfsfunktionen
def GruppenTeilungGet(self, Gruppe):
try:
return len( self.Gid_Tid[Gruppe.Id] ) - 1
except KeyError:
return 0
def VIPsSetzen(self, VIPListe, VIPs, Tische ):
"""setze die VIPs auf Ihre Plaetze"""
#print " VIPsSetzen:"
for PersonId, TischId in VIPListe.iteritems():
#print " VIPsSetzen: PersonId", PersonId
#print " VIPsSetzen: TischId", TischId
Person = VIPs.PersonVonPid(PersonId)
Tisch = Tische.vonId(TischId)
self.PersonSetzen( Person, Tisch )
def TopX(self, Liste, Anzahl=-1 ):
"""gibt eine Liste mit X Ids zurueck, die die schlechtesten Wertungen haben"""
Min = 0
RListe=[]
Wertigkeit=[]
# TODO filter verwenden
for Id, Wert in Liste.iteritems():
if Wert <= Min:
RListe.append(Id)
Wertigkeit.append(Wert)
Min = Wert
return [RListe[-Anzahl:], Wertigkeit[-Anzahl:] ]
# Sitzplatzverteilung, bestehend aus den Einzelelementen
class XMLConfig:
"""aus Xml file alles einlesen"""
def getText(self, nodelist):
rc = ""
for node in nodelist:
if node.nodeType == node.TEXT_NODE:
rc = rc + node.data
return rc
def handlePersonNode( self, person ):
"""Personendaten erfassen"""
info = {}
try:
Titel = person.getElementsByTagName("Titel")[0]
info["Titel"] = self.getText(Titel.childNodes)
except IndexError:
info["Titel"] = ""
Vorname = person.getElementsByTagName("Vorname")[0]
Nachname = person.getElementsByTagName("Nachname")[0]
info["Vorname"] = self.getText(Vorname.childNodes)
info["Nachname"] = self.getText(Nachname.childNodes)
return info
def HandleBestellung(self, Bestellung):
"""alle Bloecke in der XML Bestellung parsen"""
PidListe = []
VipHash = {}
PN = Personen()
GN = Gruppen()
VIPGruppe = Gruppe( 0 )
print '-HandleBestellung'
AlleGruppenXML = Bestellung.getElementsByTagName("Gruppe")
PID = 0
GID = 0
for GruppeXML in AlleGruppenXML:
GID = GID + 1
print '-- GID ' + repr(GID)
G = Gruppe( GID )
IsVip = False
AnzahlReservierungen = 1
for Node in GruppeXML.childNodes:
if Node.nodeName == 'Tisch':
TischNr = self.getText(Node.childNodes)
print 'TischNr:', TischNr
IsVip = True
if Node.nodeName == 'Anzahl':
AnzahlReservierungen = int(self.getText(Node.childNodes))
print 'Anzahl der Reservierungen:', AnzahlReservierungen
IsContingent = True
for Node in GruppeXML.childNodes:
if Node.nodeName == 'Person':
NRes = 0
for i in range(int(AnzahlReservierungen)):
NRes = NRes + 1
PID = PID + 1
print "PID =" + repr(PID)
info = self.handlePersonNode( Node )
Vorname = info["Vorname"]
Nachname = info["Nachname"]
Titel = info["Titel"]
P = Person( PID, Vorname, Nachname, Titel)
if IsVip == True:
PidListe.append( int(PID) )
VipHash[ int(PID) ] = int(TischNr)
VIPGruppe.Person_dazu( P )
else:
PN.PersonAdd( P )
G.Person_dazu( P )
if (G.Anzahl > 0) & (IsVip != True):
GN.Gruppe_dazu( G )
if IsVip == True:
GID = GID - 1
print PN
print GN
print VIPGruppe
print VipHash
print '=========='
return [ PN, GN, VIPGruppe, VipHash ]
def laden(self, Bestellung):
"""lese alle Eingangsdaten aus einem XML File ein"""
fsock = open( Bestellung, 'r')
xmlini = minidom.parse(fsock)
return self.HandleBestellung(xmlini)
if __name__ == '__main__':
print "\n-- Erzeuge Personen:"
P1 = Person( 1, 'Michael', 'Stangl')
P2 = Person( 2, 'Magnus', 'Mueller')
P3 = Person( 3, 'Bernd Robert', 'Hoehn')
P4 = Person( 4, 'Heinz', 'Ruehmann')
P5 = Person( 5, 'Franz', 'Bruegge')
P6 = Person( 6, 'Hubert', 'K')
print P1
print P2
print P3
print P4
print P5
print P6
print "\n-- Mehrzahl von Personen:"
PN = Personen([P1, P2, P3, P4, P5, P6])
print PN
print "\n-- Erzeuge Gruppen mit den Personen:"
G1 = Gruppe( 1, [P1, P2] )
G1.Person_dazu( P3 )
G2 = Gruppe( 2 )
G2.Person_dazu( P4 )
G3 = Gruppe( 3, [P5,P6] )
print "\n-- Stelle Gruppen dar:"
print G1
print G2
print G3
print "\n-- Durchlaufe Gruppe 3:"
for P in G3:
print P
print "\n-- Mache Liste der Gruppen:"
GN = Gruppen([G1,G2,G3])
print GN
print "\n-- Durchlaufe Gruppen sortiert:"
for G in GN:
print G
print "\n-- Teile Gruppe:"
[GX, GY] = G1.teilen()
print GX
print GY
[GX, GY] = G1.teilen(3)
print GX
print GY
print "\n-- Erzeuge Tische mit Personen:"
T1 = Tisch( 1, Plaetze=5, Koordinaten=(1,2), pids=[P1, P2], Nachbarliste=[2] )
print T1
T2 = Tisch( 2, Plaetze=4, Koordinaten=(3,2), Nachbarliste=[1,3] )
T2.Person_dazu( P3 )
print T2
T2.Person_dazu( P4 )
print T2
T2.Person_weg( P4 )
print T2
T3 = Tisch( 3, Plaetze=2, Koordinaten=(5,2), Nachbarliste=[2] )
print "\n-- Ist Tisch 2 voll oder leer?:"
print "ist voll = ", T2.istvoll()
print "ist leer = ", T2.istleer()
print "\n-- Wieviele Plaetze sind an Tisch 1 noch frei ?:"
print "Freie Plaetze = ", T1.freiePlaetze()
print "Besetzte Plaetze = ", T1.besetztePlaetze()
print "\n-- Stelle Tische dar:"
print T1
print T2
print T3
print "\n-- Ist Person Nummer 3 an Tisch 1 ?:"
print P1 in T1
print "-- Ist Person Nummer 4 an Tisch 1 ?:"
print P4 in T1
TE = Tische([T1,T2,T3])
print TE
print "\n-- Hole Tisch 2 aufgrund seiner Id :"
TX = TE.vonId( 2 )
print TX
print "\n-- Hole Gruppe 2 aufgrund ihrer Id :"
GX = GN.vonId( 2 )
print GX
print "\n-- Hole Person 2 aufgrund ihrer Id aus den Gruppen:"
PX = GN.PersonVonPid( 2 )
print PX
print "\n-- schau wo noch mindestens 3 Plaetze frei sind:"
info = Plaetze(TE)
print info.mindestensNFreie( 3 )
print "\n-- schau wo zwei Gruppen bestimmter Groesse nebeneinander sitzen koennen:"
print " zwei neben drei:"
[TX,TY] = info.NachbarTische(2, 3)
print TX
print TY
print " drei neben zwei:"
[TX,TY] = info.NachbarTische(3, 2)
print TX
print TY
P1 = Person( 1, 'Michael', 'Stangl')
P2 = Person( 2, 'Magnus', 'Mueller')
P3 = Person( 3, 'Bernd Robert', 'Hoehn')
P4 = Person( 4, 'Heinz', 'Ruehmann')
P5 = Person( 5, 'Marlene', 'Dietrich')
P6 = Person( 6, 'Sergio', 'Leone')
P7 = Person( 7, 'Walter', 'Emmerlich')
P8 = Person( 8, 'Harald', 'Junke')
P9 = Person( 9, 'Willi', 'Brandt')
P10 = Person( 10, 'Michael', 'Schumacher')
P11 = Person( 11, 'Ralf', 'Schumacher')
P12 = Person( 12, 'Bla', 'Button')
P13 = Person( 13, 'Heinz Harald', 'Frenzen')
#
# T1 T2 T3 T4
# <3> <5> <3> <4>
#
# G1 G2 G3 G4
# <3> <2> <2> <6>
#
print "\n-- Mache Gruppen:"
VIPGruppe = ( Gruppe( 1, [P1, P2, P3] ) )
G2 = ( Gruppe( 2, [P4, P5] ) )
G3 = ( Gruppe( 3, [P6, P7] ) )
G4 = ( Gruppe( 4, [P8, P9, P10, P11, P12, P13] ) )
GN = Gruppen([G2,G3,G4])
print GN
print "\n-- Mache Tische:"
T1 = ( Tisch( 1, Plaetze=3, Koordinaten=(1,1), Nachbarliste=[2] ) )
T2 = ( Tisch( 2, Plaetze=5, Koordinaten=(2,1), Nachbarliste=[1,3] ) )
T3 = ( Tisch( 3, Plaetze=3, Koordinaten=(3,1), Nachbarliste=[2,4] ) )
T4 = ( Tisch( 4, Plaetze=4, Koordinaten=(4,1), Nachbarliste=[3] ) )
TE = Tische([T1,T2,T3,T4])
print TE
print "\n-- Mache Listen:"
# Personenid - Tischid
VIPListePT = { 3:1, 2:1, 1:1 }
print "VIP Liste:", VIPListePT
# Strafliste
# die Teilung einer grossen Gruppe ist nicht so schlimm
# wie die einer kleinen
Teilung = list()
Teilung.append({'x':'x'})
Teilung.append({2:-10, 3:-8, 4:-6, 6:-4, 10:-2})
Teilung.append({3:-20, 4:-8, 6:-6, 10:-4})
Teilung.append({4:-30, 6:-10, 10:-6})
# Ein Platz an einem Tisch frei ist schlechter als zwei Plaetze frei
TischWertigkeiten={ 1:-3, 2:-2, 3:-1 }
SL = Strafliste(GruppenTrennen=Teilung, NichtNachbar=-3, Allein=-30, TischWert=TischWertigkeiten)
print SL
print "\n-- Teste Strafliste:"
print "SL.gibPunkte('Trennung', 7,1):", SL.gibPunkte('Trennung', 7,1)
print "SL.gibPunkte('Trennung', 5,1):", SL.gibPunkte('Trennung', 5,1)
print "SL.gibPunkte('Trennung', 3,1):", SL.gibPunkte('Trennung', 3,1)
try:
print "SL.gibPunkte('Trennung',(1,1):",SL.gibPunkte('Trennung',1,1)
except IndexError:
print "Gruppe sind mindestens zwei"
print "\n-- Baue Sitzplatzverteilung:"
SV = Sitzplatzverteilung(Tische=TE, Gruppen=GN, Strafen=SL,
VIPListe=VIPListePT, VIPs=VIPGruppe)
print SV
print "\n-- Mutiere Sitzplatzverteilung:"
SV.mutieren()
print SV
print "\n-- Gibt die 3 Tische mit der schlechtesten Wertung:"
[TischIds, Wertigkeit]=SV.SchlechteTischeTopX(3)
print "TischIds:", TischIds
print "Wertigkeit:", Wertigkeit
print "\n-- Gibt die Gruppen mit der schlechtesten Wertung:"
[GruppenIds, Wertigkeit]=SV.SchlechteGruppenTopX(3)
print "GruppenIds:", GruppenIds
print "Wertigkeit:", Wertigkeit
else:
pass