• Hallo liebe Userinnen und User,

    nach bereits längeren Planungen und Vorbereitungen sind wir nun von vBulletin auf Xenforo umgestiegen. Die Umstellung musste leider aufgrund der Serverprobleme der letzten Tage notgedrungen vorverlegt werden. Das neue Forum ist soweit voll funktionsfähig, allerdings sind noch nicht alle der gewohnten Funktionen vorhanden. Nach Möglichkeit werden wir sie in den nächsten Wochen nachrüsten. Dafür sollte es nun einige der Probleme lösen, die wir in den letzten Tagen, Wochen und Monaten hatten. Auch der Server ist nun potenter als bei unserem alten Hoster, wodurch wir nun langfristig den Tank mit Bytes vollgetankt haben.

    Anfangs mag die neue Boardsoftware etwas ungewohnt sein, aber man findet sich recht schnell ein. Wir wissen, dass ihr alle Gewohnheitstiere seid, aber gebt dem neuen Board eine Chance.
    Sollte etwas der neuen oder auch gewohnten Funktionen unklar sein, könnt ihr den "Wo issn da der Button zu"-Thread im Feedback nutzen. Bugs meldet ihr bitte im Bugtracker, es wird sicher welche geben die uns noch nicht aufgefallen sind. Ich werde das dann versuchen, halbwegs im Startbeitrag übersichtlich zu halten, was an Arbeit noch aussteht.

    Neu ist, dass die Boardsoftware deutlich besser für Mobiltelefone und diverse Endgeräte geeignet ist und nun auch im mobilen Style alle Funktionen verfügbar sind. Am Desktop findet ihr oben rechts sowohl den Umschalter zwischen hellem und dunklem Style. Am Handy ist der Hell-/Dunkelschalter am Ende der Seite. Damit sollte zukünftig jeder sein Board so konfigurieren können, wie es ihm am liebsten ist.


    Die restlichen Funktionen sollten eigentlich soweit wie gewohnt funktionieren. Einfach mal ein wenig damit spielen oder bei Unklarheiten im Thread nachfragen. Viel Spaß im ngb 2.0.

JavaScript identische Array Inhalte zählen

freekiller

NGBler

Registriert
17 Nov. 2015
Beiträge
43
Ort
Schweiz
Hallo zusammen

gegeben ist ein Array mit undefinierter Anzahl an Zeilen welche jeweils wie folgt aufgebaut ist:
[src=javascript]
{name: "irgendwas", email: "demo@demo.de", rating: "gut", rating2: "okay", message: "etwas text"}
{name: "irgendwas", email: "demo@demo.de", rating: "gut", rating2: "solala", message: "etwas text"}
{name: "irgendwas", email: "demo@demo.de", rating: "gut", rating2: "okay", message: "etwas text"}
{name: "irgendwas", email: "demo@demo.de", rating: "schlecht", rating2: "okay", message: "etwas text"}
{name: "irgendwas", email: "demo@demo.de", rating: "gut", rating2: "gut", message: "etwas text"}
{name: "irgendwas", email: "demo@demo.de", rating: "mittel", rating2: "okay", message: "etwas text"}
[/src]

Nun möchte ich mit JS rating & rating2 so auslesen, dass gezählt wird wie viele "gut" hat es beim rating, wie viele "schlecht" hat es beim rating, wie viele "gut" hat es beim rating2 etc.
Diese einzelnen Werte möchte ich gerne in einer Variabel hinterlegen. Allerdings ist mir bis anhin nicht bekannt wie komplette Wörter ausgelesen werden sondern nur einzelne Strings.

Ich freue mich auf die Hilfe
 

CPU

Neu angemeldet

Registriert
16 Feb. 2015
Beiträge
238
1. Das ist kein Array, das sind mehrere JSON Objekte
2. Zugriff auf einzelne Eigenschaften deines Objekts hast du über Objektname.Eigenschaftname
3. Würde ich ein sogenanntes "Nested JSON Objekt" erstellen, also ineinander verschachtelt.

z.B. so:
[src=javascript]var meinObjekt = {"1": {"name": "irgendwas", "email": "demo@demo.de", "rating": "gut", "rating2": "okay", "message": "etwas text"}, "2": {"name": "irgendwas", "email": "demo@demo.de", "rating": "gut", "rating2": "solala", "message": "etwas text"}}[/src]

