Seit einiger Zeit findet man die erste Version der Plagiat-Tests in unserer Anwendung (zu finden unter Administration -> Plagiat-Tests
Struktur
Grundsätzlich besteht ein Test immer aus den beiden Clients die gegeneinander getestet werden sollen. Man kann außerdem sog. Fake-Checks definieren, dies sind die eigentlichen Testverfahren mit denen man die Tests gegeneinander testen möchte.
Beispiele für Checks sind:
- Checksum-Check: Hier wird ein Hash der beiden Clients erzeugt und abgeglichen. Wenn die Hashes identisch sind, dann kann mit an Sicherheit grenzender Wahrscheinlichkeit gesagt werden, dass die Clients absolut identisch sind. Dieser Test ist sehr schnell und kann generell immer durchgeführt werden (Achtung: Clients der gleichen Schule könnten identisch sein, aber auch der SimpleClient wäre immer gleich). Wenn in den Archiven aber auch nur 1 Bit geändert wurde, dann ist der Test nicht tiefgehend genug. (konstanter Aufwand)
- Diff-Check: Hier werden die Archive rekursiv entpackt und dabei Class Dateien decompiliert. (es werden scheinbar unwichtige Dateien dabei ignoriert) Danach werden die Dateiinhalte der übrigen Dateien der beiden Clients verglichen um herauszufinden wie hoch die Identität ist. Dieser Test ist sehr tiefgehend und findet auch Vertuschungsversuche, jedoch können die Logs auf Grund der Größe nur temporär gespeichert werden, außerdem kann der Test zum jetzigen Zeitpunkt nur einzeln durchgeführt werden weil er sehr lange dauert (quadratischer Aufwand)!
- MetaData-Check (TODO): Identitäen beim den Erstellungs- und Modifizierungsdaten und ähnliches können auch gute Hinweise geben ob es sich um Plagiate handelt, diese Meta-Daten kann man recht leicht extrahieren. Auch der Vergleich ist, da die Datenmenge nicht so hoch ist tragbar. Ebenso ist die bei flächendeckender Nutzung nur linearer Aufwand nötig.
- Behavior-Check (TODO): Dieser Check testet die Clients gegen spezielle Beispielsituationen und deterministische Gegner, das Verhalten der Clients wird geloggt. Wenn sich Clients sehr änhlich verhalten kann das auch zeigen, dass dort kopiert wurde. Dieser Test ist abhängig von der Menge und Qualität an Testsituationen kann aber vermutlich sehr gut Plagiate ausfindig machen, es gibt jedoch auch ein Potential für false-positives! (linearer Aufwand)
- ReplaceCompare-Check (TODO): Hier werden die Clients ebenfalls entpackt und dekompiliert, nur werden hier alle Konstrukte der Programmiersprache entfernt, sodass nur noch Namen der Variablen usw. stehen bleiben. Nun ersetzt man nach einem festen Schema die Namen durch Tokens. Ein Vergleich der Aneinanderreihungen von Tokens der Clients kann sehr viel Aufschluss darüber geben wie identisch die Stuktur usw. der Clients sind. Es handelt sich um Standard-Prinzip der Plagiaterkennung, das komplizierter als der Diff-Check umzusetzen ist, jedoch kann evtl. die Präzision erhöht und der Aufwand bei der Anwendung etwas reduziert werden. (quadratischer Aufwand, wenn man von gleicher Reihenfolge ausgeht)
Aussagefähigkeit
Die Tests geben nur Indizien dafür ob kopiert wurde, jedoch kann das quasi nie zu 100% garantiert oder ausgeschlossen werden. Sie dienen aber letztlich dazu um einen Überblick über die Clients und deren Ähnlichkeit zu erhalten und möglichst zu erkennen ob sich in der Masse der Teams schwarze Schafe befinden, was besonders in Zukunft wichtig werden kann.
Implementierung neuer Checks
Es gibt das FakeCheck Model welches die Basis für einen FakeCheck darstellt. Alle FakeChecks haben eine polymorphic Beziehung zu dieser Klasse und entsprechend auch die gleichen Attribute. Wenn man einen neuen Check implementiert, so erstellt man im fake_checks Ordner eine neue Klasse die von FakeCheck ableitet. In dieser Klasse implementiert man die perform Methode in welcher man den Check durchführt. Die Resultate werden dann als FakeCheckFragment der fragments Collection hinzugefuegt. Ein solches Segment besteht aus 3 Strings: name, value, description. Nach Wunsch muss noch das Form zum Erstellen eines FakeTest so angepasst werden, dass man auch den entsprechenden Check auswählen kann. Theoretisch ist damit der Check implementiert. Falls man sich aber eine individuelle Darstellung und nicht nur eine Tabelle wünscht, kann man in /views/fake_tests/ ein Partial mit dem Namen "display< ClassNameInUnderscoreSchreibweise >.erb" erstellen, welches dann automatisch für den entsprechenen Check gerendert wird. Möchte man die Kompatiblität eines Checks auf bestimmte Spiele beschränken, so definiert man in dem Check nur die Methode compatible_games und lässt sie ein Array der GameIdentifier zurückgeben, z.B. [:HaseUndIgel].
Anpassung an neue Spiele
Bisher ist noch kein Abhängigkeit vom jeweiligen Spiel gegeben. Wenn jedoch später weitere Checks implementiert werden, muss dies bedacht werden und es ist evtl. eine Anpassung notwendig! Solange in einem Check nicht ausdrücklich definiert ist ob er nur für bestimmte Spiele kompatibel ist, so wird er generell als kompatibel angesehen! Ob ein Check mit einem Contest und dem zu ihm gehörenen Spiel kompatibel ist, kann mit Check.compatible_with_contest?() überprüft werden!
Ignore Listen
Es sollte in Zukunft die Möglichkeit geben z.B. die Dateien des SimpleClient hochzuladen und diese dann bei den späteren Tests zu ignorieren usw. Dafür wäre es evtl nicht schlecht wenn man die Funktion integriert, dass man ein *.zip im Admin-Interface hochladen kann, dies dann entpackt und von allen Dateien Name und Hash in die DB geschrieben wird. Das muss evtl für jeden Wettkampf getan werden kann aber auch vom Spiel o.ä. abhängig sein.