2D Koordinaten clustern und zählen

  • VB.NET

Es gibt 21 Antworten in diesem Thema. Der letzte Beitrag () ist von DocBizz.

    2D Koordinaten clustern und zählen

    Hallo Leute,

    ich habe ein Datenfile mit ca. 56000 Koordinaten. Die bestehen aus jeweils einem X-Achsenwert (Typ Double), einem Y-Achsenwert(Typ Double), einen Zeitstempel und einem weiteren Parameter vom Typ Integer.

    Ich möchte die Häufigkeit des Auftretens jedes Koordinatenpaares ermitteln. Dabei ist es nicht notwendig jede Koordinaten zu zählen, ein definiertes Spektrum um die Koordinatenposition herum reicht völlig aus.

    Das Problem ist, dass das alles extreme lange dauert. Kann man das Clustern und durchzählen irgendwie beschleunigen? Ist ein Dictionary ratsam? Nützt mir das was in meinem Fall etwas? Kann ich das Dictionary auch nach zwei Werten durchsuchen (X, und Y-Coordinate)?

    DataList: Darin sind die Werte gespeichert.
    Diese List wird in mehreren Durchläufen, durch berechnen der noch leeren Paramter (IntXBlock,...), gefüllt.

    VB.NET-Quellcode

    1. Structure CapCurvePower
    2. Dim dteDatum As Date
    3. Dim dteTime As Date
    4. Dim intX As Integer
    5. Dim intY As Integer
    6. Dim Counter As Integer
    7. Dim intXBlock As Integer
    8. Dim intYBlock As Integer
    9. Dim Flag As Boolean
    10. Dim BlockColor As Color
    11. End Structure
    12. Private Function MaxValue() As Integer
    13. Dim max As Integer = 0
    14. For i As Integer = 0 To DataList.Count - 2
    15. max = System.Math.Max(DataList.Item(i).intX, max)
    16. Next
    17. Return max
    18. End Function
    19. Private Function Clustergroesse(intXValue As Integer, Clusteranzahl As Integer) As Integer
    20. Dim intClustergroesse As Integer
    21. intClustergroesse = intMaxValue / Clusteranzahl
    22. Return intClustergroesse
    23. End Function
    24. Private Sub clustern()
    25. Dim RowValue As CapCurvePower
    26. Dim intMaxX As Integer = MaxValue()
    27. Dim Cluster As Integer = Clustergroesse(intMaxX, 45) '45=Clusteranzahl
    28. For i As Integer = 0 To DataList.Count - 1
    29. Dim tmp As CapCurvePower = DataList(i)
    30. tmp.intXBlock = CInt((DataList.Item(i).intX / Cluster))
    31. tmp.intYBlock = CInt((DataList.Item(i).intY / Cluster))
    32. DataList(i) = tmp
    33. Next
    34. End Sub
    35. Private Sub Counter()
    36. For RowCnt As Integer = 0 To DataList.Count - 1
    37. Dim intSearchCounter As Integer = 0
    38. For CurrentRow As Integer = RowCnt To DataList.Count - 1
    39. If DataList.Item(CurrentRow).intXBlock = DataList.Item(RowCnt).intXBlock AndAlso DataList.Item(CurrentRow).intYBlock = DataList.Item(RowCnt).intYBlock Then
    40. If DataList.Item(CurrentRow).Flag = False Then
    41. intSearchCounter = intSearchCounter + 1
    42. Dim tmp As CapCurvePower = DataList(CurrentRow)
    43. tmp.Counter = DataList.Item(CurrentRow).Counter + 1
    44. DataList(CurrentRow) = tmp
    45. End If
    46. End If
    47. Next
    48. For i As Integer = 0 To DataList.Count - 1
    49. If DataList.Item(i).intXBlock = DataList.Item(RowCnt).intXBlock AndAlso DataList.Item(i).intYBlock = DataList.Item(RowCnt).intYBlock AndAlso DataList.Item(i).Flag = False Then
    50. Dim tmp As CapCurvePower = DataList(i)
    51. tmp.Counter = intSearchCounter
    52. tmp.Flag = True
    53. DataList(i) = tmp
    54. End If
    55. Next
    56. Next
    57. End Sub


    Vielen Dank schonmal für Eure Hilfe! :)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DocBizz“ ()

    Du teilst deine Menge in z.B 4 unter Mengen ein z.B (1-15000, 15001 - 30000, ...) und lässt dort je einen Thread die Haufigkeit von Koordinaten indexieren. Am Ende Rechnest du die Ergebnisse aller Threads zusammen und kommst wieder auf deine Gesamtmenge.
    Hi, ich habe mir ehrlich gesagt nicht in deinen Algorithmus eingearbeitet.
    Ich stelle einfach mal die Vermutung in den Raum, dass du dein Kooridnatensysten in größere Kästchen eingeteilt hast, und schaust, welche der Punkte sich in diesen Kästchen befinden.
    Schau dir mal diesen Algorithmus an:

    Die zwischenergebnisse von Abstandswerten etc. solltest du dann tatsächlich in einer Hashtable etc. speichern.

    Und ganz allgemein, wenn es nur um die Überprüfung geht, ob z.B. an einer Koordinate ein Wert vorliegt, empfielt es sich strengstens, eine Hashtable zu nutzen, weil du dannn einfach mit .ContainsKey(..) anfragen kannst. :)
    Damit sparst du dir eine solche Schleife:

    VB.NET-Quellcode

    1. Dim xSuche As Integer =42
    2. Dim ySuche As Integer = 32
    3. For i = 0 To Ubound
    4. If werteX(i) = xSuche And werteY(i) = ySuche Then
    5. 'Wert ist da
    6. End If
    7. Next


    Variablen über das Internet senden? [VB.NET] Universal Ticket.dll :thumbup:
    Lasse deine Programme selbstständig lernen! [VB.NET] Brain.dll
    :thumbsup:
    Jou.

    DocBizz schrieb:

    ein definiertes Spektrum um die Koordinatenposition herum reicht völlig aus
    Meinst Du ein Histogramm in 2 Achsen?
    Mach Dir ein 2-Dimensionales Feld entsprechend der Anzahl Deiner Cluster, gehe Deine Koordinaten durch und stell fest, welchem Cluster sie zugeordnetr werden und erhöhe den kommunizierenden Feldindex um 1.
    Normiere das Ergebnis und stell es farbig dar ==> Graubild, Falschfarbenbild.
    Feddich.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo zurück,

    vielen Dank erst einmal für die vielen tollen Antworten!

    @Rod: So wie du es beschreibst, mache ich es ja. Das Problem hat MrWebber mit der hashtable und der Schleife

    VB.NET-Quellcode

    1. For i = 0 To Ubound
    2. If werteX(i) = xSuche And werteY(i) = ySuche Then
    3. 'Wert ist da
    4. End If


    erkannt. Das benötigt bei mir am meisten Zeit. Das Clustern dauert nur wenige ms. Das Countern() mehrere Minuten.
    Das Schema der Abfrage hätte sich, so wie ich dich verstanden habe, nicht wirklich geändert. Oder sollte ich grundsätzlich von der List(of Structure) weg?

    @ThuCommix: Ich durchlaufe (siehe Zeile 41 und 43) die Datalist. Da frage ich ab die geannte Bedingung ab. Wenn die Scheife true ist, frage ich wie groß der Wert intCount ist und erhöhe ihn um 1. Erst am der gesamten Datalist kenne ich jeden Wert und muss noch einmal die Datalist durchlaufen und den Wert final schreiben.


    Danke an alle für eure top Hilfe *thumbsup*
    Hallo nochmal,

    ich habe mich mal etwas in das dictionary bzw. in die Hashtable eingelesen.
    Bei beiden habe ich das Problem, dass ich einen "Key"-Wert und einen Value-Wert habe.
    Der Key-Wert entspricht bei mir meinen Koordinaten X und Y. Der Value-Wert entspricht meiner Anzahl wie oft dieser Key vorkommt.
    Wie übergebe ich die multiplen Keys an das Dictionary?

    Hier mal meine Idee:

    VB.NET-Quellcode

    1. Structure Struc
    2. Dim x As Integer
    3. Dim y As Integer
    4. End Structure
    5. Dim counter As Integer
    6. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    7. Dim dic As New Dictionary(of Struc, integer)
    8. Dim counter As Integer
    9. Dim eintrag As New Struc
    10. For i As Integer = 0 To 19
    11. eintrag.x = 1
    12. eintrag.y = 2
    13. If dic.Containskey (Struc.item)Then '<------ Hier funktioniert die Syntax nicht.
    14. 'Mach was
    15. End If
    16. dic.Add(eintrag, counter)
    17. Next
    18. End Sub
    sowas sollte ratzfatz gehen, wenn wirklich auf Identität geprüft wird.

    Problematischer wird, wenn du auch Koordinaten zusammenfassen willst, die nahe beieinander liegen.

    Ich hab jetzt aber auch nicht verstanden (bzw glaube nicht recht, was ich verstanden habe) was du willst:
    Willst du wirklich nur eine Aufstellung Positions-identischer Koordinaten haben - was soll das bringen?
    Und der ZeitWert und der Integer-Wert der Datensätze ist vollkommen irrelevant?

    Vlt. kann man auch dein Structure verbessern, etwa dass da 2 x-Werte und 2 y-Werte sind, das könnte man besser mit 2 Point darstellen, und das käme auch der Auswertung zugute. Also für eine Auswertung mit Linq-Expression wäre sone Structure viel günstiger:

    VB.NET-Quellcode

    1. Structure CapCurvePower
    2. Dim dteDatum As Date
    3. Dim dteTime As Date
    4. Dim Location As Point
    5. Dim Counter As Integer
    6. Dim Block As Point
    7. Dim Flag As Boolean
    8. Dim BlockColor As Color
    9. End Structure
    naja, je länger ich diese Structure angucke, desto mehr Zweifel kriege ich, ob die was taugt - oder ob nicht eine Class angezeigt wäre.
    Aber dazu müsstest du mehr darüber erzählen, was diese Struktur modelliert
    (ich bin Datenmodell-Maniak: ich betrachte alle Daten immer als Modelle von etwas, was durch sie dargestellt wird - hier zB könnte ich mir vorstellen, dass eine einfache Spiele-Map modelliert wird.)
    Hallo ErfinderDesRades,

    das Spektrum der Koordinaten reicht von 0;0 bis 567,5678;597,154. Ich möchte aber wissen wie häufig diese Koordinaten genutzt wurden. Das muss grafisch in einer Punktewolke dargestellt werden. (Siehe mein anderer Post. Das habe ich aber selbst per .Paint gelöst)
    Da der Messwert sehr fein ausgelöst ist, kommt es nie vor, dass das gleiche Paar nochmals auftitt. D.h. meine Wolke ist sehr fein ausgelöst. Zu fein um etwas zu erkennen und um daraus rückschlüsse zu ziehen. Daher die Clusterung. 567,5678;597,154 und 565,000;595,000 gehören somit zum selben Cluster.
    Jeweile 45 in X und 45 in Y Richtung. Von >unendlichen Möglichkeiten, reduziere ich alles auf 2025 (45²). Je nach Anzahl, wie Rod schon herausgefunden hat, färbe ich das ein und stelle es als Farbwolke dar.

    Ich hoffe das erklärt mein Anliegen.

    Danke für deine Unterstützung!
    Statt Clusterung würde ich mal von Rasterung sprechen, da weiß ich besser, was das ist. Jo, und da kann man schon einen sehr flotten Durchlauf machen - hast du mal eine Testanwendung, die ein paartausend solcher Datensätze einliest?
    Kannste zippen und anhängen, dann kann ich dazu was basteln, mit meim "TresholdDictionary", zu deutsch (äh, denglish): Schwellwert-Dictionary - eine einfache Klasse von mir, die Werte nach vorgegebenen Schwellwerten gruppiert.
    Da würde ich erstmal alle nach X gruppieren, und dann jede Gruppe nochmal nach y, dann müsste man doch schon eine brauchbare Auswertung haben, oder?

    Also dass ich da was bastel, dazu müsstest du eine Testanwendung inklusive DatenDatei zippen und anhängen.


    Das Rastern funktioniert bei mir ja auch sehr schnell. (Zeile 27 - 37)
    Das Zählen der Wertepaare dauert aber. MrWebber hat das in seinem Snippet ja schon gut dargestellt. Ich denke die doppelten Abfragen benötigen sehr viel Zeit.

    Die angepassten Rohdaten habe ich mal angehangen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DocBizz“ ()

    ja, und ich soll mir jetzt die Mühe machen, auch noch eine Testanwendung dafür zu schreiben? mit dem Einlesen, und der Struct und blabla?

    Findich ist dein Job - ich bastel da nur die Analyse dran - so war das gemeint:

    ErfinderDesRades schrieb:

    Also dass ich da was bastel, dazu müsstest du eine Testanwendung inklusive DatenDatei zippen und anhängen.


    Edit: naja, vlt. ist das Einlesen halb so wild, die Struct kann ich ja auch von hier kopieren.
    Du müsstest aber mal genauer definieren, wie das Ergebnis aussehen soll:
    Anbieten könnte ich ein Dictionary(Of integer, Dictionary(Of Integer, CpCurvePover()))Da könntest du dann per X,Y ein Array von CpCurvePover abrufen, die alle in der betreffenden Zelle drinne sind.

    Aber sind natürlich auch andere Arten der Aufbereitung denkbar, vlt Integer(,) - das wäre ein 2D-Array, was pro Zelle nur die Anzahl der gefundenen CpCurvePover angibt.
    Oder whatever.

    Edit: Ach, die Daten stimmen auch garnet - das sind ja nur Koordinaten, keine CpCurvePover-Daten - ok - ich warte, bis du aufzeigst, wie das eingelesen werden soll.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Hallo ErfinderDesRades,

    danke für deine angebotene Mühe, eine ganze Analyse zu schreiben. Das sollte aber an sich nicht notwendig sein und das kann ich auch schlecht von dir erwarten.

    Das Problem ist auch, dass meine Daten etwas anonymisiert wurden. Den code müsste ich jetzt auch noch zusätzlich anpassen. Das alles mit dem Hintergrund, dass ich deinen Code nicht verstehe und ich nichts anpassen kann.
    Mir reicht es daher eigentlich, wenn ich die Richtung wüsste. Ich versuche das gerade per Dictionary zu lösen. Gibt es da keinen Weg?

    Ein fertiger Code nützt mir einfach nicht so viel. Ich finde es aber sehr net, dass du mir das angeboten hättest!



    VB.NET-Quellcode

    1. Structure Struc
    2. Dim x As Integer
    3. Dim y As Integer
    4. Dim counter As Integer
    5. End Structure
    6. Private Sub demo2()
    7. Dim dic As New Dictionary(Of Integer, Struc)
    8. Dim eintrag As Struc
    9. eintrag.x = 1
    10. eintrag.y = 2
    11. dic.Add(0, eintrag)
    12. If dic.ContainsValue(sucheintrag) Then
    13. MsgBox("treffer")
    14. 'erhöhe counter
    15. End If
    16. End Sub


    Ist das eine grobe Richtung? Mir geht es ja nicht darum ms an Rechenzeit zu sparen.

    Danke fürs Helfen!

    DocBizz schrieb:

    Das Zählen der Wertepaare dauert aber.
    Da hast Du ggf. das Prinzip mit dem Index noch nicht verstanden.
    Pseudocode:

    Quellcode

    1. Dim xy(xMax, yMax) As Integer
    2. ForEach(MessPoints)
    3. Dim x = INDEX_X(Datensatz)
    4. Dim y = INDEX_Y(Datensatz)
    5. xy(x, y) += 1
    6. Next
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Naja, du müsstest halt ein ThresholdDictionary programmieren, damit du die Werte in diskrete Bereiche einteilen kannst - das halte ich hier für den Knackpunkt.
    ThresholdDictionary: Dictionary für Schwellwerte
    Ausserdem müsste das auch 2-dimensional arbeiten, also ein Dictionary(Of Integer, Dictionary(Of Integer, struc())) oder etwas vergleichbares müsste rauskommen.

    Das wäre also die Richtung - viel vergnügen.

    Das Problem mit Erklären und Richtung und so ist: Wenn du zB den TresholdDictionary-Code verstehst, dann verfügst du vmtl. auch über genügend KnowHow, das Prob selbst zu lösen. Wenn ich das aber alles erklären soll, kann das ziemlich langatmig werden.
    Zumal vmtl. viele Fehl-Versuche zu korrigieren wären.
    Da ists glaub effizienter, ich code das, dasses funzt, und kann dir dann anhand dessen erklären, warums funzt.

    Edit: Ups - ich glaub ich denk grad zu kompliziert.
    ThresholdDictionary ist evtl. nicht nötig, denn die Bereiche sind gleichmäßig, und die Werte sind einfache Singles - die kann man auch mit einfachen Rechenoperationen bestimmten Bereichen zuordnen.

    Also schön, die Richtung:
    Du musst einen Algo finden, der zu einem beliebigen Single die Raster-Kante ausspuckt - geht mit Division und anschl. Multiplikation - evtl. gibts da auch was effizienteres.
    Dann brauchst du ein genügend großes Array.
    Dann gehst du alle Daten durch, und sortierst die Daten ins Array ein, wobei du nur die X-Werte berücksichtigst.
    Dann gehst du die Daten jeder X-Raster-Zelle nochmal durch, und unterteilst weiter, in ein Y-Raster.

    Klar soweit?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Ok, hier die Einlese-Routinen. sinnloserweise liegen mir nämlich die Daten in einem Excel-File vor. Daher ist das alles extreme Zeitaufwendig das einzulesen. In dem CSV-File fehlen jetzt nur eine paar Kopfdaten und die Zeitstempel. Ich habe den Code aber angepasst.

    VB.NET-Quellcode

    1. Sub Readin()
    2. oExcel = New excel.Application
    3. Dim filename As String = "C:\liste.xlsx"
    4. oBook = oExcel.Workbooks.Open(filename)
    5. oSheet = CType(oBook.Worksheets(1), excel.Worksheet)
    6. End Sub
    7. Sub Add2List(Row As Integer)
    8. Dim RowValue As CapCurvePower = Nothing
    9. Dim datum As Date = Nothing
    10. DateTime.TryParse(oSheet.Cells(Row, 1).value, datum)
    11. RowValue.dteDatum = datum
    12. RowValue.dteTime = datum.ToShortTimeString
    13. RowValue.intX = oSheet.Cells(Row, 1).value
    14. RowValue.intX = Abs(RowValue.intX)
    15. RowValue.intY = oSheet.Cells(Row, 2).value
    16. RowValue.intY = (RowValue.intY)
    17. RowValue.Flag = False
    18. DataList.Add(RowValue)
    19. End Sub
    20. Sub CreateSourceDataList(FirstRow2Read As Integer)
    21. Do Until CStr((oSheet.Cells(FirstRow2Read, 1).value)) = Nothing
    22. Add2List(FirstRow2Read)
    23. FirstRow2Read = FirstRow2Read + 1
    24. Console.WriteLine(FirstRow2Read)
    25. Loop
    26. End Sub


    Das diskretisieren habe ich ja mit dem Clustern/ Rastern versucht. Nur das Suchen der Wertepaare ist so aufwendig. Ich kenn' mich da nicht genug aus, aber ist das echt so aufwendig?
    Ah - gut möglich, dass Excel da einen gehörigen Anteil an der Langsamkeit hat!

    Ich weiß jetzt nicht, was du mit Suchen der Wertepaare meinst - in meinem Plan werden keine WertePaare gesucht - es werden Werte Bereichen zugeordnet - und sowas ist sehr schnell.

    Ich hätte noch eine Frage zur Ausgabe - wie willst du die Ergebnisse präsentieren?
    Willst du das Raster malen, und je nach Anzahl enthaltener CapCurvePovers eine andere Farbe nehmen, oder wie stellst du dir das vor?

    Die Frage ist wichtig - dementsprechend muss man ja ühaupt entscheiden, welche Auflistung die Ergebnisse am besten beinhalten würde.

    Ach - kann ich vb2013 verwenden?

    Edit: ach schad - die Daten taugen garnix.
    Grad hab ich dieses darin gefunden:

    Quellcode

    1. 77777;77777
    2. 77777;77777
    3. 77777;77777
    4. 77777;77777
    5. 77777;77777
    6. 77777;77777
    7. 77777;77777
    8. 77777;77777
    9. 77777;77777
    10. 77777;77777
    11. 0,49;0,00
    12. 0,62;0,00
    13. 0,60;0,00
    14. 0,43;0,00
    15. 0,45;0,00
    16. 0,64;0,00
    17. 0,62;0,00
    18. 0,45;0,00
    Oder ist das tatsächlich so, dass die Spannweite bis 77777|77777 geht, und womöglich darüber hinaus?
    Da wirst du mit Rasterweite 0,75 aber nicht auskommen, bzw. das wird ein gemein großes Raster.
    Edit:
    Ach, und es gibt auch negative Werte:

    Quellcode

    1. 109,12;-4,27
    2. 108,89;-5,49
    3. 109,14;-1,93
    4. 109,20;3,86
    5. 109,00;27,54
    6. 118,21;63,74
    7. 172,74;65,42
    8. 307,55;68,44
    9. 404,80;90,04
    10. 414,30;101,43
    11. 416,80;104,40
    12. 417,64;104,22
    13. 366,85;98,32

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Das Einlesen dauert zwar noch, das werde ich aber noch ändern. Das ist bei dem zeitlichen Umfang den das ganze in anspruch nimmt, ist da noch gar nicht enthalten.

    Ich zeichne zu anfangs ein Koordiantensystem mit 45x45 Blöcken (mit .Fillrectangle(mybrush, x,y, 8,8 per For-Schleife mit Step 10)
    so erscheint das dann auch wie ein Raster. Es ist ja in dem 45x45 Raster nicht jeder Wert belegt. Wenn das Clustern und Zählen fertig ist, zeichne ich nur noch den .intXBlock und .intYBlock Wert, mit den entsprechenden Breiten 8,8.
    So sieht das Raster dann gefüllt aus.

    Ich färbe je nach Anzahl des Auftretens des gerasterten Blockes das zu zeichnende Kästchen anders. Je häufiger desto dunkler der Farbton. Daher ist der Wert "counter" ja so wichtig. ich habe hier vb2012. ich denke also ja.


    Danke! das ist echt super von dir!!

    Edit: Wie ich in einem anderen Post geschrieben habe, versuchte ich das über 3D-Balkendiagramme zu lösen. MSChart war da aber etwas mit überfordert und ich konnte den Sichtwinkel nicht frei anpassen. Daher jetzt über "pseudo" 3D.

    Edit: 77777 sind Fehlwerte. Die sollten ignoriert werden. Die negative Werte können erst einmal per abs() in positive geändert werden.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „DocBizz“ ()

    DocBizz schrieb:

    Die negative Werte können erst einmal per abs() in positive geändert werden.
    Das ist nicht unbedingt gut, weil das ein echter Fehler sein kann.
    Suche Max und Min und nutze diese Werte zum Skalieren.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Da das Diagramm mit Kästchen gefüllt ist, die die Farbe haben die count=0 entsprechen, reicht es auch, dass count>0 ist.

    @Rod: Ich weiß. Das Problem löse ich, in dem ich alle Quadranten des karthesischen Koordinatensystems zeichne. Aktuell ist das noch I und IV. Das reicht erstmal. Erst einmal das eine Problem lösen :)