Dann kannst du auf das Objekt folgendermaßen zugreifen: meinObjekt.1.rating bzw. meinObjekt.2.rating2 usw.

Hier die Lösung:

[src=javascript]
var obj = {"1": {"name": "irgendwas", "email": "demo@demo.de", "rating": "gut", "rating2": "okay", "message": "etwas text"}, "2": {"name": "irgendwas", "email": "demo@demo.de", "rating": "gut", "rating2": "solala", "message": "etwas text"}};
var gut = 0, okay = 0, solala = 0;
for(var i = 1; i < Object.keys(obj).length + 1; i++){
var rating = obj.rating;
var rating2 = obj.rating2;
switch(rating){
case "gut":
gut++;
break;
case "okay":
okay++;
break;
case "solala":
solala++;
break;
}
switch(rating2){
case "gut":
gut++;
break;
case "okay":
okay++;
break;
case "solala":
solala++;
break;
}
}
console.log(gut + " " + okay + " " + solala);
[/src]

Musst halt nur noch die entsprechenden Variablen "schlecht", usw. hinzufügen und die Cases zum Hochzählen der Variablen erstellen.

https://jsfiddle.net/ev5kbtcm/1
 
Zuletzt bearbeitet:

MingsPing

NGBler

Registriert
15 Juli 2013
Beiträge
347
Wenn Du Underscore (ähnlich wie jQuery) benutzt, dann sind es 3 Zeilen Code :-)

[src=javascript]
var data = [{name: "irgendwas", email: "demo@demo.de", rating: "gut", rating2: "okay", message: "etwas text"},
{name: "irgendwas", email: "demo@demo.de", rating: "gut", rating2: "solala", message: "etwas text"},
{name: "irgendwas", email: "demo@demo.de", rating: "gut", rating2: "okay", message: "etwas text"},
{name: "irgendwas", email: "demo@demo.de", rating: "schlecht", rating2: "okay", message: "etwas text"},
{name: "irgendwas", email: "demo@demo.de", rating: "gut", rating2: "gut", message: "etwas text"},
{name: "irgendwas", email: "demo@demo.de", rating: "mittel", rating2: "okay", message: "etwas text"}];

var rating1Group = _.groupBy(data, function(d){return d.rating});
Object.keys(rating1Group).forEach(function(key) {
rating1Group[key] = rating1Group[key].length;
});
console.log(rating1Group);[/src]

(Underscore wegen der "groupBy"-Funktion, sonst müsste man die noch selbst schreiben (3-4 Zeilen...)).

Fiddle (Öffne Browser-Konsole, um den Output zu sehen).
 
Zuletzt bearbeitet:

CPU

Neu angemeldet

Registriert
16 Feb. 2015
Beiträge
238
@MingsPing: Ohne den Threadstarter beleidigen zu wollen, vermute ich, dass er JavaScript-Anfänger ist. Deine Lösung ist relativ fortgeschritten, so würde ein Anfänger nicht gerade programmieren und vermutlich würde er dein Code auch nicht verstehen. Wir wissen, dass viele Wege nach Rom führen, deine Lösung ist natürlich richtig, aber verständlicher finde ich meine Lösung für den Threadstarter.
 

BurnerR

Bot #0384479

Registriert
20 Juli 2013
Beiträge
5.505
Halt schönes, funktionales Programmieren :D.
Stimme CPU aber zu, lieber seine Variante übernehmen, die der TE dann auch versteht.
 

CPU

Neu angemeldet

Registriert
16 Feb. 2015
Beiträge
238
Da sich der Threadersteller bereits bedankt hat und die Lösungen gesehen hat, welche hast du denn genommen?
 

MingsPing

NGBler

Registriert
15 Juli 2013
Beiträge
347
Stimmt, mein Code-Beispiel ist nicht ganz so basic wie der andere. Meiner Meinung nach aber tatsächlich sehr anschaulich und gut verständlich, was passiert. Falls also Interesse an Erklärung besteht, gerne!

Einen Vorteil sehe ich in meiner Variante: Man muss die Ausprägungen des Ratings (also bspw. "gut", "solala") nicht kennen!
 

CPU

Neu angemeldet

Registriert
16 Feb. 2015
Beiträge
238
Wie gesagt, ich bezweifle, dass der Threadstarter überhaupt versteht was dein Code macht.
Er hat ja auch JSON Objekte mit Arrays verwechselt.
 

