def suggest_participant(event):
    """
    Returns a suggested participant to be selected by the next wheel spin

    :param event: Lambda event containing the API Gateway request path parameter wheel_id
    {
      "pathParameters":
      {
        "wheel_id": string ID of the wheel (DDB Hash Key)
      },
    }
    :return: response dictionary containing a selected participant_id
    {
      "body":
      {
        "participant_id": string ID of the suggested participant (DDB Hash Key),
        "rigged": True (if rigged, otherwise this key is not present)
      }
    }
    """
    wheel_id = event['pathParameters']['wheel_id']
    wheel = Wheel.get_existing_item(Key={'id': wheel_id})
    if 'rigging' in wheel:
        participant_id = wheel['rigging']['participant_id']
        # Use rigging only if the rigged participant is still available
        if 'Item' in WheelParticipant.get_item(Key={
                'wheel_id': wheel_id,
                'id': participant_id
        }):
            return_value = {'participant_id': participant_id}
            # Only return rigged: True if we're not using hidden rigging
            if not wheel['rigging'].get('hidden', False):
                return_value['rigged'] = True
            return return_value
    return {'participant_id': choice_algorithm.suggest_participant(wheel)}
Ejemplo n.º 2
0
def test_selection_cycle(mock_dynamodb, setup_data, mock_participant_table):
    def get_participant_with_id(participants, target_id):
        for p in participants:
            if p['id'] == target_id:
                return p
        return None

    rngstate = random.getstate()
    random.seed(0)  # Make the (otherwise pseudorandom) test repeatable.

    participants = WheelParticipant.scan({})['Items']
    wheel = setup_data['wheel']
    total_weight_of_chosens = 0
    num_iterations = 200

    distro = {}
    for participant in participants:
        distro[participant['name']] = 0

    for _ in range(0, num_iterations):

        chosen_id = choice_algorithm.suggest_participant(wheel)

        chosen_was = get_participant_with_id(participants, chosen_id)
        chosen_was_weight = chosen_was['weight']

        distro[chosen_was['name']] = distro[chosen_was['name']] + 1

        choice_algorithm.select_participant(wheel, chosen_was)

        participants = WheelParticipant.scan({})['Items']

        chosen_now = get_participant_with_id(participants, chosen_id)
        chosen_now_weight = chosen_now['weight']

        assert chosen_was_weight > 0.0
        assert chosen_now_weight == 0
        total_weight_of_chosens += chosen_was_weight

        total_weight = sum(
            [participant['weight'] for participant in participants])
        assert abs(total_weight - len(participants)) < epsilon

    # Must match human-inspected reasonable values for the RNG seed defined
    # above for number of times each participant was chosen, and the total
    # weight of participants selected. These are a rough equivalent to
    # ensuring that the sequence of chosen participants matches the observed
    #  test run.
    dv = list(distro.values())
    list.sort(dv)
    human_observed_selection_counts = [26, 27, 27, 29, 29, 31, 31]
    human_observed_total_weight = 317.8786415239279
    assert dv == human_observed_selection_counts
    assert abs(float(total_weight_of_chosens) -
               human_observed_total_weight) < epsilon

    # Put things back the way they were.
    random.setstate(rngstate)
def test_suggest_participant_no_participants(mock_dynamodb):
    wheel = {'participant_count': 0}
    with pytest.raises(BadRequestError):
        choice_algorithm.suggest_participant(wheel)
def test_suggest_participant(mock_dynamodb, setup_data):
    participant_ids = [
        participant['id'] for participant in setup_data['participants']
    ]
    assert choice_algorithm.suggest_participant(
        setup_data['wheel']) in participant_ids