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












7















The data is here:



{'took': 0, 'timed_out': False, '_shards': {'total': 5, 'successful': 5, 'skipped': 0, 'failed': 0}, 'hits': {'total': 16, 'max_score': 1.0, 'hits': [{'_index': 'matchpoints', '_type': 'score', '_id': '6PKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '1', 'nsp': '4', 'ewp': '11', 'contract': '3NT', 'by': 'N', 'tricks': '11', 'nsscore': '460', 'ewscore ': '0'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '7_KYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '2', 'nsp': '3', 'ewp': '10', 'contract': '3C', 'by': 'E', 'tricks': '10', 'nsscore': '-130', 'ewscore ': '130'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '6fKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '1', 'nsp': '5', 'ewp': '12', 'contract': '3NT', 'by': 'S', 'tricks': '10', 'nsscore': '400', 'ewscore ': '0'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '8_KYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '2', 'nsp': '7', 'ewp': '14', 'contract': '3C', 'by': 'E', 'tricks': '10', 'nsscore': '-130', 'ewscore ': '130'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '9PKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '2', 'nsp': '8', 'ewp': '15', 'contract': '3C', 'by': 'E', 'tricks': '11', 'nsscore': '-150', 'ewscore ': '150'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '5fKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '1', 'nsp': '1', 'ewp': '16', 'contract': '3NT', 'by': 'N', 'tricks': '10', 'nsscore': '430', 'ewscore ': '0'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '6vKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '1', 'nsp': '6', 'ewp': '13', 'contract': '4S', 'by': 'S', 'tricks': '11', 'nsscore': '480', 'ewscore ': '0'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '6_KYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '1', 'nsp': '7', 'ewp': '14', 'contract': '3NT', 'by': 'S', 'tricks': '8', 'nsscore': '-50', 'ewscore ': '50'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '7fKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '2', 'nsp': '1', 'ewp': '16', 'contract': '6S', 'by': 'N', 'tricks': '12', 'nsscore': '1430', 'ewscore ': '0'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '7vKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '2', 'nsp': '2', 'ewp': '9', 'contract': '3C', 'by': 'E', 'tricks': '10', 'nsscore': '-130', 'ewscore ': '130'}}]}}


The Python code, incorporating recent changes, is as follows. There is no attempt to loop through different boards as my intermediate attempt. This data is just produced by a search all query.



@application.route('/', methods=['GET', 'POST'])
def index():
search = {"query": {"match_all": {}}}
resp = es.search(index="matchpoints", doc_type="score", body = search)
rows = extract_rows(resp)
for board in rows:
scores = score_board(board)
report(scores)
print(report(scores))
return 'ok'

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 =
top = 2 * (len(tables) - 1)
# Store the scores for each N-S partnership.
ns_scores = collections.Counter(int(table["nsscore"]) for table in tables)
# 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)


which produces, as before, the correct dictionary where the scoring is correct but there are duplication of results and too many lines. Also, there are two instances of "None" and I don't know where that comes from. :



