def _score_opslaan(uitslag, sporterboog, waarde): score = Score(afstand_meter=18, sporterboog=sporterboog, waarde=waarde) score.save() hist = ScoreHist(score=score, oude_waarde=0, nieuwe_waarde=waarde) hist.save() uitslag.scores.add(score)
def _maak_wedstrijden(self): self.wedstrijden = list() # maak een ronde + plan ronde = maak_deelcompetitie_ronde(self.deelcomp_regio_18) self.ronde = ronde de_tijd = datetime.time(hour=20) # maak binnen het plan drie wedstrijden voor deze vereniging for volgnr in range(3): wedstrijd = CompetitieWedstrijd(vereniging=self.nhbver1, datum_wanneer=datetime.date( year=2020, month=1, day=5 + volgnr * 3), tijd_begin_aanmelden=de_tijd, tijd_begin_wedstrijd=de_tijd, tijd_einde_wedstrijd=de_tijd) if volgnr <= 1: uitslag = CompetitieWedstrijdUitslag(max_score=300, afstand_meter=12) uitslag.save() wedstrijd.uitslag = uitslag wedstrijd.beschrijving = "Test - Dit is een testje %s" % volgnr if volgnr == 1: score = Score(sporterboog=self.sporterboog_100001, waarde=123, afstand_meter=12) score.save() uitslag.scores.add(score) wedstrijd.save() ronde.plan.wedstrijden.add(wedstrijd) wedstrijd.indiv_klassen.set(IndivWedstrijdklasse.objects.all()) self.wedstrijden.append(wedstrijd) # for # maak voor de vereniging een wedstrijd die niets met de competitie te doen heeft wedstrijd = CompetitieWedstrijd(vereniging=self.nhbver1, datum_wanneer=datetime.date(year=2020, month=2, day=1), tijd_begin_aanmelden=de_tijd, tijd_begin_wedstrijd=de_tijd, tijd_einde_wedstrijd=de_tijd) wedstrijd.save()
def test_scores_regio(self): # RCL kan scores invoeren / inzien / accorderen voor zijn regio self.e2e_login_and_pass_otp(self.testdata.comp18_account_rcl[101]) self.e2e_wissel_naar_functie(self.testdata.comp18_functie_rcl[101]) url = self.url_scores_regio % self.testdata.deelcomp18_regio[101].pk with self.assert_max_queries(20): resp = self.client.get(url) self.assertEqual(resp.status_code, 200) self.assert_html_ok(resp) # zet de ronde uitslag score = Score( sporterboog=self.testdata.comp18_deelnemers[0].sporterboog, afstand_meter=18, waarde=123) score.save() uitslag = CompetitieWedstrijdUitslag(max_score=300, afstand_meter=18) uitslag.save() uitslag.scores.add(score) ronde = DeelcompetitieRonde.objects.filter( deelcompetitie=self.testdata.deelcomp18_regio[101])[0] wedstrijd = ronde.plan.wedstrijden.all()[0] wedstrijd.uitslag = uitslag wedstrijd.save() with self.assert_max_queries(20): resp = self.client.get(url) self.assertEqual(resp.status_code, 200) self.assert_html_ok(resp) url = self.url_scores_regio % self.testdata.deelcomp18_regio[101].pk with self.assert_max_queries(20): resp = self.client.get(url) self.assertEqual(resp.status_code, 200) self.assert_html_ok(resp) # bad deelcomp_pk url = self.url_scores_regio % 999999 with self.assert_max_queries(20): resp = self.client.get(url) self.assert404(resp) # 404 = Not found # verkeerde regio url = self.url_scores_regio % self.testdata.deelcomp25_regio[101].pk with self.assert_max_queries(20): resp = self.client.get(url) self.assert403(resp)
def _maak_uitslag(self, sporterboog): # maak 2x wedstrijd + uitslag + score voor deze schutterboog, met geschiedenis uur_00 = datetime.time(hour=0) uur_18 = datetime.time(hour=18) uur_19 = datetime.time(hour=19) uur_22 = datetime.time(hour=22) uitslag18 = CompetitieWedstrijdUitslag(max_score=300, afstand_meter=18) uitslag18.save() uitslag25 = CompetitieWedstrijdUitslag(max_score=250, afstand_meter=25) uitslag25.save() CompetitieWedstrijd(beschrijving='Test wedstrijdje 18m', datum_wanneer=datetime.date(year=2020, month=10, day=10), tijd_begin_aanmelden=uur_18, tijd_begin_wedstrijd=uur_19, tijd_einde_wedstrijd=uur_22, uitslag=uitslag18, vereniging=self.nhbver1).save() CompetitieWedstrijd(beschrijving='Test wedstrijdje 25m', datum_wanneer=datetime.date(year=2020, month=10, day=11), tijd_begin_aanmelden=uur_00, tijd_begin_wedstrijd=uur_00, tijd_einde_wedstrijd=uur_00, uitslag=uitslag25).save() score = Score(sporterboog=sporterboog, afstand_meter=18, waarde=260) score.save() ScoreHist(score=score, oude_waarde=0, nieuwe_waarde=290, door_account=self.account_hwl).save() ScoreHist(score=score, oude_waarde=290, nieuwe_waarde=260, door_account=self.account_hwl).save() uitslag18.scores.add(score) score = Score(sporterboog=sporterboog, afstand_meter=25, waarde=234) score.save() ScoreHist(score=score, oude_waarde=SCORE_WAARDE_VERWIJDERD, nieuwe_waarde=234, door_account=self.account_hwl).save() ScoreHist(score=score, oude_waarde=0, nieuwe_waarde=SCORE_WAARDE_VERWIJDERD, door_account=self.account_hwl).save() ScoreHist(score=score, oude_waarde=0, nieuwe_waarde=1, door_account=self.account_hwl).save() uitslag25.scores.add(score)
def maak_sporterboog_aanvangsgemiddelden(afstand, ver_nr): """ Maak voor de helft van de SporterBoog een AG aan in voorgaand seizoen deze kunnen gebruikt worden voor de klassengrenzen en inschrijven. """ ag = 6000 # 6.0 ag += ver_nr bulk = list() for sporterboog in (SporterBoog.objects.filter( sporter__bij_vereniging__ver_nr=ver_nr, voor_wedstrijd=True)): # even pk get an AG if sporterboog.pk % 1 == 0: ag = 6000 if ag > 9800 else ag + 25 score = Score(type=SCORE_TYPE_INDIV_AG, sporterboog=sporterboog, waarde=ag, afstand_meter=afstand) bulk.append(score) if len(bulk) > 500: # pragma: no cover Score.objects.bulk_create(bulk) bulk2 = list() for score in bulk: hist = ScoreHist( score=score, oude_waarde=0, nieuwe_waarde=score.waarde, # when = auto-set # door_account=None, notitie='Testdata') bulk2.append(hist) # for ScoreHist.objects.bulk_create(bulk2) del bulk2 bulk = list() # for if len(bulk): # pragma: no branch Score.objects.bulk_create(bulk) bulk2 = list() for score in bulk: hist = ScoreHist( score=score, oude_waarde=0, nieuwe_waarde=score.waarde, # when = auto-set # door_account=None, notitie='Testdata') bulk2.append(hist) # for ScoreHist.objects.bulk_create(bulk2) del bulk2
def nieuwe_score(bulk, uitslag, sporterboog_pk, waarde, when, door_account): # print('nieuwe score: %s = %s' % (sporterboog_pk, waarde)) try: sporterboog = SporterBoog.objects.get(pk=sporterboog_pk) except SporterBoog.DoesNotExist: # garbage --> ignore return score_obj = Score(sporterboog=sporterboog, waarde=waarde, afstand_meter=uitslag.afstand_meter) score_obj.save() uitslag.scores.add(score_obj) hist = ScoreHist(score=score_obj, oude_waarde=0, nieuwe_waarde=waarde, when=when, door_account=door_account, notitie="Invoer uitslag wedstrijd") bulk.append(hist)
def test_fix_bad_ag(self): f1 = io.StringIO() f2 = io.StringIO() with self.assert_max_queries(20): management.call_command('fix_bad_ag', '18', stderr=f1, stdout=f2) self.assertTrue('[ERROR] Competitie is in de verkeerde fase' in f1.getvalue()) zet_competitie_fase(self.comp, 'B') f1 = io.StringIO() f2 = io.StringIO() with self.assert_max_queries(20): management.call_command('fix_bad_ag', '18', stderr=f1, stdout=f2) Score( sporterboog=self.sporterboog_r, type=SCORE_TYPE_INDIV_AG, afstand_meter=18, waarde=8000).save() f1 = io.StringIO() f2 = io.StringIO() with self.assert_max_queries(20): management.call_command('fix_bad_ag', '18', stderr=f1, stdout=f2) self.assertTrue(f1.getvalue() == '') self.assertTrue('Gebruik --commit om wijzigingen door te voeren' in f2.getvalue()) f1 = io.StringIO() f2 = io.StringIO() with self.assert_max_queries(20): management.call_command('fix_bad_ag', '18', '--commit', stderr=f1, stdout=f2) # print("f1: %s" % f1.getvalue()) # print("f2: %s" % f2.getvalue()) self.assertTrue(f1.getvalue() == '') for comp in Competitie.objects.all(): comp.is_afgesloten = True comp.save(update_fields=['is_afgesloten']) f1 = io.StringIO() f2 = io.StringIO() with self.assert_max_queries(20): management.call_command('fix_bad_ag', '18', stderr=f1, stdout=f2) self.assertTrue('[ERROR] Geen actieve competitie gevonden' in f1.getvalue())
def _score_ag_opslaan(score_type, sporterboog, afstand, gemiddelde, door_account, notitie): """ slaan het aanvangsgemiddelde op voor sporterboog Return value: True = opslagen False = niet opgeslagen / dupe """ waarde = int(gemiddelde * 1000) try: score = Score.objects.get(sporterboog=sporterboog, type=score_type, afstand_meter=afstand) except Score.DoesNotExist: # eerste aanvangsgemiddelde voor deze afstand score = Score(sporterboog=sporterboog, type=score_type, waarde=waarde, afstand_meter=afstand) score.save() hist = ScoreHist(score=score, oude_waarde=0, nieuwe_waarde=waarde, door_account=door_account, notitie=notitie) hist.save() return True if score.waarde != waarde: # nieuwe score voor deze afstand hist = ScoreHist(score=score, oude_waarde=score.waarde, nieuwe_waarde=waarde, door_account=door_account, notitie=notitie) hist.save() score.waarde = waarde score.save() return True # dezelfde score als voorheen --> voorlopig niet opslaan # (ook al is de datum en/of notitie anders) return False
def aanvangsgemiddelden_vaststellen_voor_afstand(afstand: int): """ deze functie gooit de huidige aanvangsgemiddelden van alle sporters voor gegeven afstand weg en bepaalt daarna de nieuwe AG's aan de hand van de meest recente historische competitie uitslag """ # zoek uit wat de meest recente HistComp is histcomps = (HistCompetitie .objects .filter(comp_type=afstand) .order_by('-seizoen')) if len(histcomps) == 0: schrijf_in_logboek(None, 'Competitie', 'Geen historisch uitslag om aanvangsgemiddelden vast te stellen voor %sm' % afstand) return seizoen = histcomps[0].seizoen schrijf_in_logboek(None, 'Competitie', 'Aanvangsgemiddelden vaststellen voor de %sm met uitslag seizoen %s' % (afstand, seizoen)) histcomps = histcomps.filter(seizoen=seizoen) # het eindjaar van de competitie was bepalend voor de klasse # daarmee kunnen we bepalen of de sporter aspirant was eindjaar = int(seizoen.split('/')[1]) # maak een cache aan van boogtype boogtype_dict = dict() # [afkorting] = BoogType for obj in BoogType.objects.all(): boogtype_dict[obj.afkorting] = obj # for # maak een cache aan van nhb leden # we filteren hier niet op inactieve leden sporter_dict = dict() # [lid_nr] = Sporter for obj in Sporter.objects.all(): sporter_dict[obj.lid_nr] = obj # for # maak een cache aan van sporter-boog sporterboog_cache = dict() # [lid_nr, boogtype_afkorting] = SporterBoog for sporterboog in SporterBoog.objects.select_related('sporter', 'boogtype'): tup = (sporterboog.sporter.lid_nr, sporterboog.boogtype.afkorting) sporterboog_cache[tup] = sporterboog # for # verwijder alle bestaande aanvangsgemiddelden Score.objects.filter(type=SCORE_TYPE_INDIV_AG, afstand_meter=afstand).all().delete() minimum_aantal_scores = {18: settings.COMPETITIE_18M_MINIMUM_SCORES_VOOR_AG, 25: settings.COMPETITIE_25M_MINIMUM_SCORES_VOOR_AG} # doorloop alle individuele histcomp records die bij dit seizoen horen bulk_score = list() for histcomp in histcomps: for obj in (HistCompetitieIndividueel .objects .select_related('histcompetitie') .filter(histcompetitie=histcomp)): if (obj.gemiddelde > AG_NUL and obj.boogtype in boogtype_dict and obj.tel_aantal_scores() >= minimum_aantal_scores[afstand]): # haal het sporterboog record op, of maak een nieuwe aan try: tup = (obj.schutter_nr, obj.boogtype) sporterboog = sporterboog_cache[tup] except KeyError: # nieuw record nodig sporterboog = SporterBoog() sporterboog.boogtype = boogtype_dict[obj.boogtype] sporterboog.voor_wedstrijd = True try: sporterboog.sporter = sporter_dict[obj.schutter_nr] except KeyError: # geen lid meer - skip sporterboog = None else: sporterboog.save() # zet het nieuwe record in de cache, anders krijgen we dupes tup = (sporterboog.sporter.lid_nr, sporterboog.boogtype.afkorting) sporterboog_cache[tup] = sporterboog else: if not sporterboog.voor_wedstrijd: sporterboog.voor_wedstrijd = True sporterboog.save(update_fields=['voor_wedstrijd']) if sporterboog: # aspiranten schieten op een grotere kaart en altijd op 18m # daarom AG van aspirant niet overnemen als deze cadet wordt # aangezien er maar 1 klasse is, is het AG niet nodig # voorbeeld: eindjaar = 2019 # geboortejaar = 2006 --> leeftijd was 13, dus aspirant # geboortejaar = 2005 --> leeftijd was 14, dus cadet was_aspirant = (eindjaar - sporterboog.sporter.geboorte_datum.year) <= MAXIMALE_WEDSTRIJDLEEFTIJD_ASPIRANT # zoek het score record erbij if not was_aspirant: # aanvangsgemiddelde voor deze afstand waarde = int(obj.gemiddelde * 1000) score = Score(sporterboog=sporterboog, type=SCORE_TYPE_INDIV_AG, waarde=waarde, afstand_meter=afstand) bulk_score.append(score) if len(bulk_score) >= 500: Score.objects.bulk_create(bulk_score) bulk_score = list() # for # for if len(bulk_score) > 0: # pragma: no branch Score.objects.bulk_create(bulk_score) del bulk_score # maak nu alle ScoreHist entries in 1x aan # (dit kost de meeste tijd) # hiervoor hebben we Score.pk nodig en die kregen we niet uit bovenstaande Score.objects.bulk_create bulk_scorehist = list() notitie = "Uitslag competitie seizoen %s" % histcomp.seizoen for score in (Score .objects .filter(type=SCORE_TYPE_INDIV_AG, afstand_meter=afstand)): scorehist = ScoreHist(score=score, oude_waarde=0, nieuwe_waarde=score.waarde, door_account=None, notitie=notitie) bulk_scorehist.append(scorehist) if len(bulk_scorehist) > 250: ScoreHist.objects.bulk_create(bulk_scorehist) bulk_scorehist = list() # for if len(bulk_scorehist) > 0: # pragma: no branch ScoreHist.objects.bulk_create(bulk_scorehist)
def _bepaal_teams_en_scores(deelcomp): alle_regels = list() aantal_keuzes_nodig = 0 # sporters waarvan we de scores op moeten zoeken sporterboog_pks = list() used_score_pks = list() deelnemer2sporter_cache = dict( ) # [deelnemer_pk] = (sporterboog_pk, naam_str) sporterboog_cache = dict() # [sporterboog_pk] = SporterBoog for deelnemer in (RegioCompetitieSchutterBoog.objects.select_related( 'sporterboog', 'sporterboog__sporter').filter(deelcompetitie=deelcomp)): sporterboog = deelnemer.sporterboog sporterboog_cache[sporterboog.pk] = sporterboog sporter = sporterboog.sporter tup = (sporterboog.pk, "[%s] %s" % (sporter.lid_nr, sporter.volledige_naam())) deelnemer2sporter_cache[deelnemer.pk] = tup # for alle_sporterboog_pks = list() afstand = deelcomp.competitie.afstand for poule in (RegiocompetitieTeamPoule.objects.prefetch_related( 'teams').filter( deelcompetitie=deelcomp).order_by('beschrijving')): team_pks = poule.teams.values_list('pk', flat=True) # alle al gebruikte scores used_scores = list( RegiocompetitieRondeTeam.objects.prefetch_related( 'scores_feitelijk').filter(team__in=team_pks).exclude( ronde_nr=deelcomp.huidige_team_ronde).values_list( 'scores_feitelijk__pk', flat=True)) used_score_pks.extend(used_scores) ronde_teams = (RegiocompetitieRondeTeam.objects.select_related( 'team', 'team__vereniging', 'team__klasse__team').prefetch_related( 'deelnemers_feitelijk', 'scores_feitelijk').filter( team__in=team_pks, ronde_nr=deelcomp.huidige_team_ronde).order_by( 'team__vereniging__ver_nr', 'team__volg_nr')) # TODO: is volgende lus nog wel nodig? for ronde_team in ronde_teams: ronde_team.ronde_wp = 0 ronde_team.team_str = "[%s] %s" % ( ronde_team.team.vereniging.ver_nr, ronde_team.team.maak_team_naam_kort()) # for break_poule = poule.beschrijving prev_klasse = None for ronde_team in ronde_teams: regel = SimpleNamespace() regel.poule_str = break_poule break_poule = "" regel.ronde_team = ronde_team regel.team_str = ronde_team.team.maak_team_naam() klasse_str = ronde_team.team.klasse.team.beschrijving if klasse_str != prev_klasse: regel.klasse_str = klasse_str prev_klasse = klasse_str regel.deelnemers = deelnemers = list() for deelnemer in (ronde_team.deelnemers_feitelijk.all()): sporterboog_pk, naam_str = deelnemer2sporter_cache[ deelnemer.pk] sporterboog_pks.append(sporterboog_pk) if sporterboog_pk not in alle_sporterboog_pks: # want deelnemer kan in meerdere teams voorkomen alle_sporterboog_pks.append(sporterboog_pk) deelnemer.naam_str = naam_str deelnemer.sporterboog_pk = sporterboog_pk deelnemer.gevonden_scores = None deelnemer.kan_kiezen = False deelnemer.keuze_nodig = False regel.deelnemers.append(deelnemer) # for regel.score_pks_feitelijk = list( ronde_team.scores_feitelijk.values_list('pk', flat=True)) alle_regels.append(regel) # for # for # via sporterboog_pks kunnen we alle scores vinden # bepaal welke relevant kunnen zijn score2wedstrijd = dict() # haal alle wedstrijdplannen van deze deelcompetitie op plan_pks = (DeelcompetitieRonde.objects.filter( deelcompetitie=deelcomp).values_list('plan__pk', flat=True)) # doorloop alle wedstrijden van deze plannen # de wedstrijd heeft een datum en uitslag met scores for wedstrijd in (CompetitieWedstrijd.objects.select_related( 'uitslag', 'vereniging').prefetch_related('uitslag__scores').exclude( uitslag=None).filter( competitiewedstrijdenplan__in=plan_pks)): # noteer welke scores interessant zijn # en de koppeling naar de wedstrijd, voor de datum for score in wedstrijd.uitslag.scores.all(): score2wedstrijd[score.pk] = wedstrijd # for # for # zorg dat er 'geen score' records zijn voor alle relevante sporters nieuwe_pks = alle_sporterboog_pks[:] nieuwe_pks.sort() for score in (Score.objects.select_related('sporterboog').filter( sporterboog__pk__in=nieuwe_pks, type=SCORE_TYPE_GEEN)): sporterboog_pk = score.sporterboog.pk nieuwe_pks.remove(sporterboog_pk) # for # maak een 'geen score' record aan voor alle nieuwe_pks bulk = list() for sporterboog_pk in nieuwe_pks: sporterboog = sporterboog_cache[sporterboog_pk] score = Score(type=SCORE_TYPE_GEEN, afstand_meter=0, waarde=0, sporterboog=sporterboog) bulk.append(score) # for Score.objects.bulk_create(bulk) del bulk del nieuwe_pks sporterboog_pk2score_geen = dict() for score in (Score.objects.select_related('sporterboog').filter( sporterboog__pk__in=alle_sporterboog_pks, type=SCORE_TYPE_GEEN)): sporterboog_pk = score.sporterboog.pk sporterboog_pk2score_geen[sporterboog_pk] = score # for sporterboog2wedstrijdscores = dict( ) # [sporterboog_pk] = [(score, wedstrijd), ...] early_date = datetime.date(year=2000, month=1, day=1) # doorloop alle scores van de relevante sporters for score in (Score.objects.select_related('sporterboog').exclude( waarde=SCORE_WAARDE_VERWIJDERD).filter( type=SCORE_TYPE_SCORE, sporterboog__pk__in=sporterboog_pks, afstand_meter=afstand)): score.block_selection = (score.pk in used_score_pks) sporterboog_pk = score.sporterboog.pk try: wedstrijd = score2wedstrijd[score.pk] except KeyError: # niet relevante score pass else: # optie A: eerst alle geblokkeerde opties, dan pas de keuzes # if score.block_selection: # tup = (1, wedstrijd.datum_wanneer, wedstrijd.tijd_begin_wedstrijd, wedstrijd.pk, wedstrijd, score) # else: # tup = (2, wedstrijd.datum_wanneer, wedstrijd.tijd_begin_wedstrijd, wedstrijd.pk, wedstrijd, score) # optie B: scores op datum houden tup = (1, wedstrijd.datum_wanneer, wedstrijd.tijd_begin_wedstrijd, wedstrijd.pk, wedstrijd, score) try: sporterboog2wedstrijdscores[sporterboog_pk].append(tup) except KeyError: # dit is de eerste entry sporterboog2wedstrijdscores[sporterboog_pk] = [tup] # voeg een "niet geschoten" optie toe niet_geschoten = sporterboog_pk2score_geen[sporterboog_pk] niet_geschoten.block_selection = False tup = (3, early_date, 0, 0, None, niet_geschoten ) # None = wedstrijd sporterboog2wedstrijdscores[sporterboog_pk].append(tup) # for eerste_anchor = None for regel in alle_regels: for deelnemer in regel.deelnemers: try: tups = sporterboog2wedstrijdscores[ deelnemer.sporterboog_pk] except KeyError: # geen score voor deze sporter deelnemer.gevonden_scores = list() else: # sorteer de gevonden scores op wedstrijddatum tups.sort() deelnemer.gevonden_scores = [ (wedstrijd, score) for _, _, _, _, wedstrijd, score in tups ] aantal = len(tups) for _, score in deelnemer.gevonden_scores: if score.block_selection: aantal -= 1 # for deelnemer.kan_kiezen = deelnemer.keuze_nodig = (aantal > 1) if deelnemer.kan_kiezen: deelnemer.id_radio = "id_score_%s" % deelnemer.sporterboog_pk for wedstrijd, score in deelnemer.gevonden_scores: if not score.block_selection: score.id_radio = "id_score_%s" % score.pk score.is_selected = ( score.pk in regel.score_pks_feitelijk) if score.is_selected: deelnemer.keuze_nodig = False # for if deelnemer.keuze_nodig: if eerste_anchor is None: deelnemer.anchor = eerste_anchor = "anchor_%s" % deelnemer.sporterboog.pk aantal_keuzes_nodig += 1 # for # for return alle_regels, aantal_keuzes_nodig, eerste_anchor