theSplit

1998
Veteran Barkeeper

Registriert
3 Aug. 2014
Beiträge
28.573
Oder ihr versucht diese Varainte:

[src=javascript]var data = [{ name: "irgendwas", email: "demo@demo.de", rating: "gut", rating2: "okay", message: "etwas text" }, { name: "irgendwas", email: "demo@demo.de", rating: "gut", rating2: "solala", message: "etwas text" }, { name: "irgendwas", email: "demo@demo.de", rating: "gut", rating2: "okay", message: "etwas text" }, { name: "irgendwas", email: "demo@demo.de", rating: "schlecht", rating2: "okay", message: "etwas text" }, { name: "irgendwas", email: "demo@demo.de", rating: "gut", rating2: "gut", message: "etwas text" }, { name: "irgendwas", email: "demo@demo.de", rating: "mittel", rating2: "okay", message: "etwas text" }];

let ratings = {}

for (let item of data) {
for (let key of Object.keys(item)) {
if (key.startsWith('rating')) {
ratings[item[key]] !== undefined ? ++ratings[item[key]] : ratings[item[key]] = 1
}
}
}

console.log(ratings)[/src]

Vorteil: "Alles was mit [kw]rating[/kw] als Schlüssel beginnt, wird erfasst.
Und man braucht die Werte nicht kennen, da die Felder die Anzahl und den Schlüssel gleichzeitig erfassen.
 
Zuletzt bearbeitet:

electric.larry

\''; DROP TABLE user; --
Teammitglied

Registriert
13 Dez. 2014
Beiträge
4.549
Ort
Raum 43
Split, du verwendest hier let anstelle von var. wie sieht es da mit Browser Kompatibilität aus? wird das flächendeckend unterstützt? wie siehts mit älteren Browsern aus? hat das abgesehen vom Scope noch irgendeinen Vorteil gegenüber var?
 

theSplit

1998
Veteran Barkeeper

Registriert
3 Aug. 2014
Beiträge
28.573
@electric.larry: Im Grunde ist "let" das moderne "var". Und ich nutze das in erster Linie für den Scope-Effekt. Meint, alles was nicht dringend "global" gebraucht wird und zum Beispiel für den Schleifenkopf genutzt wird, zerstört werden kann, wenn es nicht mehr genutzt wird.

Was die mögliche Browserunterstützung betrifft: https://caniuse.com/let

Vorteil ist halt, wenn man "var" normal nutzt, gilt der Zähler für die gesamte Funktion/Routine. Ansonsten geht der mit "let" aus dem Scope und wird geräumt.

Ich würde "var" nur noch für Legacy Code verwenden. Zukunft ist "let" zu verwenden.

Der Code würde auch mit "var", anstelle von "let", funktionieren.
 

freekiller

NGBler

Registriert
17 Nov. 2015
Beiträge
43
Ort
Schweiz
  • Thread Starter Thread Starter
  • #13
Besten Dank für die Hilfe :)
Ja es ist korrekt ich bin noch Anfänger und versuche mich mehr und mehr mit der Materie zu befassen. Ich werde die unterschiedlichen Varianten testen. Aber ja bevor ich mich mit jquery und Underscore beschäftige werde ich die in JS verfügbare Lösung nehmen. Auch wenn ich davon ausgehe, dass underscore ähnlich wie bei jquery einfach eingebunden werden könnte.
Ihr seid die besten! Dank für die tolle Community
 

CPU

Neu angemeldet

Registriert
16 Feb. 2015
Beiträge
238
@freekiller: Also meine Lösung?

Übrigens plain JavaScript (auch VanillaJS genannt) wird in der Zukunft mehr und mehr in Mode kommen. jQuery wird immer weniger relevant.
 
Zuletzt bearbeitet:

BurnerR

Bot #0384479

Registriert
20 Juli 2013
Beiträge
5.505
Übrigens plain JavaScript (auch VanillaJS genannt) wird in der Zukunft mehr und mehr in Mode kommen. jQuery wird immer weniger benutzt.
Gibt es irgendwo einen Vergleich wie diesen hier, aber für ES6? http://youmightnotneedjquery.com/
Denke auch, dass es sich mehr und mehr lohnt, auf reines JS zu gucken... so langsam scheinen sie ja im neuen Jahrtausend anzukommen :D. Andererseits gibt es auch mittelfristig keinen ernsthaften Grund, jQuery nicht einzusetzen.

