making a calculation with the elements of an elasticsearch json object, of a contract bridge score, using Python

This code will calculate the scores. The code is fairly straightforward.

Rather than iterate over the input dictionary to compute the scores for each pair, the the North-South scores are stored in a collections.Counter instance that keeps a count of the number of pairs that made each score. This makes it easier to compute the match point score for each pair - we just double the number of lower scores made and add the number of equal scores made, minus one to account for the score of the current partnership.

import collections                                                                                                               
import itertools                                                                                                                                                                                                                                    


def extract_rows(resp):                                                                                                          
    """Extract the rows for the board from the query response."""                                                                
    # Based on the data structure provided by the OP.                                                          
    rows = [row["_source"] for row in resp["hits"]["hits"]]
    # We want to return the group the data by board number
    # so that we can score each board.                                                                       
    keyfunc = lambda row: int(row['board_number'])                                                                               
    rows.sort(key=keyfunc)                                                                                                       
    for _, group in itertools.groupby(rows, keyfunc):                                                                            
        yield list(group)


def compute_mp(scores, score):
    """Compute the match point score for a pair."""
    mp_score = sum(v for k, v in scores.items() if score > k) * 2
    # The pair's own score will always compare equal - remove it.
    mp_score += sum(v for k, v in scores.items() if score == k) - 1
    return mp_score


def score_board(tables):
    """Build the scores for each pair."""
    scores = []

    # Store the scores for each N-S partnership.
    ns_scores = collections.Counter(int(table["nsscore"]) for table in tables)
    # The top score is (2 * number of tables) - 2, then reduced by one for each 
    # equal top score.
    top = 2 * (len(tables) - 1) - (ns_scores[max(ns_scores)] - 1)
    # Build the output for each pair.
    for table in tables:
        output = {
            "board": table["board_number"],
            "nsp": table["nsp"],
            "ewp": table["ewp"],
        }
        ns_score = int(table["nsscore"])
        ns_mp_score = compute_mp(ns_scores, ns_score)
        output["ns_mp_score"] = ns_mp_score
        ew_mp_score = top - ns_mp_score
        output["ew_mp_score"] = ew_mp_score
        scores.append(output)
    return scores

# Replace this function with one that adds the rows to
# the new search index
def report(scores):
    """Print the scores."""
    for row in scores:
        print(row)

Running the code:

rows = extract_rows(resp)
scores = [score for rows in extract_rows(resp) for score in score_board(rows)]
report(scores)

Produces this output:

{'board': '1', 'nsp': '4', 'ewp': '11', 'ns_mp_score': 6, 'ew_mp_score': 2}
{'board': '1', 'nsp': '5', 'ewp': '12', 'ns_mp_score': 2, 'ew_mp_score': 6}
{'board': '1', 'nsp': '1', 'ewp': '16', 'ns_mp_score': 4, 'ew_mp_score': 4}
{'board': '1', 'nsp': '6', 'ewp': '13', 'ns_mp_score': 8, 'ew_mp_score': 0}
{'board': '1', 'nsp': '7', 'ewp': '14', 'ns_mp_score': 0, 'ew_mp_score': 8}
{'board': '2', 'nsp': '3', 'ewp': '10', 'ns_mp_score': 4, 'ew_mp_score': 4}
{'board': '2', 'nsp': '7', 'ewp': '14', 'ns_mp_score': 4, 'ew_mp_score': 4}
{'board': '2', 'nsp': '8', 'ewp': '15', 'ns_mp_score': 0, 'ew_mp_score': 8}
{'board': '2', 'nsp': '1', 'ewp': '16', 'ns_mp_score': 8, 'ew_mp_score': 0}
{'board': '2', 'nsp': '2', 'ewp': '9', 'ns_mp_score': 4, 'ew_mp_score': 4}