Um was geht es (ich hoffe, ich bringe das verständlich rüber):
Mein Rechentrainer vergibt jetzt auch Noten (bisher fast nur schlechte). Die Kids müssen in jeder Woche eine bestimmte Anzahl Aufgaben machen und das in allen Kategorien die sie schon können müssten (zur Zeit sind das 25). Die Note wird bestimmt aus dem Prozentsatz wieviel der geforderten Aufgaben pro Kategorie erledigt wurden und von diesem werden dann noch Fehler abgezogen und auserdem auch noch die Klicks wenn Aufgaben weggeklickt werden und auch wenn die Kids die Lösung der Aufgabe anzeigen lassen. Da es sehr frustrierend ist, hier endlos Fehler anzusammeln, wird der Fehlerzähler nach einer festgelegten Anzahl von Aufgaben, die an einem Stück richtig gerechnet wurden, gelöscht. Da ist mir wieder nichts besseres eingefallen, als die Fehler und Abbrüche und Lösungen doppelt zu zählen. Zu jeder Kategorie gibt es für jeden Nutzer einen Eintrag in einer Datenbank "Zähler". Dort zähle ich die Fehler und lösche sie dann auch. Diese Fehler stehen aber auch in der Datenbank "Protokoll" und ihr habt mich schon mal hingewiesen, dass das Quatsch ist (ich konnte es aber mal wieder nicht besser). Den Pfusch möchte ich jetzt beseitigen (das funktioniert eh nicht über die verschiedenen Halbjahre).
Also das ist meine Idee:
Für jede Aufgabe wird ein Eintrag in "Protokoll" erzeugt. Dort wird auch jeweils gespeichert, ob die Antwort richtig oder falsch war und ob "Abbrechen" oder "Lösung" angeklickt wurde. Ich möchte jetzt in der Tabele "Zähler" anstelle der Fehlerzähler ein Feld mit einem Datum erzeugen und dort für die entsprechende Kategorie festhalten, zu welchem Zeitpunkt der Fehlerzähler gelöscht wurde und dann im Protokoll nur noch die Fehler addieren, die danach gemacht wurden.
Zunächst mal muss ich ein Feld für den Zeitpunkt definieren und diesem wollte ich als default zunächst mal den Beginn des Halbjahres übergeben. Wäre da
Code: Alles auswählen
fehler_ab = models.DateTimeField(default=datetime(2023, 8, 1, 0, 0, 0, 0))
Aber zur Ursprungsfrage: Wie bekomme ich die Summe der Fehler seit dem gespeicherten Datum? Soll ich da ein Filter benutzen? Irgendjemand hat hier mal gesagt, dass man diese Berechnung auch direkt in der Datenbank vornehmen kann.
Ich will euch auch hier nicht das neue Jahr verderben, indem ich den ganzen Code hier hochlade - hoffentlich reicht auch das:
Code: Alles auswählen
def uebersicht(req, schueler_id=0):
...
protokoll = Protokoll.objects.filter(user=user, sj=user.sj, hj=user.hj) # alle Aufgaben des Users aus diesem Schulhalbjahr
..
kategorien = Kategorie.objects.all().order_by('zeile') # alle Aufgabenkategorien
...
sj = user.sj
hj = user.hj
...
for kategorie in kategorien:
...
protokoll_kategorie = protokoll.filter(kategorie = kategorie)
if protokoll_kategorie.count() > 0: # es sind Aufgaben da
zaehler_kategorie = Zaehler.objects.get(user=user, kategorie = kategorie) # die Kategorie wurde schon bearbeitet
kategorie_werte = ( # die Summen der einzelnen Kategoren des jeweiligen Users
protokoll_kategorie
.values("kategorie__zeile")
.annotate(richtig_sum=Sum('richtig'))
.annotate(zeit_sum=Sum(F('end') - F('start')))
)
for k in kategorie_werte:
richtig_kat = k['richtig_sum']
zeit_kat = k['zeit_sum']
und das ist dann der Code, mit dem ich zurzeit die diversen Fehler zähle und das möchte ich ändern:
Code: Alles auswählen
falsch_kat = zaehler_kategorie.fehler_zaehler
abbr_kat = zaehler_kategorie.abbr_zaehler
lsg_kat = zaehler_kategorie.lsg_zaehler
hilfe_kat = zaehler_kategorie.hilfe_zaehler
Code: Alles auswählen
class Protokoll(models.Model):
user = models.ForeignKey(Profil, verbose_name='Benutzer', related_name='protokolle', on_delete=models.CASCADE)
#gewertet werden nur die Aufgaben des jeweiligen Schuljabjahres, im Januar, Juni und August, kann der user aber auch schon festlegen, dass die Aufgaben für das nächste Schulhalbjahr gelten:
sj = models.SmallIntegerField(default=0)
hj = models.SmallIntegerField(default=0)
kategorie = models.ForeignKey(Kategorie, related_name='protokolle', on_delete=models.CASCADE)
...
aufgnr = models.PositiveSmallIntegerField(default=0)
#der Aufgabentext:
text = models.TextField(blank=True)
...
#hier speichere ich die Lösung, wahlweise als zahl, u.U. auch (mehrere) Lösungen als String:
wert = models.DecimalField('Wert', null=True, max_digits=20, decimal_places=7)
loesung = models.JSONField() #hier können mehrere Werte eingegeben werden, der erste wird angezeigt wenn "Lösung anzeigen" angeklickt wird. Steht hier auch "indiv" so wird die Eingabe in der jeweiligen Funktion überprüft
...
#die Eingabe des users:
eingabe = models.CharField(max_length=20, blank=True)
versuche = models.PositiveSmallIntegerField('Versuche', default=0)
#Eintrag richtig, falsch, Extrapunkte, Lösung anzeigen, Abbruch:
wertung = models.CharField(max_length=10, blank=True)
richtig = models.DecimalField(max_digits=3, decimal_places=1, default=0)
falsch = models.PositiveSmallIntegerField(default=0)
abbr = models.BooleanField(default=True)
lsg = models.BooleanField(default=False)
hilfe = models.BooleanField(default=False)
start = models.DateTimeField('Start', auto_now_add=True)
end = models.DateTimeField('Ende', blank=True, null=True, default=None)