Exemplo n.º 1
0
def save_insight(
    insight_id: str,
    annotation: int,
    update: bool = True,
    data: Optional[Dict] = None,
    auth: Optional[OFFAuthentication] = None,
) -> AnnotationResult:
    try:
        insight: Union[ProductInsight,
                       None] = ProductInsight.get_by_id(insight_id)
    except ProductInsight.DoesNotExist:
        insight = None

    if not insight:
        return UNKNOWN_INSIGHT_RESULT

    if insight.annotation is not None:
        return ALREADY_ANNOTATED_RESULT

    annotator = InsightAnnotatorFactory.get(insight.type)
    return annotator.annotate(insight,
                              annotation,
                              update,
                              data=data,
                              auth=auth)
Exemplo n.º 2
0
    def on_get(self, req: falcon.Request, resp: falcon.Response, insight_id: str):
        try:
            insight: ProductInsight = ProductInsight.get_by_id(insight_id)
        except ProductInsight.DoesNotExist:
            raise falcon.HTTPNotFound()

        resp.media = insight.to_dict()
Exemplo n.º 3
0
def save_insight(insight_id: str, annotation: int, update: bool = True) \
        -> AnnotationResult:
    try:
        insight: Union[ProductInsight, None] \
            = ProductInsight.get_by_id(insight_id)
    except ProductInsight.DoesNotExist:
        insight = None

    if not insight:
        return UNKNOWN_INSIGHT_RESULT

    if insight.annotation is not None:
        return ALREADY_ANNOTATED_RESULT

    annotator = InsightAnnotatorFactory.get(insight.type)
    return annotator.annotate(insight, annotation, update)
Exemplo n.º 4
0
def save_annotation(
    insight_id: str,
    annotation: int,
    device_id: str,
    update: bool = True,
    data: Optional[Dict] = None,
    auth: Optional[OFFAuthentication] = None,
    trusted_annotator: bool = False,
) -> AnnotationResult:
    """Saves annotation either by using a single response as ground truth or by using several responses.

    trusted_annotator: defines whether the given annotation comes from an authoritative source (e.g.
    a trusted user), ot whether the annotation should be subject to the voting system.
    """
    try:
        insight: Union[ProductInsight,
                       None] = ProductInsight.get_by_id(insight_id)
    except ProductInsight.DoesNotExist:
        insight = None

    if not insight:
        return UNKNOWN_INSIGHT_RESULT

    if insight.annotation is not None:
        return ALREADY_ANNOTATED_RESULT

    if not trusted_annotator:
        verified: bool = False

        AnnotationVote.create(
            insight_id=insight_id,
            username=auth.get_username() if auth else None,
            value=annotation,
            device_id=device_id,
        )

        with db.atomic() as tx:
            try:
                existing_votes = list(
                    AnnotationVote.select(
                        AnnotationVote.value,
                        peewee.fn.COUNT(
                            AnnotationVote.value).alias("num_votes"),
                    ).where(AnnotationVote.insight_id == insight_id).group_by(
                        AnnotationVote.value).order_by(
                            peewee.SQL("num_votes").desc()))
                insight.n_votes = functools.reduce(
                    lambda sum, row: sum + row.num_votes, existing_votes, 0)
                insight.save()
            except Exception as e:
                tx.rollback()
                raise e

        # If the top annotation has more than 2 votes, consider applying it to the insight.
        if existing_votes[0].num_votes > 2:
            annotation = existing_votes[0].value
            verified = True

        # But first check for the following cases:
        #  1) The 1st place annotation has >2 votes, and the 2nd place annotation has >= 2 votes.
        #  2) 1st place and 2nd place have 2 votes each.
        #
        # In both cases, we consider this an ambiguous result and mark it with 'I don't know'.
        if (existing_votes[0].num_votes >= 2 and len(existing_votes) > 1
                and existing_votes[1].num_votes >= 2):
            # This code credits the last person to contribute a vote with a potentially not their annotation.
            annotation = 0
            verified = True

        if not verified:
            return SAVED_ANNOTATION_VOTE_RESULT

    annotator = InsightAnnotatorFactory.get(insight.type)
    result = annotator.annotate(insight,
                                annotation,
                                update,
                                data=data,
                                auth=auth)
    username = auth.get_username() if auth else "unknown annotator"
    events.event_processor.send_async("question_answered", username, device_id,
                                      insight.barcode)
    return result