# Schwarmsimulation



## Dr.Gonzo93 (21. Nov 2011)

Hallo,
bin in der 12ten klasse und ich habe die Aufgabe, eine Schwarmsimulation zu schreiben, die Threads verwendet.
Leider ist mein latein bei doppelt verketteten listen am ende...(und die krieg ich auch nur mit sehr viel mühe hin^^)
und etwas grafisches haben wir auch noch nie programmiert.
Die Simulation soll ungeordnet beginnen und sich dann formieren.(am besten irgendeine schöne form, z.B wie ein vogelschwarm als "V")
als objekte genügen kreise.
Jetzt ist meine Frage, wie ich das anstellen soll.. ich würde ja gerne einen ansatz präsentieren, weiß aber leider gar nicht, wo ich anfangen soll. :bahnhof:
falls jemand ein tutorial o.ä. kennt, wäre ich für einen link sehr dankbar.
oder auch tipps, mit was ich anfangen soll, wären echt super.

falls ich das aber nicht selbst hinkriege( un die chancen stehen nicht schlecht), wäre mir eine funktionierende version nen 20er ucash wert. dann wär es aber auch super, wenn sie für mich nachvollziehbar formuliert ist, evtl mit einigen kommentaren.

Natürlich würde ich es gerne erst mal selbst versuchen, ich will ja auch was lernen.
Aber dafür brauch ich trotzdem fachkundige hilfe!
hoffe jemand erbamt sich und gibt mir ein paar tipps...
schonmal vielen dank!


----------



## qowaz (21. Nov 2011)

Kannst du mal die vollständige Aufgabenbeschreibung posten?

Verstehe nicht wirklich was gefragt ist.


----------



## Dr.Gonzo93 (21. Nov 2011)

die wurde nur mündlich gegeben, und auch nicht sehr genau.
da ist auch rellativ viel spielraum für eigenes, im prinzip soll es nur eine grafische simulation sein, aber mit threads..
das mit dem vogelschwarm war nur ein beispiel.
was mein lehrer auch vorgeschlagen hat, ist eine sich brechende welle. das stell ich mir aber noch schwerer vor.
ich nehme mal an, das ganze wird mit einem drawpad dargestellt?


----------



## Marco13 (21. Nov 2011)

WTF ist ein Drawpad? Wie auch immer, es gibt ja viel Listeratur zu dem Thema. Eine grobe Idee, welche Klassen es geben könnte, und welche Methoden die haben könnten, wäre vielleicht ein erster Schritt...


----------



## Dr.Gonzo93 (21. Nov 2011)

hab grad nochmal ein bisschen überlegt, wie ich die aufgabe besser deutlich machen kann.
ich versuch's nochmal an dem beispiel mit dem vogelschwarm:
man erzeugt z.B 20 kreise, die an einer zufälligen stelle des drawpads(wenn das damit funktioniert) erscheinen.
diese sollten aber nicht ineinander liegen können, also bei gleicher "platzbelegung" neue zufallskoordinaten wählen.
dann sollten sich diese kreise gemächlich über das drawpad bewegen und entweder an den ecken apprallen, oder auf der gegenüberliegenden seite wieder auftauchen.
Sie sollten sich langsam annähern und einen schwarm bilden(wie z.B. dieses "V"). also müssen sie die abstände zu den anderen kreisen kennen und auch ihre geschwindigkeit anpassen können.
so ist die idee im groben...

drawpad gibts in netbeans(damit arbeiten wir), ist halt sone zeichenoberfläche.. aber viel hatte ich damit auch noch nicht zu tun. 
habe damit nur mal bunte strahlen erzeugt..(auch mit zufälligen koordinaten)


----------



## Marco13 (21. Nov 2011)

Hmja... pragmatisch...



Dr.Gonzo93 hat gesagt.:


> also müssen sie die abstände zu den anderen kreisen kennen und auch ihre geschwindigkeit anpassen können.
> so ist die idee im groben...



-> 

```
interface WhichWillCertainlyNotBeCalledKreis
{
    float distanceTo(WhichWillCertainlyNotBeCalledKreis other);
    void setVelocity(Vector2D velocity);
    ...
}
```

Erstmal keine Rocket Science draus machen. Bird Science reicht


----------



## Dr.Gonzo93 (21. Nov 2011)

