in api/choice_algorithm.py [0:0]
def on_participant_deletion(wheel, participant):
"""
Normalize the remaining participant weights to account for participant removal.
The ratio is based on the following:
1) The participant should be at weight=1 when it leaves the system (which is the same as it arrived)
2) That difference should be split by the remaining participants proportional by weight
This ensures that 'weight=0' participants are still at weight=0 and that the sum of all
weights is equal to the number of participants, so new additions are treated fairly
:param wheel: Wheel dictionary:
{
"id": string ID of the wheel (DDB Hash Key),
"name": string name of the wheel,
"participant_count": number of participants in the wheel,
}
:param participant: Participant dictionary:
{
"id": string ID of the wheel (DDB Hash Key),
"name": string name of the wheel,
"url": Participant's URL,
"wheel_id": string ID of the wheel the participant belongs to,
}
:return: None
"""
total_weight = participant['weight']
for p in WheelParticipant.iter_query(KeyConditionExpression=Key('wheel_id').eq(wheel['id'])):
total_weight += p['weight']
weight = participant['weight']
remaining_weight = total_weight - weight # <-- no longer presumes existing weight balance via 'int(participant_count)'
ratio = (1 + ((weight - 1) / remaining_weight)) if (remaining_weight != 0) else 1
num_participants = Decimal(0)
with WheelParticipant.batch_writer() as batch:
for p in WheelParticipant.iter_query(KeyConditionExpression=Key('wheel_id').eq(wheel['id'])):
if p['id'] != participant['id']:
# This is cast to a string before turning into a decimal because of rounding/inexact guards in boto3
p['weight'] = Decimal(str(float(p['weight']) * float(ratio))) if (remaining_weight != 0) else \
get_sub_wheel_size(p['name'])
batch.put_item(Item=p)
num_participants = num_participants+1
Wheel.update_item(
Key={'id': wheel['id']},
**to_update_kwargs({'participant_count': num_participants})
)