""" 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