示例#1
0
def detail(request, board_id, dummy_board_slug=None):
    """Return a detail view for the given board.

    Evidence is sorted in order of diagnosticity. Hypotheses are sorted in order of consistency.
    """
    # NOTE: Django's page cache considers full URL including dummy_board_slug. In the future, we may want to adjust
    # the page key to only consider the id and the query parameters.
    # https://docs.djangoproject.com/en/1.10/topics/cache/#the-per-view-cache
    # NOTE: cannot cache page for logged in users b/c comments section contains CSRF and other protection mechanisms.
    view_type = (
        "aggregate"
        if request.GET.get("view_type") is None
        else request.GET["view_type"]
    )

    board = get_object_or_404(Board, pk=board_id)
    permissions = board.permissions.for_user(request.user)

    if "read_board" not in permissions:
        raise PermissionDenied()

    if view_type == "comparison" and not request.user.is_authenticated:
        raise PermissionDenied()

    collaborator_ids = board.collaborator_ids()
    vote_type = request.GET.get(
        "vote_type",
        default=("collab" if request.user.id in collaborator_ids else "all"),
    )

    # calculate aggregate and disagreement for each evidence/hypothesis pair
    all_votes = list(board.evaluation_set.all())
    agg_votes = (
        [x for x in all_votes if x.user_id in collaborator_ids]
        if vote_type == "collab"
        else all_votes
    )

    def _pair_key(evaluation):
        return evaluation.evidence_id, evaluation.hypothesis_id

    keyed = defaultdict(list)
    for vote in agg_votes:
        keyed[_pair_key(vote)].append(Eval(vote.value))
    aggregate = {k: aggregate_vote(v) for k, v in keyed.items()}
    disagreement = {k: calc_disagreement(v) for k, v in keyed.items()}

    user_votes = (
        {_pair_key(v): Eval(v.value) for v in all_votes if v.user_id == request.user.id}
        if request.user.is_authenticated
        else None
    )

    # augment hypotheses and evidence with diagnosticity and consistency
    def _group(first, second, func, key):
        return [(f, func([keyed[key(f, s)] for s in second])) for f in first]

    hypotheses = list(board.hypothesis_set.filter(removed=False))
    evidence = list(board.evidence_set.filter(removed=False))
    hypothesis_consistency = _group(
        hypotheses, evidence, hypothesis_sort_key, key=lambda h, e: (e.id, h.id)
    )
    evidence_diagnosticity = _group(
        evidence, hypotheses, evidence_sort_key, key=lambda e, h: (e.id, h.id)
    )

    return render(
        request,
        "boards/detail.html",
        {
            "board": board,
            "permissions": permissions,
            "evidences": sorted(evidence_diagnosticity, key=lambda e: e[1]),
            "hypotheses": sorted(hypothesis_consistency, key=lambda h: h[1]),
            "view_type": view_type,
            "vote_type": vote_type,
            "votes": aggregate,
            "user_votes": user_votes,
            "disagreement": disagreement,
            "meta_description": board.board_desc,
            "allow_share": not getattr(settings, "ACCOUNT_REQUIRED", False),
            "debug_stats": DEBUG,
        },
    )
示例#2
0
def detail(request, board_id, dummy_board_slug=None):
    """Return a detail view for the given board.

    Evidence is sorted in order of diagnosticity. Hypotheses are sorted in order of consistency.
    """
    # NOTE: Django's page cache considers full URL including dummy_board_slug. In the future, we may want to adjust
    # the page key to only consider the id and the query parameters.
    # https://docs.djangoproject.com/en/1.10/topics/cache/#the-per-view-cache
    # NOTE: cannot cache page for logged in users b/c comments section contains CSRF and other protection mechanisms.
    view_type = 'aggregate' if request.GET.get('view_type') is None else request.GET['view_type']

    board = get_object_or_404(Board, pk=board_id)
    permissions = board.permissions.for_user(request.user)

    if 'read_board' not in permissions:
        raise PermissionDenied()

    if view_type == 'comparison' and not request.user.is_authenticated:
        raise PermissionDenied()

    vote_type = request.GET.get('vote_type', default=(
        'collab'
        # rewrite to avoid unnecessary lookup if key is present?
        if board.permissions.collaborators.filter(pk=request.user.id).exists()
        else 'all'
    ))

    all_votes = list(board.evaluation_set.all())

    # calculate aggregate and disagreement for each evidence/hypothesis pair
    agg_votes = all_votes
    if vote_type == 'collab':
        collaborators = set([c.id for c in board.permissions.collaborators.all()])
        agg_votes = [v for v in all_votes if v.user_id in collaborators]

    def _pair_key(evaluation):
        return evaluation.evidence_id, evaluation.hypothesis_id
    keyed = defaultdict(list)
    for vote in agg_votes:
        keyed[_pair_key(vote)].append(Eval(vote.value))
    aggregate = {k: aggregate_vote(v) for k, v in keyed.items()}
    disagreement = {k: calc_disagreement(v) for k, v in keyed.items()}

    user_votes = (
        {_pair_key(v): Eval(v.value) for v in all_votes if v.user_id == request.user.id}
        if request.user.is_authenticated
        else None
    )

    # augment hypotheses and evidence with diagnosticity and consistency
    def _group(first, second, func, key):
        return [(f, func([keyed[key(f, s)] for s in second])) for f in first]
    hypotheses = list(board.hypothesis_set.filter(removed=False))
    evidence = list(board.evidence_set.filter(removed=False))
    hypothesis_consistency = _group(hypotheses, evidence, hypothesis_sort_key, key=lambda h, e: (e.id, h.id))
    evidence_diagnosticity = _group(evidence, hypotheses, evidence_sort_key, key=lambda e, h: (e.id, h.id))

    context = {
        'board': board,
        'permissions': permissions,
        'evidences': sorted(evidence_diagnosticity, key=lambda e: e[1]),
        'hypotheses': sorted(hypothesis_consistency, key=lambda h: h[1]),
        'view_type': view_type,
        'vote_type': vote_type,
        'votes': aggregate,
        'user_votes': user_votes,
        'disagreement': disagreement,
        'meta_description': board.board_desc,
        'allow_share': not getattr(settings, 'ACCOUNT_REQUIRED', False),
        'debug_stats': DEBUG,
    }
    return render(request, 'boards/detail.html', context)
示例#3
0
 def test_extreme_votes_have_greater_disagreement(self):
     """Test that votes that are further from neutral result in a larger disagreement score."""
     small = [Eval.consistent, Eval.inconsistent]
     large = [Eval.very_inconsistent, Eval.very_consistent]
     self.assertGreater(calc_disagreement(large), calc_disagreement(small))
示例#4
0
 def test_same_vote_has_zero_disagreement(self):
     """Test that calc_disagreement() returns 0.0 when there are only votes of a single type."""
     for vote in Eval:
         self.assertEqual(calc_disagreement([vote, vote]), 0.0)
示例#5
0
 def test_single_vote_has_zero_disagreement(self):
     """Test that calc_disagreement() returns 0.0 when there is a single vote."""
     for vote in Eval:
         self.assertEqual(calc_disagreement([vote]), 0.0)
示例#6
0
 def test_no_votes_returns_none(self):
     """Test that calc_disagreement() returns None when there is no votes"""
     self.assertEqual(calc_disagreement([]), None)