making a calculation with the elements of an elasticsearch json object, of a contract bridge score, using...
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
add a comment |
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
add a comment |
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
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
python elasticsearch
edited Jan 5 at 17:08
user1903663
asked Dec 24 '18 at 18:03
user1903663user1903663
5241931
5241931
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
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}
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 firstsum
incompute_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
|
show 8 more comments
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.
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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}
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 firstsum
incompute_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
|
show 8 more comments
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}
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 firstsum
incompute_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
|
show 8 more comments
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}
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}
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 firstsum
incompute_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
|
show 8 more comments
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 firstsum
incompute_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
|
show 8 more comments
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.
add a comment |
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.
add a comment |
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.
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.
answered Jan 2 at 15:30
user1903663user1903663
5241931
5241931
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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