Kontext für den TE:
Reines Javascript war in diversen wichtigen Teilen äußerst grausam, unschön und der Code abhängig vom Browser. jQuery kam dann daher und hat das zu einem großen Teil verbessert, weswegen es heute extremst weit verbreitet ist. Nun sind die Jahre aber ins Land gezogen und man bemüht sich in neuen Javascript-Versionen (auch Programmiersprachen kriegen updates!) die Grausamkeiten der Vergangenheit zu verbessern, weswegen mehr und mehr Gründe für den Einsatz von jQuery über die Zeit weggefallen sind bzw. weiter wegfallen könnten.
 

freekiller

NGBler

Registriert
17 Nov. 2015
Beiträge
43
Ort
Schweiz
  • Thread Starter Thread Starter
  • #16
@CPU
Genau konnte ich tiptop verwenden.

Danke für den interessanten Hinweis.

Ein anderer Punkt an welchem ich anstehe. Ich möchte eine for Schleife erstellen um folgenden Code zu ersetzen:
[src=javascript]
let button=document.getElementById("like1");
let button1=document.getElementById("like2");
let button2=document.getElementById("like3");
let button3=document.getElementById("like4");
let button4=document.getElementById("like5");
let button5=document.getElementById("like6");
let button6=document.getElementById("like7");
let button7=document.getElementById("like8");
button.addEventListener("click", Function);
button1.addEventListener("click", Function);
button2.addEventListener("click", Function);
button3.addEventListener("click", Function);
button4.addEventListener("click", Function);
button5.addEventListener("click", Function);
button6.addEventListener("click", Function);
button7.addEventListener("click", Function);
[/src]

Nun habe ich lange recherchiert und versucht es mittels for Schleife hinzukriegen, leider funktioniert es bis anhin nicht.

In etwa so habe ich es angedacht:

[src=javascript]
for(let i = 0; i<8; i++){
let button +i = document.getElementById("like" + i);
button+i.addEventListener("click, Function");
}

// Anderer Versuch mittels Array

let array = [];
for(let i = 0; i<8; i++) {
let button = document.getElementById("like" + );
button.addEventListener("click,Function");
}
[/src]
 

BurnerR

Bot #0384479

Registriert
20 Juli 2013
Beiträge
5.505
Lies bitte ganz dringend einführende Tutorials zu Javascript, sonst wirst du mittelfristig nicht glücklich werden. Richtig ist, dass man das mit einer Schleife löst, aber ansonsten zeugen die beiden Versuche von ganz vielen ganz grundlegenden Missverständnissen darüber, wie programmieren funktioniert.
Es ist absolut nicht ausreichend, die Syntax also Klammern und Co. zu lernen und ein paar Funktionen wie "getElementById". Was dir fehlt lässt sich aber zu einem guten Teil z.b. an einem Samstag-Vormittag aufarbeiten. Einfach mal auf codeacadamy gehen und bisschen JS lernen.
 

CPU

Neu angemeldet

Registriert
16 Feb. 2015
Beiträge
238
@freekiller: Hier die Lösung https://jsfiddle.net/7ae3ysn2/

[src=html5]<button class="btn" id="like1">1
</button>
<button class="btn" id="like2">2
</button>
<button class="btn" id="like3">3
</button>
<button class="btn" id="like4">4
</button>
<button class="btn" id="like5">5
</button>
<button class="btn" id="like6">6
</button>
<button class="btn" id="like7">7
</button>[/src]

[src=javascript]var buttons = document.querySelectorAll(".btn");

for (var i = 0; i < buttons.length; i++) {
buttons.addEventListener("click", klickMich);
}

function klickMich() {
console.log("geht");
}
[/src]

Bitte beachte, dass ich zu den Buttons die Klasse "btn" hinzugefügt habe.

--- [2019-01-05 13:32 CET] Automatisch zusammengeführter Beitrag ---

Das hier solltest du dir vielleicht mal anschauen
 
Zuletzt bearbeitet:

Krutius

Verrückter