ja okay, das hört sich schonmal ganz gut an, danke!
jetz werd ichs aber aus protest kreis nennen xD


----------



## Dr.Gonzo93 (21. Nov 2011)

jetzt fehlt mir noch die gemächliche bewegung, die am anfang am besten auch in zufällige richtungen verläuft.
und wie stell ich das an, wenn dann so ein kreis am ende der fläche angekommen ist und dann auf die gegenüberliegende seite "rübergebeemt" wird? am besten noch mit der selben richtung..
vielleicht mit einer if abfrage wie(bei 1000*1000pixel):
if this.Kreis a.getKoordinaten()==(1000;327){
this.Kreis a.setKoordinaten(1;327);
} 
???
ihr dürft ruhig lachen ^^

die art der formation muss ich ja dann auch noch irgendwie bestimmen.

sorry wenn das alles hier für die meisten von euch kinderkram is, aber ich habs halt nichso mit der implementierung..
die überlegungen dazu krieg ich ja noch hin, aber wenns dann an den quellcode geht...


----------



## Marco13 (22. Nov 2011)

DIe Überlegungen sind am Anfang auch erstmal wichtiger... Wie man vorhat, das ganze zu modellieren. Schon dort treten Fragen auf, die man möglichst schon klären oder im Hinterkopf haben sollte, bevor man auch nur eine Zeile Code schreibt. Als Beispiel eine, die sich auf das bezieht, was du jetzt geschrieben hast: 
Wenn ein "Kreis" (grml...  ) bei 999,327 ist, und sich dann 1 nach rechts bewegt (also bei 1000,327 landen würde) soll er bei 1,327 landen. Wenn man einen zweiten Kreis bei 999,328 hat, der seine Position nicht verändert, wie groß ist dann der Abstand dieses Kreises zum ersten - vor und nach dem "Sprung"?


----------



## Dr.Gonzo93 (22. Nov 2011)

hmm... dann muss ich das ganze wohl als eine art kreis betrachten. also, dass der nachfolger des letzten pixels der erste pixel ist. und das in x und y richtung.. dann müsste man auch die abstände bestimmen können.
zu deinem beispiel würd ich sagen, dass der kreis dann bei 0,327 landet(ist aber vielleicht gar nicht möglich,wenn der kreis einen ganzen pixel belegt), damit es einigermaßen flüssig aussieht. 
oder man rundet halt auf den nächsten ganzzahligen pixel auf und addiert diese zahl zum abstand des zweiten kreises zur wand.
Bsp:
kreis 1: 999,820---->0,820 aufgerundet auf 1
kreis 2 :998,100
abstand zwischen kreis 1&2 vor dem sprung:1,720p
abstand nach dem sprung:2,900p

naja, ich überlege mir die tage mal die gesamtstruktur des ablaufes und poste die dann. vielleicht kann mir dann ja jemand bei der implementierung helfen und eventuelle fehler aufzeigen...

schonmal vielen dank für deine tipps!


----------



## ARadauer (22. Nov 2011)

Du bist schon viel zu detailiert, beschäftige dich doch erst mal theoretisch mit dem Thema...


