Der Partyfinanzausgleich

Eine Feier und jede(r) bringt etwas mit. Später sollen die Kosten geteilt werden und schon geht die Rechnerei los: Betrag x von a an b, Betrag y von b an c, Betrag z von c nach a. Allerdings sind a zwei Personen, haben für ebenso viele Personen gegessen und es wäre sinnlos, zweimal Geld zu überweisen.

Klar, kann man das einfach und klassisch mit Bleistift und Papier machen, aber warum nicht einfach den großen Taschenrechner arbeiten lassen? Also kurz ein Javascript zusammengetippt, das die Aufgabe übernimmt:

var teilnehmer = [
    {"name" : "Mila/Adam", "ausgaben" : 30, "esser" : 2},
    {"name" : "Emilia/Noah", "ausgaben" : 20, "esser" : 2},
    {"name" : "Leni/Felix", "ausgaben" : 35, "esser" : 2},
    {"name" : "Mira/Leon/Sophia", "ausgaben" : 10, "esser" : 3},
    {"name" : "Emil", "ausgaben" : 5, "esser" : 1 },
]

var transfer = [];
teilnehmer = teilnehmer.sort((a, b) => a.ausgaben - b.ausgaben);
var ausgaben = teilnehmer.reduce((prev, curr) => prev += curr.ausgaben, 0);
var ausgabenpp = ausgaben / teilnehmer.reduce((prev, curr) => prev += curr.esser, 0);

console.log("Ausgaben Insgesamt:", ausgaben, "Euro, pro Esser:", ausgabenpp)
teilnehmer.forEach(p => p.ausgaben -= ausgabenpp * p.esser)
teilnehmer.forEach(p1 => {
    if(p1.ausgaben < 0)
    {
        var p2 = teilnehmer.find(a => a.ausgaben > 0);
        if(p2 != undefined)
        {
            transfer.push(Math.round(-p1.ausgaben * 100) / 100 + " Euro von " + p1.name + " an " + p2.name);
            p2.ausgaben += p1.ausgaben;
            p1.ausgaben = 0;
        }
    }
});

console.log("Überweisungen:", transfer);
console.log("Betrag nicht ausgeglichen für:", teilnehmer.filter(p => p.ausgaben != 0));

Oben kommen die Teilnehmer, Ausgaben und die „esser“ rein, es purzeln die Beträge, die Transaktionen und was übrig geblieben ist (was bis bis auf Rundungsfehler leer bleiben sollte) heraus:

Ausgaben Insgesamt: 100 Euro, pro Esser: 10
Überweisungen: [
  '5 Euro von Emil an Mila/Adam',
  '20 Euro von Mira/Leon/Sophia an Mila/Adam',
  '15 Euro von Mila/Adam an Leni/Felix'
]
Betrag nicht ausgeglichen für: []

Kann man sicher eleganter lösen, aber: ?‍♂️

Tarnkappen-Links enttarnen

Heise hat „Breaking News“ parat: über Javascript-Events kann man Hyperlinks andere Adressen unterschieben. Das ist nicht neu, macht Google schon seit Jahren.

Dabei wird über das onclick- oder onmousedown-Event einfach das href-Attribut des a-Elements verändert. So ziemlich alle Browser führen den Eventhandler vor dem Öffnen des Links aus. So weit, so schlecht.

Nun kann man entweder Javascript deaktivieren (und viele Seiten kaputt machen) oder einen „faulen“ Trick anwenden, der zumindest bei onmousedown funktioniert:

Mit der rechten Maustaste darauf fahren und in die Statusleiste gucken, dann die rechte Maustaste drücken, das Menü schließen, wieder auf den Link fahren und gucken, ob sich der Text in der Statuszeile verändert hat. Funktioniert genauso, wenn man den Link per Drag & Drop anfängt zu ziehen, dies aber abbricht.

Wäre da noch das onclick-Event. Das kann man als Benutzer so einfach nicht ermitteln. Auch die Durchsicht des Quelltextes hilft nicht, da das Attribut samt Miniscript nicht direkt im Element stehen muss (siehe das Beispiel auf heise.de).

Da muss man Feuer mit Feuer bekämpfen. Ich habe dazu ein kleines Bookmarklet geschrieben, das alle Links im Dokument auf onclick- und onmousedown-Events durchsucht und im Falle dessen hinter dem Linktext ein kleines Ausrufezeichen einblendet.

Nach dem „Installieren“ kann es sogleich getestet werden, da meine Bookmarklet-Seite das Onclick-Event verwendet.

tarnkappen-links

So schaut’s aus

Allerdings sei dazu gesagt, dass Hyperlinks mit hinterlegten Events nicht per se nicht „böse“ sind, sondern auf manchen Seiten (wie hier im Wiki bei den Miniaturansichten von Bildern) eine Zusatzfunktion anbieten.

Happy Clicking!