Move core matching factors to the config file

Bonus changes here were making the config a singleton, fixing some more tests and then re-writing the stress test because it was pissing me off.
This commit is contained in:
Marc Di Luzio 2024-08-11 22:07:43 +01:00
parent a5d7dae851
commit 9043615498
6 changed files with 254 additions and 86 deletions

View file

@ -3,20 +3,24 @@ import logging
from datetime import datetime, timedelta
from typing import Protocol, runtime_checkable
import state
# Number of days to step forward from the start of history for each match attempt
_ATTEMPT_TIMESTEP_INCREMENT = timedelta(days=7)
import config
class _ScoreFactors(int):
"""Various eligability scoring factors for group meetups"""
REPEAT_ROLE = 2**2
REPEAT_MATCH = 2**3
EXTRA_MEMBER = 2**5
"""
Score factors used when trying to build up "best fit" groups
Matchees are sequentially placed into the lowest scoring available group
"""
# Scores higher than this are fully rejected
UPPER_THRESHOLD = 2**6
# Added for each role the matchee has that another group member has
REPEAT_ROLE = config.Config.score_factors.repeat_role or 2**2
# Added for each member in the group that the matchee has already matched with
REPEAT_MATCH = config.Config.score_factors.repeat_match or 2**3
# Added for each additional member over the set "per group" value
EXTRA_MEMBER = config.Config.score_factors.extra_member or 2**5
# Upper threshold, if the user scores higher than this they will not be placed in that group
UPPER_THRESHOLD = config.Config.score_factors.upper_threshold or 2**6
logger = logging.getLogger("matching")
@ -76,8 +80,8 @@ def get_member_group_eligibility_score(member: Member,
return rating
# Add score based on prior matchups of this user
rating += sum(m.id in prior_matches for m in group) * \
_ScoreFactors.REPEAT_MATCH
num_prior = sum(m.id in prior_matches for m in group)
rating += num_prior * _ScoreFactors.REPEAT_MATCH
# Calculate the number of roles that match
all_role_ids = set(r.id for mr in [r.roles for r in group] for r in mr)
@ -159,7 +163,7 @@ def iterate_all_shifts(list: list):
def members_to_groups(matchees: list[Member],
hist: state.State = state.State(),
st: state.State = state.State(),
per_group: int = 3,
allow_fallback: bool = False) -> list[list[Member]]:
"""Generate the groups from the set of matchees"""
@ -170,18 +174,16 @@ def members_to_groups(matchees: list[Member],
if not matchees:
return []
# Grab the oldest timestamp
history_start = hist.get_oldest_timestamp() or datetime.now()
# Walk from the start of time until now using the timestep increment
for oldest_relevant_datetime in datetime_range(history_start, _ATTEMPT_TIMESTEP_INCREMENT, datetime.now()):
# Walk from the start of history until now trying to match up groups
# Or if there's no
for oldest_relevant_datetime in st.get_history_timestamps() + [datetime.now()]:
# Attempt with each starting matchee
for shifted_matchees in iterate_all_shifts(matchees):
attempts += 1
groups = attempt_create_groups(
shifted_matchees, hist, oldest_relevant_datetime, per_group)
shifted_matchees, st, oldest_relevant_datetime, per_group)
# Fail the match if our groups aren't big enough
if num_groups <= 1 or (groups and all(len(g) >= per_group for g in groups)):