Registriert
14 Juli 2013
Beiträge
115
Also ehrlich gesagt ist die Lösung von CPU meiner Meinung nach sehr kompliziert, und nicht wirklich hilfreich was das Verständnis angeht.

Gerade um eine Lösung verständlich zu halten würde ich das Problem zerlegen.

Zunächst gehen wir mal davon aus, dass unser Array arr heisst:

[src=javascript]
const arr = [
{name: "irgendwas", email: "demo@demo.de", rating: "gut", rating2: "okay", message: "etwas text"},
{name: "irgendwas", email: "demo@demo.de", rating: "gut", rating2: "solala", message: "etwas text"},
{name: "irgendwas", email: "demo@demo.de", rating: "gut", rating2: "okay", message: "etwas text"},
{name: "irgendwas", email: "demo@demo.de", rating: "schlecht", rating2: "okay", message: "etwas text"},
{name: "irgendwas", email: "demo@demo.de", rating: "gut", rating2: "gut", message: "etwas text"},
{name: "irgendwas", email: "demo@demo.de", rating: "mittel", rating2: "okay", message: "etwas text"},
];
[/src]

Nun versuchen wir zunächst ein einfacher Problem zu lösen: Wie viele Einträge mit rating: "gut" gib es? Ein Lösungsansatz ist das hier:

[src=javascript]
const noOfRatingGood = arr.filter(elem => elem.rating === "gut").length;
[/src]

Ein Funktionaler aber dennoch einfach zu verstehender Ansatz. Wir "filtern" das array einfach so, dass wir ein neues Array erhalten, dass nur die Einträge mit rating="gut" enthält. Dann schauen wir mit .length wie lang dieses Array ist. Entsprechend so viele einträge mit dem "gut" rating gibt es.

Das rating "schlecht" geht analog. Nun können wir jedoch eine Funktion schreiben die für jeden rating-string die Anzahl an Einträgen ausgibt:

[src=javascript]
function getNoOfElementsWithRating(arr, rating) {
return arr.filter(elem => elem.rating === rating).length;
}

const noOfRatingGood = getNoOfElementsWithRating(arr, "gut");
const noOfRatingBad = getNoOfElementsWithRating(arr, "schlecht");
[/src]

Nun willst du das jedoch auch für "rating2" machen. Wir können die Funktion hierzu etwas anpassen. Wichtig zu wissen ist dabei, dass obj.key identisch ist zu obj["key"], wobei bei letzterer Version auch eine variable genutzt werden kann: obj[k] ist identisch zu obj["key"] wenn die Variable "k" den Wert "key" hat. Das erlaubt die Funktion etwas allgemeiner zu schreiben:

[src=javascript]
function getNoOfElementsWithRating(arr, field, rating) {
return arr.filter(elem => elem[field] === rating).length;
}

const noOfRatingGood = getNoOfElementsWithRating(arr, "rating", "gut");
const noOfRatingBad = getNoOfElementsWithRating(arr, "rating", "schlecht");
const noOfRating2Good = getNoOfElementsWithRating(arr, "rating2", "gut");
const noOfRating2Bad = getNoOfElementsWithRating(arr, "rating2", "schlecht");
[/src]

Wenn du nun ein Array der möglichen ratings hast:

[src=javascript]
const ratings = ["gut", "schlecht", "mittel"];
[/src]

Können wir das und "reduce" benutzen um daraus ein Objekt dieser Art zu erzeugen:

[src=javascript]
{ gut: 4, schlecht: 1, mittel: 1 }
[/src]

"reduce" ist etwas kompliziert, aber durchaus einen Blick wert, da es ein Kernkonzept der funktionalen Programmierung ist. Wir machen folgendes:

[src=javascript]
const allRatings = ratings.reduce((acum, rating) => {
acum[rating] = getNoOfElementsWithRating(arr, "rating", rating);
return acum;
}, {});
[/src]

Reduce nimmt 2 parameter: Der zweite ist ein sogenannter initialwert für den Akkumulator. Der erste Parameter ist eine Funktion, die für jeden Eintrag in dem Array ein Mal aufgerufen wird. Sie hat widerrum 2 Parameter. Der zweite ist jeweils das Element in dem Array, und der erste ist am Anfang der initialwert für den Akkumulator, und dann jeweils der Rückgabewert des vorherigen Aufrufs der Funktion. Der letzte Rückgabewert wird dann von "reduce" zurückgegeben. Man muss da vlt. mal etwas mit rumspielen, aber das lohnt sich echt!

