web-dev-qa-db-fra.com

faire un calcul avec les éléments d'un objet elasticsearch json, d'un score de pont de contrat, en utilisant Python

Les données sont ici:

{'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'}}]}}

Le code Python, intégrant les modifications récentes, est le suivant. Il n’ya aucune tentative de parcourir différentes cartes en tant que tentative intermédiaire. Ces données sont simplement produites par une requête de recherche tous. 

@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)

qui produit, comme auparavant, le dictionnaire correct où la notation est correcte mais il y a duplication des résultats et trop de lignes. De plus, il y a deux exemples de "Aucun" et je ne sais pas d'où ça vient. :

{'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

La notation est correcte mais il y a, encore une fois, plusieurs cas de duplication des résultats des mêmes paires. 

7
user1903663

Ce code va calculer les scores. Le code est assez simple. 

Plutôt que de parcourir le dictionnaire en entrée pour calculer les scores de chaque paire, les scores Nord-Sud sont stockés dans une collections.Counter instance qui conserve le nombre de paires ayant généré chaque score. Cela facilite le calcul du score de match pour chaque paire - nous doublons simplement le nombre de scores les plus faibles et ajoutons le nombre de scores égaux obtenus, moins un pour prendre en compte le score du partenariat actuel. 

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)

Lancer le code:

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

Produit cette sortie:

{'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}
3
snakecharmerb

Ce n'est PAS mon travail, c'est le travail de "va" mais comme c'est la réponse que je cherche je le posterai ici pour que cela puisse aider les autres. 

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)

Je vous remercie.

0
user1903663