<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _summarize_action(self, root_action):
 """Return a dictionary with various information about this root_action. Note: Scoring assumes that each actor makes the "best" choices in their turn based on the simulation available. """

        def is_target_node(node):
            return isinstance(node, base.EOT) or (node is root_action)
        # store per-turn results from the bottom up.
        realistic_ends_by_node = dict()
        for node in root_action.post_order_nodes():  # bottom up to this action
            # only work with EOT or the root action
            if not is_target_node(node):
                continue
            # by the time this node is reached, the results of all children
            # have been stored under it in realistic_ends (except leaves)
            # so choose the best of the available results and send it
            # up to the next valid node
            try:  # get the results stored previously in the deeper turn
                realistic_ends = realistic_ends_by_node[node]
            except KeyError:  # leaves are own realistic end
                realistic_ends = [node]
            # identify the "best" end for this node
            if node is root_action:
                active = node.parent.active
                passive = node.parent.passive
            else:
                active = node.parent.passive
                passive = node.parent.active
            ends_by_score = dict()
            for realistic_end in realistic_ends:
                # determine the relative score. i.e. if delta is positive
                # then the end result is better for active than passive
                relative_score = self._relative_score(node, realistic_end,
                                                      active, passive)
                ends_by_score[relative_score] = realistic_end
            best_end = ends_by_score[max(ends_by_score.keys())]
            # done after determining realistic result for root action
            if node is root_action:
                return self._summarize_result(root_action, best_end)
            # not done: place best end on the parent EOT's list of possibilities
            parent = node.parent
            while parent:
                if is_target_node(parent):
                    break
                parent = parent.parent  # keep moving up until target found
            # at this point the parent is either root_action or another EOT
            realistic_ends_by_node.setdefault(parent, list()).append(best_end)
        pass