/
SchuelerNoten.cs
829 lines (733 loc) · 29 KB
/
SchuelerNoten.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
using diNo.diNoDataSetTableAdapters;
using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
namespace diNo
{
/// <summary>
/// Verwaltet alle Noten eines Schülers
/// </summary>
public class SchuelerNoten
{
private Schueler schueler;
public List<FachSchuelerNoten> alleKurse; // enthält nur die aktuell besuchten Kurse
public List<FachSchuelerNoten> alleFaecher; // enthält alle Fächer, die der S jemals belegt hat
public List<FachSchuelerNoten> alleSprachen; // für die Fremdsprachenliste
public List<FachSchuelerNoten> FaecherOhneKurse; // enthält alle Fächer, die der S aus vorigen JgStufen mitbringt
// die folgendes Array verwaltet die Anzahl der Einser, Zweier, usw., getrennt nach SAP-Fach und Nebenfach
// anzahlNoten[6,1] ergibt z.B. die Anzahl der Sechser in SAP-Fächern, anzahlNoten[5,0] die Anzahl der Fünfer in Nebenfächern
private int[,] anzahlNoten;
private int abi5er = 0, abi6er = 0, abiE = 0; // Anzahl 5er und 6 im Abi, Abi-Note in Englisch
private Zeitpunkt zeitpunkt = (Zeitpunkt)Zugriff.Instance.aktZeitpunkt;
public string Unterpunktungen, UnterpunktungenAbi;
public int anz4P = 0;
public double Punkteschnitt = 0;
public List<HjLeistung> Fachreferat = new List<HjLeistung>(); // sollte i.d.R. nur einelementig sein, aber wegen irrtümlicher Doppelvergabe
public FachSchuelerNoten ZweiteFSalt = null; // Verweis auf die beiden HjLeistungen in der 2. Fremdsprache (kann auch Kurs aus der 12. enthalten oder 13., die wiederholt wurde)
public HjLeistung AlternatZweiteFS = null; // Verweis auf die schlechtere Leistung in der 2. Fremdsprache in der 13. Klasse (nur befüllt bei aktuellem Kurs in 13)
public HjLeistung AlternatEinbr = null; // Verweis auf eine alternativ einzubringende HjLeistung (fachgeb. HSR)
public SchuelerNoten(Schueler s)
{
schueler = s;
alleFaecher = new List<FachSchuelerNoten>();
alleKurse = new List<FachSchuelerNoten>();
alleSprachen = new List<FachSchuelerNoten>();
FaecherOhneKurse = new List<FachSchuelerNoten>();
foreach (var kurs in schueler.Kurse)
{
var fsn = new FachSchuelerNoten(schueler, kurs.Id, this);
alleFaecher.Add(fsn);
alleKurse.Add(fsn);
AddSprache(fsn);
}
// alle Fächer des Schülers ohne Kurs finden und diese HjLeistungen laden
diNoDataSet.FachDataTable fDT = (new FachTableAdapter()).GetFaecherOhneKurseBySchuelerId(schueler.Id, (int)schueler.getKlasse.Jahrgangsstufe);
foreach (var fachR in fDT)
{
Fach fach = Zugriff.Instance.FachRep.Find(fachR.Id);
var fsn = new FachSchuelerNoten(schueler, fach, this);
if (fach.getKursniveau() > Kursniveau.None)
{ // abgelegte 2. FS --> nicht in die normale Liste aufnehmen, da außerhalb der Noten- und Einbringungsprüfung
alleSprachen.Add(fsn);
if (s.Data.AndereFremdspr2Art != (int)ZweiteFSArt.ErgPr && fsn.getHjLeistung(HjArt.Hj1) != null && fsn.getHjLeistung(HjArt.Hj2) != null)
ZweiteFSalt = fsn;
}
else
{
alleFaecher.Add(fsn);
FaecherOhneKurse.Add(fsn);
}
}
// Fachreferat als eigenes Fach führen --> macht leider auch viele Probleme, deshalb erst mal so lassen
// (Sollte es mehrere FR geben, bleibt aber nur das letzte übrig, weil alle in denselben Index geschrieben werden).
/*
if (schueler.Fachreferat.Count>0)
{
alleFaecher.Add(new FachSchuelerNoten(schueler, schueler.Fachreferat));
}
*/
Zweig z = schueler.Zweig; // Profilfächer haben neue Sortierung
alleFaecher.Sort((x, y) => x.getFach.Sortierung(z).CompareTo(y.getFach.Sortierung(z)));
alleKurse.Sort((x, y) => x.getFach.Sortierung(z).CompareTo(y.getFach.Sortierung(z)));
// Schnitt, Unterpunktungen etc. berechnen
anzahlNoten = new int[7, 2];
InitAnzahlNoten();
InitAlternatEinbr();
if (AlternatZweiteFS != null && AlternatEinbr == null)
AlternatZweiteFS = null; // wenn keine alternative Einbringung existiert (weil es nicht besser wird), gibt es auch keine Alternative 2.FS-Einbringung
}
// prüft, ob bei aktiven Kursen eine alternative Einbringung für die fachgeb. HSR günstiger ist
private void AddSprache(FachSchuelerNoten fsn)
{
Kursniveau k = fsn.getFach.getKursniveau();
if (k != Kursniveau.None) alleSprachen.Add(fsn);
if (k > Kursniveau.Englisch)
{
var hj1 = fsn.getHjLeistung(HjArt.Hj1);
var hj2 = fsn.getHjLeistung(HjArt.Hj2);
if (hj1 != null && hj2 != null)
{
AlternatZweiteFS = (hj1.Punkte < hj2.Punkte) ? hj1 : hj2;
}
}
}
// sucht ggf. alternativ eingebrachte HjLeistung
private void InitAlternatEinbr()
{
if (schueler.getKlasse.Jahrgangsstufe < Jahrgangsstufe.Dreizehn || AlternatZweiteFS == null) return;
foreach (var f in alleFaecher)
{
foreach (HjArt hjArt in new[] { HjArt.Hj1, HjArt.Hj2 })
{
HjLeistung hj;
hj = f.getHjLeistung(hjArt);
if (hj != null && hj.Status == HjStatus.AlternativeEinbr)
{
AlternatEinbr = hj;
return;
}
}
}
}
public FachSchuelerNoten getFach(int kursid)
{
foreach (FachSchuelerNoten f in alleFaecher)
{
if (f.kursId == kursid) return f;
}
return null;
//throw new IndexOutOfRangeException("FachSchuelerNoten.getFach: falsche kursid");
}
/// <summary>
/// Liefert die Noten des Schülers im übergebenen Fach.
/// </summary>
/// <param name="fachKuerzel">Das Fachkürzel.</param>
/// <returns>Die FachNoten oder null, wenn der Schüler das fach nicht belegt.</returns>
public FachSchuelerNoten FindeFach(string fachKuerzel)
{
foreach (FachSchuelerNoten f in alleFaecher)
{
if (f.getFach.Kuerzel.Equals(fachKuerzel, StringComparison.OrdinalIgnoreCase)) return f;
}
return null;
}
public FachSchuelerNoten FindeFach(int fachId)
{
foreach (FachSchuelerNoten f in alleFaecher)
{
if (f.getFach.Id == fachId) return f;
}
return null;
}
/// <summary>
/// Liefert die Sportnoten des Schülers
/// </summary>
/// <returns>Die FachNoten oder null, wenn der Schüler das fach nicht belegt.</returns>
public FachSchuelerNoten FindeSportnote()
{
foreach (FachSchuelerNoten f in alleFaecher)
{
if (f.getFach.BezZeugnis.StartsWith("Sport", StringComparison.OrdinalIgnoreCase)) return f;
}
return null;
}
/// <summary>
/// Liefert eine Liste in der je Fach alle Noten in druckbarer Form vorliegen.
/// </summary>
public IList<NotenDruck> SchuelerNotenDruck(Bericht rptName)
{
IList<NotenDruck> liste = new List<NotenDruck>();
foreach (FachSchuelerNoten f in alleFaecher)
{
liste.Add(NotenDruck.CreateNotenDruck(f, rptName));
}
foreach (var f in Fachreferat)
{
if (rptName == Bericht.Abiergebnisse)
liste.Add(new NotenAbiDruck(f));
else
liste.Add(new NotenHjDruck(f));
}
if (schueler.getKlasse.Jahrgangsstufe == Jahrgangsstufe.Dreizehn)
{
if (rptName == Bericht.Abiergebnisse)
liste.Add(new NotenAbiDruck(schueler.Seminarfachnote));
else
liste.Add(new NotenHjDruck(schueler.Seminarfachnote));
}
return liste;
}
public IList<NotenDruck> SchuelerNotenZeugnisDruck(Bericht rptName)
{
IList<NotenDruck> liste = new List<NotenDruck>();
if (rptName == Bericht.Abiturzeugnis)
{
foreach (FachSchuelerNoten f in alleFaecher)
{
liste.Add(new NotenZeugnisDruck(f, rptName));
}
}
else
foreach (FachSchuelerNoten f in alleKurse)
{
if (rptName != Bericht.Gefaehrdung || f.getRelevanteNote(zeitpunkt) <= 4)
liste.Add(new NotenZeugnisDruck(f, rptName));
}
foreach (var f in Fachreferat)
{
liste.Add(new NotenZeugnisDruck(f, "Fachreferat in " + f.getFach.BezZeugnis));
}
if (rptName != Bericht.Gefaehrdung && schueler.getKlasse.Jahrgangsstufe == Jahrgangsstufe.Elf)
{
NotenZeugnisDruck f = new NotenZeugnisDruck(schueler.FPANoten);
liste.Add(f);
}
if (schueler.getKlasse.Jahrgangsstufe == Jahrgangsstufe.Dreizehn &&
rptName != Bericht.Gefaehrdung && rptName != Bericht.Bescheinigung && rptName != Bericht.Zwischenzeugnis) // kommt sonst sinnlos bei Gefährdungen und ZZ)
{
liste.Add(new NotenZeugnisDruck(schueler.Seminarfachnote));
}
return liste;
}
// Zu diesem Zeitpunkt werden die Notenanzahlen gebildet,
// wird dieser geändert, muss neu gerechnet werden
public void SetZeitpunkt(Zeitpunkt z)
{
if (zeitpunkt != z)
{
anzahlNoten = null;
anzahlNoten = new int[7, 2];
zeitpunkt = z;
InitAnzahlNoten();
}
}
public int AnzahlProbleme()
{
return AnzahlNoten(5) + 2 * AnzahlNoten(6);
}
// liefert Anzahl der Sechser, Fünfer, ..., egal ob Prüfungsfach oder nicht
public int AnzahlNoten(int note)
{
return AnzahlNoten(note, true) + AnzahlNoten(note, false);
}
// Doku s. private Variable
public int AnzahlNoten(int note, bool SAP)
{
if (SAP) return anzahlNoten[note, 1];
else return anzahlNoten[note, 0];
}
private void NimmNote(byte relevanteNote, int istSAP, string kuerzel)
{
if (relevanteNote == 0) anzahlNoten[6, istSAP]++;
else if (relevanteNote < 4) anzahlNoten[5, istSAP]++;
else if (relevanteNote >= 13) anzahlNoten[1, istSAP]++;
else if (relevanteNote >= 10) anzahlNoten[2, istSAP]++;
else if (relevanteNote >= 7) anzahlNoten[3, istSAP]++;
else anzahlNoten[4, istSAP]++;
if (relevanteNote == 4) anz4P++; // nur 4P für Gefährdungsmitteilung
if (relevanteNote < 4 || relevanteNote == 4 && zeitpunkt == Zeitpunkt.HalbjahrUndProbezeitFOS)
Unterpunktungen += kuerzel + "(" + relevanteNote + ") ";
}
private void InitAnzahlNoten()
{
string kuerzel;
int Punktesumme = 0;
int AnzahlFaecher = 0;
Unterpunktungen = "";
UnterpunktungenAbi = "";
List<FachSchuelerNoten> zuAnalysierendeNoten; // zum Abi werden alle Fächer betrachtet
zuAnalysierendeNoten = (zeitpunkt >= Zeitpunkt.ErstePA && zeitpunkt <= Zeitpunkt.DrittePA ? alleFaecher : alleKurse);
foreach (var fachNoten in zuAnalysierendeNoten)
{
kuerzel = fachNoten.getFach.Kuerzel;
if (fachNoten.getFach.NichtNC) continue; // Nicht-NC-Fächer zählen gar nicht
byte? relevanteNote = fachNoten.getRelevanteNote(zeitpunkt);
int istSAP = fachNoten.getFach.IstSAPFach(schueler.Zweig, schueler.getKlasse.Jahrgangsstufe <= Jahrgangsstufe.Vorklasse) ? 1 : 0;
if (relevanteNote != null)
{
Punktesumme += relevanteNote.GetValueOrDefault();
AnzahlFaecher++;
NimmNote(relevanteNote.GetValueOrDefault(), istSAP, kuerzel);
}
if (istSAP == 1 && (zeitpunkt == Zeitpunkt.ZweitePA || zeitpunkt == Zeitpunkt.DrittePA))
{
InitAbiNoten(fachNoten);
}
}
foreach (var f in Fachreferat)
{
NimmNote(f.Punkte, 0, "FR");
}
if (!schueler.Seminarfachnote.IsGesamtnoteNull())
{
byte relevanteNote = (byte)schueler.Seminarfachnote.Gesamtnote;
Punktesumme += relevanteNote;
AnzahlFaecher++;
NimmNote(relevanteNote, 0, "Sem");
}
// Punkteschnitt berechnen
if (zeitpunkt >= Zeitpunkt.ErstePA && zeitpunkt <= Zeitpunkt.DrittePA)
{
Punktesumme = schueler.punktesumme.Summe(PunktesummeArt.Gesamt);
AnzahlFaecher = schueler.punktesumme.Anzahl(PunktesummeArt.Gesamt);
}
if (AnzahlFaecher > 0)
{
Punkteschnitt = Math.Round((double)Punktesumme / AnzahlFaecher, 2, MidpointRounding.AwayFromZero);
if (Unterpunktungen != "" && zeitpunkt!=Zeitpunkt.ErstePA && !(zeitpunkt == Zeitpunkt.Jahresende && schueler.getKlasse.Jahrgangsstufe <= Jahrgangsstufe.Vorklasse))
{
Unterpunktungen += " Schnitt: " + String.Format("{0:0.00}", Punkteschnitt);
if (zeitpunkt == Zeitpunkt.ZweitePA || zeitpunkt == Zeitpunkt.DrittePA)
Unterpunktungen += "; " + Punktesumme + " P.";
}
}
}
private void InitAbiNoten(FachSchuelerNoten f)
{
HjLeistung hj = f.getHjLeistung(HjArt.AP);
if (hj == null) return;
byte apg = hj.Punkte;
if (f.getFach.Kuerzel == "E") abiE = apg;
if (apg < 4)
{
UnterpunktungenAbi += f.getFach.Kuerzel + "-Abi(" + apg + ") ";
if (apg == 0) abi6er++; else abi5er++;
}
}
public bool HatAbiNichtBestanden()
{
if (schueler.getKlasse.Jahrgangsstufe == Jahrgangsstufe.Dreizehn)
return (abi6er > 0 || abi5er > 2);
else
return (2 * abi6er + abi5er > 2);
}
// kann nicht mal mehr das Abi bestehen, weil zu viele 0er da sind
// 2 Noten können durch MAP bereinigt werden.
public bool WegenAbiNichtZurMAPZugelassen()
{
int nachMAP6er = abi6er;
int nachMAP5er = abi5er;
for (byte i = 0; i < 2; i++) // zwei MAP möglich
{
if (abiE == 0 && nachMAP6er > 1) nachMAP6er--;
else if (nachMAP6er > 0) nachMAP6er--;
else if (nachMAP5er > 0) nachMAP5er--;
}
if (schueler.getKlasse.Jahrgangsstufe == Jahrgangsstufe.Dreizehn)
return (nachMAP6er > 0 || nachMAP5er > 2);
else
return (2 * nachMAP6er + nachMAP5er > 2);
}
public bool HatNichtBestanden()
{
// Achtung: Vorklasse hat am Jahresende eine besondere Bestanden-Regelung
if (zeitpunkt == Zeitpunkt.Jahresende && schueler.getKlasse.Jahrgangsstufe <= Jahrgangsstufe.Vorklasse)
{
if (AnzahlNoten(6) == 0 && AnzahlNoten(5) == 0) return false; // bestanden
if (AnzahlNoten(6) > 0 || AnzahlNoten(5) > 1) return true; // da geht nichts mehr
if (AnzahlNoten(5, true) > 0) // eine 5 in D,E oder M kann nur dadurch ausgeglichen werden
return !(AnzahlNoten(1, true) + AnzahlNoten(2, true) > 0 || AnzahlNoten(3, true) > 1);
else
return !(AnzahlNoten(1) + AnzahlNoten(2) > 0 || AnzahlNoten(3) > 1);
}
else
return !(AnzahlNoten(6) == 0 && AnzahlNoten(5) == 0 ||
AnzahlNoten(6) == 0 && AnzahlNoten(5) == 1 && Punkteschnitt >= 5 ||
(AnzahlNoten(6) * 2 + AnzahlNoten(5)) == 2 && Punkteschnitt >= 6);
}
public bool HatIn12KeinePZ()
{ // überall mindestens eine 3
return AnzahlNoten(6) == 0 && AnzahlNoten(5) == 0 && AnzahlNoten(4) == 0;
}
public bool MAPmoeglich()
{
GEVariante[] gev = new GEVariante[3]; // aus 3 Fächern kann die MAP ausgewählt werden
byte index = 0;
foreach (var f in alleKurse)
{
string kuerzel = f.getFach.Kuerzel;
HjLeistung hj = f.getHjLeistung(HjArt.GesErg);
if (hj == null) continue; // sollte natürlich nicht passieren!
// nur in Abifächern außer E kann man MAP machen
if (f.getFach.IstSAPFach(schueler.Zweig) && kuerzel != "E")
{
int? sap = f.getNote(Halbjahr.Zweites, Notentyp.APSchriftlich);
if (sap == null && f.getHjLeistung(HjArt.AP) != null) sap = f.getHjLeistung(HjArt.AP).Punkte; // für Testzwecke Meldung über Notenanzahlchecker
gev[index] = new GEVariante();
Fachsumme fs = f.SummeHalbjahre();
gev[index].AP = Notentools.BerechneAbiGes(sap.GetValueOrDefault(), 15); // AP-Gesamtergebnis bei MAP=15
fs.Add(gev[index].AP, schueler.APFaktor);
gev[index].GE = fs.GesErg(); //GE in diesem Fach, wenn optimaler MAP
gev[index].CalcDiff(sap.GetValueOrDefault(), hj.Punkte, schueler.APFaktor); // berechnen, wie sich die Gesamtsumme dadurch verbessert
index++;
}
}
if (index != 3) throw new Exception(schueler.benutzterVorname + " kann nicht aus 3 Fächern die MAP auswählen.");
return CheckVariante(gev[0], gev[1]) || CheckVariante(gev[0], gev[2]) || CheckVariante(gev[1], gev[2]);
}
// ergibt true, wenn er bei dieser Variante besteht
private bool CheckVariante(GEVariante v1, GEVariante v2)
{
Punktesumme ps = schueler.punktesumme;
int probl = AnzahlProbleme() + v1.ProblemDiff + v2.ProblemDiff; // ProblemDiff ist idR negativ
int sum = ps.Summe(PunktesummeArt.Gesamt) + v1.PunkteDiff + v2.PunkteDiff;
bool erg = (probl <= 0 ||
probl == 1 && sum >= 5 * ps.Anzahl(PunktesummeArt.Gesamt) ||
probl == 2 && sum >= 6 * ps.Anzahl(PunktesummeArt.Gesamt));
return erg;
}
public bool DarfInBOS13()
{
if (schueler.Data.Schulart != "B" || schueler.getKlasse.Jahrgangsstufe != Jahrgangsstufe.Zwoelf) return false;
foreach (var f in alleKurse) // auch Nicht-NC-Fächer
{
var jn = f.getHjLeistung(HjArt.JN);
if (jn == null || jn.Punkte < 4)
return false;
}
return true;
}
}
/// <summary>
/// Verwaltet alle Noten eines Schülers in einem Fach (=Kurs)
/// </summary>
public class FachSchuelerNoten
{
public Schueler schueler;
private SchuelerNoten schuelernoten;
private Fach fach = null;
public bool BerechnungFehlt = false;
public bool NoteUngueltig = false;
public int kursId
{
get;
private set;
}
//private static readonly log4net.ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
// das Array wird über das Halbjahr und den Notentyp indiziert,
// jedes Arrayelement enthält eine Liste mit Noten dieses Typs.
private IList<int>[,] noten = new List<int>[Enum.GetValues(typeof(Halbjahr)).Length, Enum.GetValues(typeof(Notentyp)).Length];
private HjLeistung[] hjLeistung = new HjLeistung[Enum.GetValues(typeof(HjArt)).Length];
private HjLeistung[] vorHjLeistung = new HjLeistung[2]; // enthält nur 11/1 und 11/2
public FachSchuelerNoten(Schueler aschueler, int akursid, SchuelerNoten aschuelernoten)
{
kursId = akursid;
schueler = aschueler;
schuelernoten = aschuelernoten;
foreach (Halbjahr hj in Enum.GetValues(typeof(Halbjahr)))
{
// erstmal leere Notenlisten anlegen
foreach (Notentyp typ in Enum.GetValues(typeof(Notentyp)))
noten[(int)hj, (int)typ] = new List<int>();
}
// Notenlisten füllen je Typ und Halbjahr
LeseNotenAusDB();
}
// Kursunabhängige HjLeistungen (z.B. abgelegte Fächer oder Seminararbeit) können hier erzeugt werden
public FachSchuelerNoten(Schueler aschueler, Fach aFach, SchuelerNoten aschuelernoten)
{
fach = aFach;
kursId = 0;
schueler = aschueler;
schuelernoten = aschuelernoten;
LeseNotenAusDB(fach.getKursniveau() == Kursniveau.Fortg);
}
// HjLeistungen, die als eigenes Fach behandelt werden, aber aus andere Quelle kommen (FR, FpA, Seminar)
public FachSchuelerNoten(Schueler aschueler, List<HjLeistung> hjList, SchuelerNoten aschuelernoten)
{
fach = hjList[0].getFach;
schuelernoten = aschuelernoten;
foreach (var hj in hjList)
{
hjLeistung[(int)(hj.Art)] = hj;
}
}
private void LeseNotenAusDB(bool AlteZweiteFS = false)
{
if (kursId > 0)
{
diNoDataSet.NoteDataTable notenDT;
notenDT = new NoteTableAdapter().GetDataBySchuelerAndKurs(schueler.Id, kursId);
foreach (var noteR in notenDT)
{
noten[noteR.Halbjahr, noteR.Notenart].Add(noteR.Punktwert);
}
}
// HjLeistungen
// nur die HjLeistungen holen, die der aktuellen JgStufe entsprechen
int jg = (int)schueler.getKlasse.Jahrgangsstufe;
var ta = new HjLeistungTableAdapter();
IEnumerable<diNoDataSet.HjLeistungRow> hjDT;
// suche alte Französischnoten
if (AlteZweiteFS)
hjDT = ta.GetDataBySchuelerAndFach(schueler.Id, getFach.Id); // kann aus einer früheren 12./13. Klasse kommen
else
// alle HjLeistungen dieses Jahres selektieren, Sprachniveau kann aus vorigen Jahrgangsstufen mitgebracht worden sein.
hjDT = ta.GetDataBySchuelerAndFach(schueler.Id, getFach.Id).Where(x => x.JgStufe == jg || x.Art == (byte)HjArt.Sprachenniveau);
foreach (var hjR in hjDT)
{
hjLeistung[(int)(hjR.Art)] = new HjLeistung(hjR);
if ((HjArt)hjR.Art == HjArt.FR)
{
schuelernoten.Fachreferat.Add(hjLeistung[(int)(hjR.Art)]);
}
}
if (schueler.hatVorHj)
{
hjDT = ta.GetDataBySchuelerAndFach(schueler.Id, getFach.Id).Where(x => x.JgStufe == jg - 1 && x.Art < 2);
foreach (var hjR in hjDT)
{
vorHjLeistung[(int)(hjR.Art)] = new HjLeistung(hjR);
}
}
}
/// <summary>
/// Liefert die erste Note eines Schülers in einem Fach von diesem Typ
/// </summary>
public int? getNote(Halbjahr hj, Notentyp typ)
{
var n = noten[(int)hj, (int)typ];
return n == null || n.Count == 0 ? null : (int?)n.First();
}
/// <summary>
/// Liefert alle Noten eines Schülers in einem Fach von diesem Typ
/// </summary>
public IList<int> getNoten(Halbjahr hj, Notentyp typ)
{
return noten[(int)hj, (int)typ]; // klappt der Cast immer???
}
/// <summary>
/// Liefert die Halbjahresleistungen
/// </summary>
public HjLeistung getHjLeistung(HjArt art)
{
return hjLeistung[(int)art];
}
public void setHjLeistung(HjLeistung hj)
{
hjLeistung[(int)hj.Art] = hj;
}
public HjLeistung getVorHjLeistung(HjArt art)
{
return vorHjLeistung[(int)art];
}
public void NimmHj(Fachsumme fs, HjArt a, bool vorJahr, bool ignoreEinbringung = false)
{
int faktor = 1;
HjLeistung hj;
if (vorJahr) hj = getVorHjLeistung(a);
else hj = getHjLeistung(a);
if (hj != null && hj.Status != HjStatus.Ungueltig && (a==HjArt.AP || hj.Status <= HjStatus.Einbringen || ignoreEinbringung))
{
if (a == HjArt.AP)
{
faktor = schueler.APFaktor;
}
fs.anz += faktor;
fs.sum += hj.Punkte * faktor;
// log.Debug("Jahr=" + (vorJahr?"11":"12") + "Art=" + a + " P=" + hj.Punkte);
}
}
/// <summary>
/// Bestimmt die Punktesumme der eingebrachten Halbjahre dieses Faches
/// </summary>
public Fachsumme SummeHalbjahre(bool ignoreEinbringung = false)
{
Fachsumme fs = new Fachsumme();
NimmHj(fs, HjArt.Hj1, true, false);
NimmHj(fs, HjArt.Hj2, true, ignoreEinbringung);
NimmHj(fs, HjArt.Hj1, false, ignoreEinbringung); // NichtNC-Fächer werden zwar nicht eingebracht, GesErg wird aber über alle Hj gebildet
NimmHj(fs, HjArt.Hj2, false, ignoreEinbringung);
return fs;
}
/// <summary>
/// Berechnet das Gesamtergebnis für dieses Fach aufgrund der vorliegenden HjLeistungen neu (nur Abiturklassen)
/// </summary>
public void BerechneGesErg(Punktesumme p)
{
Fachsumme fs;
Fachsumme fsprache; // Fremdsprache getrennt
Fachsumme ap = new Fachsumme(); // Abiergebnis
bool istFS = fach.getKursniveau() != Kursniveau.None; // Fremdsprache
HjLeistung gesErg = getHjLeistung(HjArt.GesErg);
if (gesErg == null) gesErg = new HjLeistung(schueler.Id, fach, HjArt.GesErg, schueler.getKlasse.Jahrgangsstufe);
// 4 mögliche Halbjahre:
// log.Debug("Fach " + fach.Kuerzel);
fs = SummeHalbjahre(fach.NichtNC); // Nicht-NC-Fächer ausrechnen, aber nicht verbuchen
// Verbuchen auf die richtige Gesamt-Punktesumme (über alle Fächer)
if (fach.Typ == FachTyp.FPA) p.Add(PunktesummeArt.FPA, fs);
else if (!fach.NichtNC) p.Add(PunktesummeArt.HjLeistungen, fs);
// AP
NimmHj(ap, HjArt.AP, false);
p.Add(PunktesummeArt.AP, ap);
// Gesamtergebnis berechnen (dazu das AP-Ergebnis mitnehmen)
fs.Add(ap);
fs.SaveGesErg(gesErg);
// extra Rechnung für Sprachniveau (unabhängig von Einbringung)
if (istFS)
{
fsprache = SummeHalbjahre(true);
fsprache.Add(ap);
gesErg = getHjLeistung(HjArt.GesErgSprache);
if (gesErg == null) gesErg = new HjLeistung(schueler.Id, fach, HjArt.GesErgSprache, schueler.getKlasse.Jahrgangsstufe);
fsprache.SaveGesErg(gesErg);
}
}
/// <summary>
/// Liefert die zur Zeit z (z.B. Probezeit BOS) relevante Note (hier Jahresfortgang Ganzz. 1. Hj.)
/// </summary>
public byte? getRelevanteNote(Zeitpunkt z)
{
HjLeistung hj;
if (z <= Zeitpunkt.HalbjahrUndProbezeitFOS) hj = getHjLeistung(HjArt.Hj1);
else if ((byte)schueler.getKlasse.Jahrgangsstufe < 12)
{
hj = getHjLeistung(HjArt.JN);
if (hj == null)
{
hj = getHjLeistung(HjArt.Hj2); // Behelfskonstruktion, falls im 1. Hj keine Note gebildet wurde (z.B. Rücktritt in Fvk)
NoteUngueltig = true;
}
}
else
{
hj = getHjLeistung(HjArt.GesErg);
if (hj == null)
{
hj = getHjLeistung(HjArt.JN); // behelfsweise, damit man grob den Leistungsstand überprüfen kann
BerechnungFehlt = true;
}
}
if (hj == null) return null;
else
{
if (hj.Status == HjStatus.Ungueltig)
NoteUngueltig = true;
return hj.Punkte;
}
}
public int getNotenanzahl(Halbjahr hj, Notentyp typ)
{
return noten[(int)hj, (int)typ].Count;
}
public int getNotenanzahl(Notentyp typ)
{
return noten[(int)Halbjahr.Erstes, (int)typ].Count + noten[(int)Halbjahr.Zweites, (int)typ].Count;
}
public Fach getFach
{
get
{
if (fach == null)
{
Kurs k = Zugriff.Instance.KursRep.Find(kursId);
fach = Zugriff.Instance.FachRep.Find(k.Data.FachId);
}
return fach;
}
}
private string NotenString(IList<int> noten, string bez = "")
{
if (noten == null) return ""; // tritt bei Fach ohne Kurs auf (z.B. Fpa)
string s = "";
if (noten != null)
{
foreach (var note in noten)
{
s += note + bez + " ";
}
}
return s;
}
/// <summary>
/// Liefert alle SA eines Faches als Text
/// </summary>
public string SA(Halbjahr hj)
{
return (NotenString(getNoten(hj, Notentyp.Schulaufgabe), "")).TrimEnd();
}
public string ToString(Halbjahr hj, Notentyp typ)
{
return (NotenString(getNoten(hj, typ), "")).TrimEnd();
}
/// <summary>
/// Liefert alle sonstige Leistungen eines Faches als Text
/// </summary>
public string sL(Halbjahr hj)
{
string s;
s = NotenString(getNoten(hj, Notentyp.Kurzarbeit), "K");
s += NotenString(getNoten(hj, Notentyp.Ex), "");
s += NotenString(getNoten(hj, Notentyp.EchteMuendliche), "");
// s+=NotenString(getNoten(hj, Notentyp.Ersatzprüfung), "E"); gibts im Excel nicht mehr
return s.TrimEnd();
}
public string NotwendigeNoteInMAP(double Zielpunkte)
{
if (getFach.Kuerzel == "E" || !getFach.IstSAPFach(schueler.Zweig)) return ""; // in Nebenfächern gibt es keine MAP
if (getHjLeistung(HjArt.GesErg) == null) return "";
int zeugnis = getHjLeistung(HjArt.GesErg).Punkte;
if (zeugnis >= Zielpunkte) return ""; // Ziel schon erreicht
Fachsumme fs = SummeHalbjahre();
int faktor = schueler.APFaktor;
int apg = (int)Math.Ceiling((Zielpunkte * (fs.anz + faktor) - fs.sum) / (double)faktor); // diese Note müsste im Abigesamt stehen
var sapL = getNoten(Halbjahr.Zweites, Notentyp.APSchriftlich);
int sap;
if (sapL.Count > 0) sap = sapL[0];
else if (getHjLeistung(HjArt.AP) != null) sap = getHjLeistung(HjArt.AP).Punkte; // sollte nur im Test passieren.
else return "";
int map = Math.Max(3 * apg - 2 * sap - 1, 3); // mind. 3P, sonst wird auf 0 abgerundet.
if (map > 15) return "nicht möglich";
else return map.ToString();
}
public string NotwendigeNoteAPG()
{
if (getFach.Kuerzel == "E" || !getFach.IstSAPFach(schueler.Zweig)) return ""; // in Nebenfächern gibt es keine MAP
var sapL = getNoten(Halbjahr.Zweites, Notentyp.APSchriftlich);
int sap;
if (sapL.Count > 0) sap = sapL[0];
else if (getHjLeistung(HjArt.AP) != null) sap = getHjLeistung(HjArt.AP).Punkte; // sollte nur im Test passieren.
else return "";
if (sap > 3) return "";
int map = 11 - 2 * sap;
return map.ToString();
}
}
// Verwaltet die Gesamtergebnis-Varianten, um zu überprüfen, ob ein Schüler noch in die MAP darf
public class GEVariante
{
public int AP, GE, PunkteDiff, ProblemDiff;
public void CalcDiff(int APalt, int GEalt, int faktor)
{
PunkteDiff = (AP - APalt) * faktor;
ProblemDiff = ProblemLevel(GE) - ProblemLevel(GEalt);
}
private int ProblemLevel(int ge)
{
if (ge == 0) return 2;
else if (ge < 4) return 1;
else return 0;
}
}
}