{'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': '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}
None
{'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}
{'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}
None


The scoring is correct but there are, again, multiple cases of duplication of the same pairs' results.










share|improve this question





























    7















    The data is here:



    {'took': 0, 'timed_out': False, '_shards': {'total': 5, 'successful': 5, 'skipped': 0, 'failed': 0}, 'hits': {'total': 16, 'max_score': 1.0, 'hits': [{'_index': 'matchpoints', '_type': 'score', '_id': '6PKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '1', 'nsp': '4', 'ewp': '11', 'contract': '3NT', 'by': 'N', 'tricks': '11', 'nsscore': '460', 'ewscore ': '0'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '7_KYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '2', 'nsp': '3', 'ewp': '10', 'contract': '3C', 'by': 'E', 'tricks': '10', 'nsscore': '-130', 'ewscore ': '130'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '6fKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '1', 'nsp': '5', 'ewp': '12', 'contract': '3NT', 'by': 'S', 'tricks': '10', 'nsscore': '400', 'ewscore ': '0'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '8_KYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '2', 'nsp': '7', 'ewp': '14', 'contract': '3C', 'by': 'E', 'tricks': '10', 'nsscore': '-130', 'ewscore ': '130'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '9PKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '2', 'nsp': '8', 'ewp': '15', 'contract': '3C', 'by': 'E', 'tricks': '11', 'nsscore': '-150', 'ewscore ': '150'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '5fKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '1', 'nsp': '1', 'ewp': '16', 'contract': '3NT', 'by': 'N', 'tricks': '10', 'nsscore': '430', 'ewscore ': '0'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '6vKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '1', 'nsp': '6', 'ewp': '13', 'contract': '4S', 'by': 'S', 'tricks': '11', 'nsscore': '480', 'ewscore ': '0'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '6_KYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '1', 'nsp': '7', 'ewp': '14', 'contract': '3NT', 'by': 'S', 'tricks': '8', 'nsscore': '-50', 'ewscore ': '50'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '7fKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '2', 'nsp': '1', 'ewp': '16', 'contract': '6S', 'by': 'N', 'tricks': '12', 'nsscore': '1430', 'ewscore ': '0'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '7vKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '2', 'nsp': '2', 'ewp': '9', 'contract': '3C', 'by': 'E', 'tricks': '10', 'nsscore': '-130', 'ewscore ': '130'}}]}}


    The Python code, incorporating recent changes, is as follows. There is no attempt to loop through different boards as my intermediate attempt. This data is just produced by a search all query.



    @application.route('/', methods=['GET', 'POST'])
    def index():
    search = {"query": {"match_all": {}}}
    resp = es.search(index="matchpoints", doc_type="score", body = search)
    rows = extract_rows(resp)
    for board in rows:
    scores = score_board(board)
    report(scores)
    print(report(scores))
    return 'ok'

    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 =
    top = 2 * (len(tables) - 1)
    # Store the scores for each N-S partnership.
    ns_scores = collections.Counter(int(table["nsscore"]) for table in tables)
    # 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)


    which produces, as before, the correct dictionary where the scoring is correct but there are duplication of results and too many lines. Also, there are two instances of "None" and I don't know where that comes from. :



    {'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': '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}
    None
    {'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}
    {'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}
    None


    The scoring is correct but there are, again, multiple cases of duplication of the same pairs' results.










    share|improve this question



























      7












      7








      7








      The data is here:



      {'took': 0, 'timed_out': False, '_shards': {'total': 5, 'successful': 5, 'skipped': 0, 'failed': 0}, 'hits': {'total': 16, 'max_score': 1.0, 'hits': [{'_index': 'matchpoints', '_type': 'score', '_id': '6PKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '1', 'nsp': '4', 'ewp': '11', 'contract': '3NT', 'by': 'N', 'tricks': '11', 'nsscore': '460', 'ewscore ': '0'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '7_KYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '2', 'nsp': '3', 'ewp': '10', 'contract': '3C', 'by': 'E', 'tricks': '10', 'nsscore': '-130', 'ewscore ': '130'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '6fKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '1', 'nsp': '5', 'ewp': '12', 'contract': '3NT', 'by': 'S', 'tricks': '10', 'nsscore': '400', 'ewscore ': '0'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '8_KYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '2', 'nsp': '7', 'ewp': '14', 'contract': '3C', 'by': 'E', 'tricks': '10', 'nsscore': '-130', 'ewscore ': '130'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '9PKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '2', 'nsp': '8', 'ewp': '15', 'contract': '3C', 'by': 'E', 'tricks': '11', 'nsscore': '-150', 'ewscore ': '150'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '5fKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '1', 'nsp': '1', 'ewp': '16', 'contract': '3NT', 'by': 'N', 'tricks': '10', 'nsscore': '430', 'ewscore ': '0'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '6vKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '1', 'nsp': '6', 'ewp': '13', 'contract': '4S', 'by': 'S', 'tricks': '11', 'nsscore': '480', 'ewscore ': '0'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '6_KYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '1', 'nsp': '7', 'ewp': '14', 'contract': '3NT', 'by': 'S', 'tricks': '8', 'nsscore': '-50', 'ewscore ': '50'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '7fKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '2', 'nsp': '1', 'ewp': '16', 'contract': '6S', 'by': 'N', 'tricks': '12', 'nsscore': '1430', 'ewscore ': '0'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '7vKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '2', 'nsp': '2', 'ewp': '9', 'contract': '3C', 'by': 'E', 'tricks': '10', 'nsscore': '-130', 'ewscore ': '130'}}]}}


      The Python code, incorporating recent changes, is as follows. There is no attempt to loop through different boards as my intermediate attempt. This data is just produced by a search all query.



      @application.route('/', methods=['GET', 'POST'])
      def index():
      search = {"query": {"match_all": {}}}
      resp = es.search(index="matchpoints", doc_type="score", body = search)
      rows = extract_rows(resp)
      for board in rows:
      scores = score_board(board)
      report(scores)
      print(report(scores))
      return 'ok'

      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 =
      top = 2 * (len(tables) - 1)
      # Store the scores for each N-S partnership.
      ns_scores = collections.Counter(int(table["nsscore"]) for table in tables)
      # 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)


      which produces, as before, the correct dictionary where the scoring is correct but there are duplication of results and too many lines. Also, there are two instances of "None" and I don't know where that comes from. :



      {'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': '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}
      None
      {'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}
      {'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}
      None


      The scoring is correct but there are, again, multiple cases of duplication of the same pairs' results.










      share|improve this question
















      The data is here:



      {'took': 0, 'timed_out': False, '_shards': {'total': 5, 'successful': 5, 'skipped': 0, 'failed': 0}, 'hits': {'total': 16, 'max_score': 1.0, 'hits': [{'_index': 'matchpoints', '_type': 'score', '_id': '6PKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '1', 'nsp': '4', 'ewp': '11', 'contract': '3NT', 'by': 'N', 'tricks': '11', 'nsscore': '460', 'ewscore ': '0'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '7_KYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '2', 'nsp': '3', 'ewp': '10', 'contract': '3C', 'by': 'E', 'tricks': '10', 'nsscore': '-130', 'ewscore ': '130'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '6fKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '1', 'nsp': '5', 'ewp': '12', 'contract': '3NT', 'by': 'S', 'tricks': '10', 'nsscore': '400', 'ewscore ': '0'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '8_KYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '2', 'nsp': '7', 'ewp': '14', 'contract': '3C', 'by': 'E', 'tricks': '10', 'nsscore': '-130', 'ewscore ': '130'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '9PKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '2', 'nsp': '8', 'ewp': '15', 'contract': '3C', 'by': 'E', 'tricks': '11', 'nsscore': '-150', 'ewscore ': '150'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '5fKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '1', 'nsp': '1', 'ewp': '16', 'contract': '3NT', 'by': 'N', 'tricks': '10', 'nsscore': '430', 'ewscore ': '0'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '6vKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '1', 'nsp': '6', 'ewp': '13', 'contract': '4S', 'by': 'S', 'tricks': '11', 'nsscore': '480', 'ewscore ': '0'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '6_KYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '1', 'nsp': '7', 'ewp': '14', 'contract': '3NT', 'by': 'S', 'tricks': '8', 'nsscore': '-50', 'ewscore ': '50'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '7fKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '2', 'nsp': '1', 'ewp': '16', 'contract': '6S', 'by': 'N', 'tricks': '12', 'nsscore': '1430', 'ewscore ': '0'}}, {'_index': 'matchpoints', '_type': 'score', '_id': '7vKYGGgBjpp4O0gQgUu5', '_score': 1.0, '_source': {'board_number': '2', 'nsp': '2', 'ewp': '9', 'contract': '3C', 'by': 'E', 'tricks': '10', 'nsscore': '-130', 'ewscore ': '130'}}]}}


      The Python code, incorporating recent changes, is as follows. There is no attempt to loop through different boards as my intermediate attempt. This data is just produced by a search all query.



      @application.route('/', methods=['GET', 'POST'])
      def index():
      search = {"query": {"match_all": {}}}
      resp = es.search(index="matchpoints", doc_type="score", body = search)
      rows = extract_rows(resp)
      for board in rows:
      scores = score_board(board)
      report(scores)
      print(report(scores))
      return 'ok'

      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 =
      top = 2 * (len(tables) - 1)
      # Store the scores for each N-S partnership.
      ns_scores = collections.Counter(int(table["nsscore"]) for table in tables)
      # 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)


      which produces, as before, the correct dictionary where the scoring is correct but there are duplication of results and too many lines. Also, there are two instances of "None" and I don't know where that comes from. :



      {'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': '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}
      None
      {'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}
      {'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}
      None


      The scoring is correct but there are, again, multiple cases of duplication of the same pairs' results.







      python elasticsearch






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Jan 5 at 17:08







      user1903663

















      asked Dec 24 '18 at 18:03









      user1903663user1903663

      5241931




      5241931
























          2 Answers
          2






          active

          oldest

          votes


















          3





          +50









          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}





          share|improve this answer


























          • Absolutely amazing, thank you. Do you play bridge? Seems you do. This has anticipated other difficulties that I am expecting to deal with later in this project so thank you for that too. Would you like the bounty?

            – user1903663
            Jan 2 at 16:56











          • I used to play, but it's been a while now. Obviously I'd appreciate the bounty, upvotes etc but best you wait until the end of the period (the system may enforce that anyway) - someone else might have an even better solution!

            – snakecharmerb
            Jan 2 at 17:07











          • right ho we'll wait but, as you say, may not have a choice. Meantime I will tick your answer.

            – user1903663
            Jan 2 at 17:29











          • I made a small change - moved the multiplication out of the first sum in compute_mp so that we only need to multiply once, rather than multiplying each value. This is more efficient, though it doesn't matter too much unless you are computing a lot of results.

            – snakecharmerb
            Jan 4 at 8:14











          • I have edited my question to include new difficulties.

            – user1903663
            Jan 4 at 19:01



















          0














          This NOT my work, it is the work of "rvs" but as this is the answer I am looking for I will post it here so that may help others.



          scores = {}
          for row in arr["hits"]["hits"]:
          nsp = row["_source"]["nsp"]
          nsscore = row["_source"]["nsscore"]
          scores[nsp] = nsscore

          input_scores = {}

          def calculate_score(pair, scores):
          score = 0
          for p in scores:
          if p == pair:
          continue
          if scores[p] < scores[pair]:
          score += 2 # win
          elif scores[p] == scores[pair]:
          score += 1
          return score


          board_num = arr["hits"]["total"]
          top = (board_num - 1) * 2
          result_score = {}
          for row in arr["hits"]["hits"]:
          nsp = row["_source"]["nsp"]
          ewp = row["_source"]["ewp"]
          res = calculate_score(nsp, scores)
          ew_mp_score = top - res
          result_score.update({'nsp':nsp, 'ns_mp_score': res, 'ewp': ewp, 'ew_mp_score': ew_mp_score})
          print(result_score)


          Thank you.






          share|improve this answer























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53916503%2fmaking-a-calculation-with-the-elements-of-an-elasticsearch-json-object-of-a-con%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            3





            +50









            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}





            share|improve this answer


























            • Absolutely amazing, thank you. Do you play bridge? Seems you do. This has anticipated other difficulties that I am expecting to deal with later in this project so thank you for that too. Would you like the bounty?

              – user1903663
              Jan 2 at 16:56











            • I used to play, but it's been a while now. Obviously I'd appreciate the bounty, upvotes etc but best you wait until the end of the period (the system may enforce that anyway) - someone else might have an even better solution!

              – snakecharmerb
              Jan 2 at 17:07











            • right ho we'll wait but, as you say, may not have a choice. Meantime I will tick your answer.

              – user1903663
              Jan 2 at 17:29











            • I made a small change - moved the multiplication out of the first sum in compute_mp so that we only need to multiply once, rather than multiplying each value. This is more efficient, though it doesn't matter too much unless you are computing a lot of results.

              – snakecharmerb
              Jan 4 at 8:14











            • I have edited my question to include new difficulties.

              – user1903663
              Jan 4 at 19:01
















            3





            +50









            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}





            share|improve this answer


























            • Absolutely amazing, thank you. Do you play bridge? Seems you do. This has anticipated other difficulties that I am expecting to deal with later in this project so thank you for that too. Would you like the bounty?

              – user1903663
              Jan 2 at 16:56











            • I used to play, but it's been a while now. Obviously I'd appreciate the bounty, upvotes etc but best you wait until the end of the period (the system may enforce that anyway) - someone else might have an even better solution!

              – snakecharmerb
              Jan 2 at 17:07











            • right ho we'll wait but, as you say, may not have a choice. Meantime I will tick your answer.

              – user1903663
              Jan 2 at 17:29











            • I made a small change - moved the multiplication out of the first sum in compute_mp so that we only need to multiply once, rather than multiplying each value. This is more efficient, though it doesn't matter too much unless you are computing a lot of results.

              – snakecharmerb
              Jan 4 at 8:14











            • I have edited my question to include new difficulties.

              – user1903663
              Jan 4 at 19:01














            3





            +50







            3





            +50



            3




            +50





            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}





            share|improve this answer















            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}






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Jan 7 at 11:31

























            answered Jan 2 at 16:53









            snakecharmerbsnakecharmerb

            11.9k42552




            11.9k42552













            • Absolutely amazing, thank you. Do you play bridge? Seems you do. This has anticipated other difficulties that I am expecting to deal with later in this project so thank you for that too. Would you like the bounty?

              – user1903663
              Jan 2 at 16:56











            • I used to play, but it's been a while now. Obviously I'd appreciate the bounty, upvotes etc but best you wait until the end of the period (the system may enforce that anyway) - someone else might have an even better solution!

              – snakecharmerb
              Jan 2 at 17:07











            • right ho we'll wait but, as you say, may not have a choice. Meantime I will tick your answer.

              – user1903663
              Jan 2 at 17:29











            • I made a small change - moved the multiplication out of the first sum in compute_mp so that we only need to multiply once, rather than multiplying each value. This is more efficient, though it doesn't matter too much unless you are computing a lot of results.

              – snakecharmerb
              Jan 4 at 8:14











            • I have edited my question to include new difficulties.

              – user1903663
              Jan 4 at 19:01



















            • Absolutely amazing, thank you. Do you play bridge? Seems you do. This has anticipated other difficulties that I am expecting to deal with later in this project so thank you for that too. Would you like the bounty?

              – user1903663
              Jan 2 at 16:56











            • I used to play, but it's been a while now. Obviously I'd appreciate the bounty, upvotes etc but best you wait until the end of the period (the system may enforce that anyway) - someone else might have an even better solution!

              – snakecharmerb
              Jan 2 at 17:07











            • right ho we'll wait but, as you say, may not have a choice. Meantime I will tick your answer.

              – user1903663
              Jan 2 at 17:29











            • I made a small change - moved the multiplication out of the first sum in compute_mp so that we only need to multiply once, rather than multiplying each value. This is more efficient, though it doesn't matter too much unless you are computing a lot of results.

              – snakecharmerb
              Jan 4 at 8:14











            • I have edited my question to include new difficulties.

              – user1903663
              Jan 4 at 19:01

















            Absolutely amazing, thank you. Do you play bridge? Seems you do. This has anticipated other difficulties that I am expecting to deal with later in this project so thank you for that too. Would you like the bounty?

            – user1903663
            Jan 2 at 16:56





            Absolutely amazing, thank you. Do you play bridge? Seems you do. This has anticipated other difficulties that I am expecting to deal with later in this project so thank you for that too. Would you like the bounty?

            – user1903663
            Jan 2 at 16:56













            I used to play, but it's been a while now. Obviously I'd appreciate the bounty, upvotes etc but best you wait until the end of the period (the system may enforce that anyway) - someone else might have an even better solution!

            – snakecharmerb
            Jan 2 at 17:07





            I used to play, but it's been a while now. Obviously I'd appreciate the bounty, upvotes etc but best you wait until the end of the period (the system may enforce that anyway) - someone else might have an even better solution!

            – snakecharmerb
            Jan 2 at 17:07













            right ho we'll wait but, as you say, may not have a choice. Meantime I will tick your answer.

            – user1903663
            Jan 2 at 17:29





            right ho we'll wait but, as you say, may not have a choice. Meantime I will tick your answer.

            – user1903663
            Jan 2 at 17:29













            I made a small change - moved the multiplication out of the first sum in compute_mp so that we only need to multiply once, rather than multiplying each value. This is more efficient, though it doesn't matter too much unless you are computing a lot of results.

            – snakecharmerb
            Jan 4 at 8:14





            I made a small change - moved the multiplication out of the first sum in compute_mp so that we only need to multiply once, rather than multiplying each value. This is more efficient, though it doesn't matter too much unless you are computing a lot of results.

            – snakecharmerb
            Jan 4 at 8:14













            I have edited my question to include new difficulties.

            – user1903663
            Jan 4 at 19:01





            I have edited my question to include new difficulties.

            – user1903663
            Jan 4 at 19:01













            0














            This NOT my work, it is the work of "rvs" but as this is the answer I am looking for I will post it here so that may help others.



            scores = {}
            for row in arr["hits"]["hits"]:
            nsp = row["_source"]["nsp"]
            nsscore = row["_source"]["nsscore"]
            scores[nsp] = nsscore

            input_scores = {}

            def calculate_score(pair, scores):
            score = 0
            for p in scores:
            if p == pair:
            continue
            if scores[p] < scores[pair]:
            score += 2 # win
            elif scores[p] == scores[pair]:
            score += 1
            return score


            board_num = arr["hits"]["total"]
            top = (board_num - 1) * 2
            result_score = {}
            for row in arr["hits"]["hits"]:
            nsp = row["_source"]["nsp"]
            ewp = row["_source"]["ewp"]
            res = calculate_score(nsp, scores)
            ew_mp_score = top - res
            result_score.update({'nsp':nsp, 'ns_mp_score': res, 'ewp': ewp, 'ew_mp_score': ew_mp_score})
            print(result_score)


            Thank you.






            share|improve this answer




























              0














              This NOT my work, it is the work of "rvs" but as this is the answer I am looking for I will post it here so that may help others.



              scores = {}
              for row in arr["hits"]["hits"]:
              nsp = row["_source"]["nsp"]
              nsscore = row["_source"]["nsscore"]
              scores[nsp] = nsscore

              input_scores = {}

              def calculate_score(pair, scores):
              score = 0
              for p in scores:
              if p == pair:
              continue
              if scores[p] < scores[pair]:
              score += 2 # win
              elif scores[p] == scores[pair]:
              score += 1
              return score


              board_num = arr["hits"]["total"]
              top = (board_num - 1) * 2
              result_score = {}
              for row in arr["hits"]["hits"]:
              nsp = row["_source"]["nsp"]
              ewp = row["_source"]["ewp"]
              res = calculate_score(nsp, scores)
              ew_mp_score = top - res
              result_score.update({'nsp':nsp, 'ns_mp_score': res, 'ewp': ewp, 'ew_mp_score': ew_mp_score})
              print(result_score)


              Thank you.






              share|improve this answer


























                0












                0








                0







                This NOT my work, it is the work of "rvs" but as this is the answer I am looking for I will post it here so that may help others.



                scores = {}
                for row in arr["hits"]["hits"]:
                nsp = row["_source"]["nsp"]
                nsscore = row["_source"]["nsscore"]
                scores[nsp] = nsscore

                input_scores = {}

                def calculate_score(pair, scores):
                score = 0
                for p in scores:
                if p == pair:
                continue
                if scores[p] < scores[pair]:
                score += 2 # win
                elif scores[p] == scores[pair]:
                score += 1
                return score


                board_num = arr["hits"]["total"]
                top = (board_num - 1) * 2
                result_score = {}
                for row in arr["hits"]["hits"]:
                nsp = row["_source"]["nsp"]
                ewp = row["_source"]["ewp"]
                res = calculate_score(nsp, scores)
                ew_mp_score = top - res
                result_score.update({'nsp':nsp, 'ns_mp_score': res, 'ewp': ewp, 'ew_mp_score': ew_mp_score})
                print(result_score)


                Thank you.






                share|improve this answer













                This NOT my work, it is the work of "rvs" but as this is the answer I am looking for I will post it here so that may help others.



                scores = {}
                for row in arr["hits"]["hits"]:
                nsp = row["_source"]["nsp"]
                nsscore = row["_source"]["nsscore"]
                scores[nsp] = nsscore

                input_scores = {}

                def calculate_score(pair, scores):
                score = 0
                for p in scores:
                if p == pair:
                continue
                if scores[p] < scores[pair]:
                score += 2 # win
                elif scores[p] == scores[pair]:
                score += 1
                return score


                board_num = arr["hits"]["total"]
                top = (board_num - 1) * 2
                result_score = {}
                for row in arr["hits"]["hits"]:
                nsp = row["_source"]["nsp"]
                ewp = row["_source"]["ewp"]
                res = calculate_score(nsp, scores)
                ew_mp_score = top - res
                result_score.update({'nsp':nsp, 'ns_mp_score': res, 'ewp': ewp, 'ew_mp_score': ew_mp_score})
                print(result_score)


                Thank you.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jan 2 at 15:30









                user1903663user1903663

                5241931




                5241931






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53916503%2fmaking-a-calculation-with-the-elements-of-an-elasticsearch-json-object-of-a-con%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    MongoDB - Not Authorized To Execute Command

                    How to fix TextFormField cause rebuild widget in Flutter

                    Npm cannot find a required file even through it is in the searched directory