Dank ES6 können wir das ganze auch noch etwas kürzer schreiben:

[src=javascript]
const allRatings = ratings.reduce((acum, rating) => ({...acum, [rating]: getNoOfElementsWithRating(arr, "rating", rating) }), {});
[/src]

Wir benutzen 2 features: "Computed property keys" und den "Object spread operator". Das googelt man vermutlich am besten.

Man möchte nun u.U. noch die "ratings" automatisch ermitteln. Es ist nun sehr einfach in unserem originalen array einfach nur die werte von "rating" zu extrahieren:

[src=javascript]
const ratings =arr.map(elem => elem.rating);
[/src]

nur enthält das noch Dopplungen. Also quasi das hier:

[src=javascript]
gut
gut
gut
schlecht
gut
mittel
[/src]

Dopplungen können wir nun mittels einem "Set" sehr einfach entfernen. Ein Set ist so was ähnliches wie ein Array, aber ohne Dopplungen. Wir machen also:
[src=javascript]
const ratings = new Set(arr.map(elem => elem.rating));
[/src]

Da jetzt ratings aber ein Set ist und kein array ist müssen wir das wieder in ein Array umwandeln. Hier kann ES6 spread syntax verwendet werden. Die macht in dieser Variante aus irgendwas iterierbarem ein Array:

[src=javascript]
const ratings = [...new Set(arr.map(elem => elem.rating))];
[/src]

Das alles können wir wieder zu einer Funktion zusammenfassen:

[src=javascript]
function getRatings(arr) {
return [...new Set(arr.map(elem => elem.rating))]
.reduce((acum, rating) => ({...acum, [rating]: getNoOfElementsWithRating(arr, "rating", rating) }), {});
}
[/src]

Und wir machen die wieder generisch, so dass wir sie für "rating" und "rating2" benutzen können:
[src=javascript]
function getRatings(arr, field) {
return [...new Set(arr.map(elem => elem[field]))]
.reduce((acum, rating) => ({...acum, [rating]: getNoOfElementsWithRating(arr, field, rating) }), {});
}
[/src]


Die komplette Lösung ist nun:

[src=javascript]

const arr = [
{name: "irgendwas", email: "demo@demo.de", rating: "gut", rating2: "okay", message: "etwas text"},
{name: "irgendwas", email: "demo@demo.de", rating: "gut", rating2: "solala", message: "etwas text"},
{name: "irgendwas", email: "demo@demo.de", rating: "gut", rating2: "okay", message: "etwas text"},
{name: "irgendwas", email: "demo@demo.de", rating: "schlecht", rating2: "okay", message: "etwas text"},
{name: "irgendwas", email: "demo@demo.de", rating: "gut", rating2: "gut", message: "etwas text"},
{name: "irgendwas", email: "demo@demo.de", rating: "mittel", rating2: "okay", message: "etwas text"},
];

function getRatings(arr, field) {
return [...new Set(arr.map(elem => elem[field]))]
.reduce((acum, rating) => ({...acum, [rating]: getNoOfElementsWithRating(arr, field, rating) }), {});
}

function getNoOfElementsWithRating(arr, field, rating) {
return arr.filter(elem => elem[field] === rating).length;
}

const rating = getRatings(arr, "rating");
const rating2 = getRatings(arr, "rating2");
[/src]

Kurz noch ein Wort zu var, let und const:

Ich würde immer const benutzen wenn es geht! Man hat die Garantie, dass der Wert nicht "ausversehen" überschrieben wird. Will man das benutzt man let. Dadurch ist das immer explizit.
Wenn wirklich ein Browser verwendet werden soll der kein let/const hat benutzt babel! Der code ist mit let/const um vieles leserlicher und sicherer!
 
Zuletzt bearbeitet:

CPU

Neu angemeldet

Registriert
16 Feb. 2015
Beiträge
238
@Krutius: Dein Code ist übrigens fehlerhaft, hab mir gerade die Konstanten rating und rating2 ausgeben lassen, da kommt was Merkwürdiges raus. (siehe hier)

@freekiller: Ist das was Krutius hier geschrieben hat verständlicher als das was ich dir geliefert habe? Bitte ehrlich antworten.
 
Zuletzt bearbeitet:
Oben