if this.Kreis a.getKoordinaten()==(1000;327){
nö beim setzen modulo der breite rechnen... bzw halt > nicht ==


----------



## Dr.Gonzo93 (22. Nov 2011)

ja, das war schwachsinn... 
den gedanken hab ich auch schon verworfen.

wie gesagt, ich überlege mir jetz die tage mal den theoretischen ablauf des ganzen und poste den dann..


----------



## Andi_CH (23. Nov 2011)

Das ist so faszinierend - dass muss zur Auflockerung einfach hinein

Wenn dem da ein mathematisches Modell zugrunde liegt, kann man es auch simulieren.

Ich denke das einzige Problem, dass hier konkret wieder einmal mehr existiert, ist die Tatsache, dass der TO keine Ahnung hat *was* er machen soll ...

So Gedankenblitze:

Es braucht einen Leitvogel.

Es braucht eine Hierarchie (1-n Beziehung : ein oberer n untere)

Nur der Leitvogel fliegt nach freiem Willen

Jeder der Unteren fliegt seinem oberen nach, achtet aber immer auf genügend Abstand zu den höheren und gleichgestellten (die untergeordneten müssen selbst schauen)

Zielkoordinate für einen Vogel ist in einerm definierten Abstand hinter dem übergeordneten

Dass dynamik reinkommt brauchen die Vögel eine gewisse Trägheit.


----------



## schalentier (23. Nov 2011)

Andi_CH hat gesagt.:


> Es braucht einen Leitvogel.



Ne, der Clou bei der Simulation von Schwaermen ist ja gerade, dass es keine zentrale Steuerinstanz gibt. 

Jedes Individuum verhaelt sich genau gleich und orientiert sich lediglich an seinen Nachbarn (und weicht natuerlich Hindernissen oder Gefahren aus). Im Grunde ganz einfach, nur skalieren die Algorithmen recht schlecht (O(n*n) laut Wikipedia). Deswegen wahrscheinlich auch der Punkt mit den Threads. Nur ist das alles andere als einfach. 

Wieso sollst du eine Anwendung aus einem KI-Forschungsgebiet schreiben, wenn du grad so mit Doppelt Verketteten Listen klarkommst?


----------



## Marco13 (23. Nov 2011)

Andi_CH hat gesagt.:


> Wenn dem da ein mathematisches Modell zugrunde liegt, kann man es auch simulieren.



"Mathematisches Modell" klingt IMHO zu "stark". Es sind in der Tat nur einfache Regeln, und die komplexen Strukturen bilden sich "automatisch". 

Der Punkt mit dem Fehlenden Leitvogel wurde ja schon genannt. Mich hatte auch irritiert, dass einerseits von einem Schwarm die Rede war, andererseits von dieser V-Formation - diese Formation ist bestenfalls eine spezielle Ausprägung eines (kleinen) Schwarms, die aber auch nicht explizit modelliert wird, sondern sich aus einfachen Regeln ergibt (oder ergeben sollte). 

Die Lösung für dieses Problem (d.h. das Programmieren so einer Simulation) an sich ist wohl eine dieser vielen Aufgaben, die man (mit etwas Übung und einer groben Idee) an ein, zwei Nachmittagen schon ganz ansehnlich hinbekommt, mit der man aber auch mehrere (oder gar beliebig viele) Forscherleben ausfüllen kann. Als Schaulaufgabe mit der lapidaren Aufgabenstellung: "Mach' eine Schwarmsimulation mit mehreren Threads" kann man aber schon etwa einschätzen, wie man da ran gehen könnte - auch wenn man noch einen nicht unerheblichen Spielraum beim "Grad der Erfüllung" dieser Aufgabe hat (oder kurz: Am Ende gibt's was zwischen 1 und 6  )


----------



## Andi_CH (23. Nov 2011)

Für die Situation im Video fragte ich nach dem mathematischen Modell.
Ein gemeinsames Ziel scheinen die Viecher nämlich zu haben - wenn es nicht ein Leitvogel ist, ist es halt was anderes (z.B. eine sich bewegende Futterquelle)

Und betreffend Leitvogel - wer nur einmal in seinem Leben Gänse in V-Form hat fliegen sehen weiss, dass es in gewissen Situationen sehr wohl einen Leitvogel gibt.

Dann noch etwas - wenn ich so etwas schreibe ist es durchaus auch eine Zusammenfassung (sonst muss ich wieder Vorwürfe lese, ich läse die Posts nicht)

Es ist der Ansatz einer Analyse oder besser Requirements-Spec - damit sollte *jede* Problemlösung begonnen werden.

Der nächste Schritt ist dann zu beschreiben wie sich ein einzelner Vogel verhält - aufgrund welcher Kriterien er seinen Geschwindigkeitsvektor verändert und welche Reaktionszeit er hat.


----------



## Dr.Gonzo93 (23. Nov 2011)

um auf die frage einzugehen, warum ich soetwas komplexes schreiben soll,
unser lehrer geht wohl davon aus, dass wir alle informatik studieren wollen und will uns schon an die ansprüche gewöhnen.

ich stelle mir das ungefähr so vor, wie andi das beschrieben hat. dass es es einen leitvogel gibt, dem die anderen folgen. das sollte aber nich von anfang an so sein. am anfang sollten sich alle vögel selbständig in zufällige richtungen bewegen und sich nach z.B 10sec laufzeit(oder auf knopfdruck) anfangen zu formieren. in dieser formation folgen dann alle dem leitvogel...

es geht auch nicht unbedingt darum, das verhalten von vögeln 1zu1 wiederzugeben, dass wäre auch zuviel verlangt. 
unser lehrer will nur sehen, das wir mit threads arbeiten können(welche wir aber nicht einmal besprochen haben) und dass wir eine grafische simulation hinbekommen.
der spielraum liegt sogar zwischen 1 und 15  (haben dieses punktesystem)

schön zu sehen, dass sich zu dem thema soviele gedanken gemacht und auch gepostet wurden.
vielen dank!


----------



## Marco13 (23. Nov 2011)

Andi_CH hat gesagt.:


> Für die Situation im Video fragte ich nach dem mathematischen Modell.
> Ein gemeinsames Ziel scheinen die Viecher nämlich zu haben - wenn es nicht ein Leitvogel ist, ist es halt was anderes (z.B. eine sich bewegende Futterquelle)
> 
> Und betreffend Leitvogel - wer nur einmal in seinem Leben Gänse in V-Form hat fliegen sehen weiss, dass es in gewissen Situationen sehr wohl einen Leitvogel gibt.



Für die Gänse gibt es automatisch einen Leitvogel - nämlich den vordersten. Deswegen fand ich das in der ursprünglichen Aufgabe auch so "widersprüchlich" :bahnhof: Aber vielleicht ist es nur eine Frage der Definition: Du hast ja schon das "gemeinsame Ziel" angesprochen, irgendeinen Bezugspunkt - das könnte ja so ein "Leitvogel" sein - aka der Vogel, den man mit der Maus umherzieht  Wenn es GAR keinen Bezug, keine Richtung und keinen Anstoß (oder Abstoß - von Feinden  ) gibt, bewegen sich AFAIK früher oder später alle im Kreis....


----------



## Dr.Gonzo93 (7. Jan 2012)

Hallo,
hat sich ja lange nichts bei mir getan, jetzt muss das Projekt aber bald mal fertiggestellt werden.
Wäre echt super, wenn sich nochmal jemand kurz damit auseinandersetzen könnte.

Das Grundgerüst steht, die Vögel fliegen kreuz und quer über das Feld. Nur das Implementieren der Formation stellt mich vor ein Rätsel. 

Erstmal habe ich das Problem, dass ich nicht weiß, wie ich die einzelnen Bots anwähle, habe nur eine Botliste und aus der kann ich nicht einfach Bot1,Bot2 usw auswählen. Genau das brauche ich aber um die Abstände in der Formation zu definieren.
Außerdem weiß ich nicht genau, wie das funktioniert, dass die Bots nicht schlagartig in der Formation sind, sondern sich erst annähern. Dazu habe ich zwar schon eine kleine Anpassung, diese funktioniert aber nicht 100%ig
[JAVA=42]public void scan_nah()
    {
   //    Geschwindigkeit anpassen
      Double vx_neu=this.vx;
        Double vy_neu=this.vy;
        int anz=1;
        Knoten aktuell=nachbarn.getStart();
        while(aktuell!=null)
        {
            vx_neu+=aktuell.getBot().vx;
            vy_neu+=aktuell.getBot().vy;
            anz++;
            aktuell=aktuell.getNF();
       }
        this.vx=vx_neu/anz;
        this.vy=vy_neu/anz;

    }[/code]

Ich habe in der Benutzeroberfläche einen Button angelegt, auf dessen Betätigung sich die Bots als "v" anordnen sollen. Jetzt muss ich doch eine Methode erstellen, die erst nach betätigen des Buttons auf true gesetzt wird, oder?
Hier mal der quelltext aus dem Bereich Bot:

[JAVA=42] package schwarm;
/**
 *
 * @author ich
 */
public class bot extends Thread {
    private double x_position, y_position, vx,vy;
    private Animation ausgabe;
    private Liste botliste;
    private Liste nachbarn;

    public bot(Double max_v, Animation a, Liste b)
    {
        x_position=Math.random()*a.getWidth();
        y_position=Math.random()*a.getHeight();
        botliste=b;
        do
        {
             Double Richtungx=Math.random()*2;
             vx=Math.random()*max_v;
             if (Richtungx<1.0) vx=-1.0*vx;
        }while(Math.abs(vx)<0.1);
        Double Richtungy=Math.random()*2;
        vy=Math.sqrt(max_v*max_v-vx*vx);
        if (Richtungy<1.0) vy=-1.0*vy;
        ausgabe=a;
    }

    public boolean abstandzu_unter(bot x, Double abstand)
    {
        if ((abstand*abstand)>((this.x_position-x.x_position)*(this.x_position-x.x_position)+(this.y_position-x.y_position)*(this.y_position-x.y_position)))return true; else return false;
    }

    public void scan_nah()
    {
//        Geschwindigkeit anpassen
//        Double vx_neu=this.vx;
//        Double vy_neu=this.vy;
//        int anz=1;
//        Knoten aktuell=nachbarn.getStart();
//        while(aktuell!=null)
//        {
//            vx_neu+=aktuell.getBot().vx;
//            vy_neu+=aktuell.getBot().vy;
//            anz++;
//            aktuell=aktuell.getNF();
//        }
//        this.vx=vx_neu/anz;
//        this.vy=vy_neu/anz;
//        
    }

    public void scan_weit()
    {
        //scan über alle bots, um die nachbarn heraus zu finden
        nachbarn=new Liste();
        Knoten aktuell= botliste.getStart();
        while(aktuell!=null)
        {
            if(abstandzu_unter(aktuell.getBot(),300.0)) nachbarn.add(new Knoten(aktuell.getBot()));
            aktuell=aktuell.getNF();
        }
    }

public void formation_v()
{


}
    public void run()
    {
        this.scan_weit();
        while(true)
        {
            int count=0;

            if (count>10)
            {
                this.scan_weit();
                count=0;
            }
            if (this.nachbarn.getSize()>0)this.scan_nah();
            x_position+=vx;
            y_position+=vy;
            if(x_position<0) x_position=ausgabe.getWidth()+x_position;
            if(x_position>ausgabe.getWidth()) x_position-=ausgabe.getWidth();
            if(y_position<0) y_position=ausgabe.getHeight()+y_position;
            if(y_position>ausgabe.getHeight()) y_position-=ausgabe.getHeight();
            System.out.println(this.toString()+String.valueOf(nachbarn.getSize()));
            ausgabe.repaint();
            count++;
            try { sleep(10); }
            catch(InterruptedException e) { }
        }
    }
    public int getx()
    {
        return (int)Math.round(x_position);
    }
    public int gety()
    {
        return (int)Math.round(y_position);
    }

}
[/code]

Hat jemand eine Idee für die Methode Formation_v? Bin leider echt ziemlich ratlos...


----------



## Marco13 (8. Jan 2012)

Grauslige Namen, kompliziert durch fehlende Point2D/Vector2D-Klasse, schwer debuggbar durch Math.random - und... "Liste" ist irgendeine selbsgebastelte verkettete Liste?! Was spricht gegen ArrayList, da hat man auch indizierten Zugriff mit birds.get(1), birds.get(2), ...


----------



## Dr.Gonzo93 (8. Jan 2012)

die Namen sind größtenteils nicht auf meinem Mist gewachsen, das Grundgerüst hat der Lehrer bereitgestellt.
Und ja, die Liste ist so eine selbstgebastelte...
[JAVA=42]
public class Liste {
    private Knoten start;
    private int size;

    public Liste()
    {
        start=null;
        size=0;
    }

    public void add(Knoten neu)
    {
        Knoten aktuell;
        if(start==null)
        {
            start=neu;
            size=1;
        }
        else
        {
            aktuell=start;
            while(aktuell.getNF()!=null)
            {
                aktuell=aktuell.getNF();
            }
            aktuell.setNF(neu);
            size++;
        }
    }
    public int getSize()
    {
        return size;
    }
    public Knoten getStart()
    {
        return start;
    }

}
[/code]

Das mit der arraylist hört sich gut an, muss ich mir mal angucken, wie die geht.
Von dieser vector2D Klasse habe ich zwar schon gehört, aber leider keinen Plan, wie ich die anwende.
Könnte ich damit die Formation erzeugen?

Gibt es denn keine Möglichkeit, mit dem Vorhandenen eine Methode zu schreiben, die diese Formation erzeugt?
Und falls es eine gibt, kann mir vielleicht jemand bei der Implementierung helfen?
Den theorethischen Ablauf kann ich ja mal schildern:

-Mit den vorhandenen Methoden werden die Nachbarn erkannt.
-Vogel1 wird Leitvogel(das wird einfach so definiert)
-Alle anderen bekommen die selbe Richtung wie der Leitvogel aber eine höhere Geschwindigkeit
-Sobald Vogel2&3 den Abstand 10pixel erreicht haben, auch die selbe Geschwindigkeit
-Vogel2&3 sollen  10pixel in x und y richtung hinter dem LV fliegen(also einer y=+10/der andere y=-10)
das selbe dann mit vogel3,4,5,6,usw
- Schwierig wird es dann, wenn der LV mal nicht gerade senkrecht fliegt, und das wird er sehr häufig tun...

 Für Ideen/Implementierungsvorschläge wäre ich sehr dankbar!


----------



## Marco13 (8. Jan 2012)

So eine Vector2D oder Point2D-Klasse (gibt's schon in java.awt.geom) würde helfen, manches kompakter zu machen. So eine Klasse könnte dann eben Methoden haben wie
point.distanceTo(otherPoint) 
oder
vector.length()
oder 
vector.add(otherVector)

Ohne den Code (aus den angedeuteten Gründen) im Detail nachvollzogen zu haben: Diese V-Formation ist, wie schon gesagt wurde, eigentlich nicht das, was ich unter einem "Schwarm" verstehen würde, aber gut. 

Jeder Vogel hätte eine Position und eine Richtung. Um sicherzustellen, dass dabei ein "V" entsteht, müßte man vermutlich recht "spezielle" Informationen in die Vogel-Klasse packen. Im einfachsten Fall, nur ganz grob und spontan aufgeschrieben:
- Jeder Vogel hat einen Vogel, dem er folgt. 
- Jeder Vogel darf nur EINEN Verfolger haben - außer dem Leitvogel, der hat zwei
- Jeder Vogel hat einen "Versatz" zu dem, dem er folgt: Ein Stück weiter hinten, und ein Stück weiter rechts bzw. links
- Jeder Vogel hat den gleichen Versatz wie der, dem er folgt - die beiden, die dem Leitvogel folgen, geben den Versatz für alle weiteren vor.


----------



## Dr.Gonzo93 (8. Jan 2012)

Ja, das hört sich gut an. Also die Bedingungen..

Dass das dann nicht wirklich ein Schwarm ist, ist erstmal nebensächlich. Ich bin ja kein Vogelforscher. Es soll nur nett aussehen. Un da alle anderen Gruppen aus meinem Kurs die zufällige Richtung beibehalten haben und ich das rellativ langweilig fand, habe ich mir halt das hier überlegt.

Ich denke, ich werde das Ganze dann auch über diese vector2D klasse machen. 
Nur, wie implementiere ich den Versatz? Netbeans kennt das bestimmt nicht...
Dieser muss ja auch bei Richtungswechseln weiter bestehen.

Danke schonmal, ich schaue mir dann jetzt erstmal dieses Vector2d an.


----------



## Marco13 (8. Jan 2012)

"Diese" Vector2D-Klasse gibt es nicht - es ging darum, dass man sich was basteln könnte, was einem sowas wie http://www.java-forum.org/spiele-mu...iniges-geometrie-punkte-vektoren-geraden.html einfacher macht. Die java.awt.geom.Point2D ist schonmal ein Ansatz, könnte für die meisten Sachen ausreichen - zusammen mit ein paar Utility-Methoden für Kreuz- und Skalarprodukt, Skalierung, Addition etc.

Diesen "Versatz" könnte man recht allgemein beschreiben: Jeder Vogel macht ja das gleiche. Er versucht, eine "Zielposition+Ausrichtung" erreichen, der er sich in kleinen Schritten annähert. Für den Leitvogel ist die gegeben durch die aktuelle Mausposition, und die Differenz zwischen der vorherigen und der aktuellen Position. Für alle weiteren wird diese Zielposition+Ausrichtung berechnet aus der aktuellen Position+Ausrichtung des Vogels, dem er folgt. 

Ja, wer hätte gedacht, dass ich mich mal so intensiv mit Vögeln beschäftigen würde.

*räusper*


----------



## Dr.Gonzo93 (9. Jan 2012)

Ich glaube, das übersteigt meinen Java-Horizont.

Aber ich guck mal, ob ich da sowas zusammengebastelt bekomme 

Danke für die Tipps. Legst du wert auf extra abgegebene "danke"? Wenn ja will ich dir gerne eines abgeben


----------

