예제 #1
0
    def test_event(self):
        # Test event add.
        for i in range(300):
            yield db_utils.update_event({
                "event_id": str(i),
                "event_type": stats_consts.EVENT_TYPE_CLICK,
                "timestamp": 0,
                "user_id": str(i % 20),
                "banner_id": '1',
                "campaign_id": "campaign_id",
                "event_value": 10,
                "our_keywords": {},
                "human_score": 1
            })

        # Test event select.
        counter = 0
        event_iter = yield db_utils.get_events_per_user_iter(
            campaign_id="campaign_id", timestamp=0, uid=u'0')
        while True:
            event_doc = yield event_iter.next()
            if not event_doc:
                break

            self.assertEqual(event_doc['user_id'], u'0')
            self.assertEqual(event_doc['timestamp'], 0)
            self.assertEqual(event_doc['campaign_id'], "campaign_id")
            counter += 1

        self.assertEqual(counter, 15)

        unique_uids = yield db_utils.get_distinct_users_from_events(
            "campaign_id", timestamp=0)
        self.assertEqual(set(unique_uids), set([str(x) for x in range(20)]))

        # Test event deletion.
        for i in range(300):
            yield db_utils.delete_event(str(i))

        counter = 0
        event_iter = yield db_utils.get_events_per_user_iter("campaign_id",
                                                             timestamp=0,
                                                             uid=u'0')
        while True:
            event_doc = yield event_iter.next()
            if not event_doc:
                break
            counter += 1
        self.assertEqual(counter, 0)
예제 #2
0
def create_user_budget(campaign_doc, timestamp, uid):
    """
    Calculate individual user budgets.

    User budget dictionary default values for each event type are:

        {
        'default_value': 0.0,  # Default value for this event type
        'event_value': 0.0,    # Calculated event value (used later on)
        'num': 0,              # Number of events of this time in the time period
        'share': 0.0           # Share of this user for this event type in the time period
        }

    :param campaign_doc: Campaign document
    :param timestamp: Timestamp (last hour)
    :param uid:
    :return: User budget dictionary
    """
    logger = logging.getLogger(__name__)

    user_budget = defaultdict(
        lambda: dict(default_value=0, event_value=0.0, num=0, share=0.0))

    if campaign_doc is None:
        defer.returnValue(user_budget)

    user_events_iter = yield db_utils.get_events_per_user_iter(
        campaign_doc['campaign_id'], timestamp, uid)
    while True:
        event_doc = yield user_events_iter.next()
        if not event_doc:
            break

        event_type = event_doc['event_type']

        banner_doc = yield db_utils.get_banner(event_doc['banner_id'])
        if not filter_event(
                event_doc, campaign_doc,
                banner_doc) and event_type in stats_consts.PAID_EVENT_TYPES:

            user_budget[event_type]['num'] += 1
            user_budget[event_type][
                'default_value'] += get_default_event_payment(
                    event_doc, campaign_doc['max_cpc'],
                    campaign_doc['max_cpm'])
        else:
            logger.warning('Event type for event_id: ' +
                           event_doc['event_id'] +
                           ' not included in payment calculation.')

    for event_type in stats_consts.PAID_EVENT_TYPES:
        if user_budget[event_type]['num'] > 0:
            user_budget[event_type]['default_value'] /= user_budget[
                event_type]['num']

    yield logger.debug(user_budget)
    defer.returnValue(user_budget)
예제 #3
0
def get_best_user_payments_and_humanity(campaign_doc, timestamp, uid):
    """
    Return user information: best payment, total payment and max human score.

    :param campaign_doc:
    :param timestamp:
    :param uid:
    :return: Tuple: max_user_payment, max_human_score, total_user_payments
    """
    logger = logging.getLogger(__name__)
    max_user_payment, max_human_score = 0.0, 0.0

    total_user_payments = defaultdict(lambda: float(0.0))

    user_value_doc = yield db_utils.get_user_value_in_campaign(
        campaign_doc['campaign_id'], uid)
    if user_value_doc:
        max_user_payment = float(user_value_doc['payment'])

    user_events_iter = yield db_utils.get_events_per_user_iter(
        campaign_doc['campaign_id'], timestamp, uid)
    while True:
        event_doc = yield user_events_iter.next()
        if not event_doc:
            break

        event_type = event_doc['event_type']

        banner_doc = yield db_utils.get_banner(event_doc['banner_id'])
        if not stats_utils.filter_event(
                event_doc, campaign_doc,
                banner_doc) and event_type in stats_consts.PAID_EVENT_TYPES:
            event_payment = stats_utils.get_default_event_payment(
                event_doc, campaign_doc['max_cpc'], campaign_doc['max_cpm'])

            total_user_payments[event_type] += float(event_payment)

            max_user_payment = max([max_user_payment, event_payment])
            max_human_score = max([max_human_score, event_doc['human_score']])

    yield logger.info(
        "User {0} max_user_payment, max_human_score, total_user_payments: {1}".
        format(uid, (max_user_payment, max_human_score, total_user_payments)))
    defer.returnValue((max_user_payment, max_human_score, total_user_payments))
예제 #4
0
def calculate_payments_for_new_users(campaign_doc, timestamp):
    """
    Calculate payments for new uses. Use CPM as default payment.

    :param campaign_doc:
    :param timestamp:
    :return:
    """
    logger = logging.getLogger(__name__)
    yield logger.info("Calculating payment score for new user.")

    # For new users add payments as cpv
    uids = yield db_utils.get_distinct_users_from_events(
        campaign_doc['campaign_id'], timestamp)

    yield logger.debug("Found {0} distinct user ids".format(len(uids)))

    for uid in uids:
        max_human_score = 0

        user_events_iter = yield db_utils.get_events_per_user_iter(
            campaign_doc['campaign_id'], timestamp, uid)

        while True:
            event_doc = yield user_events_iter.next()
            if not event_doc:
                break

            banner_doc = yield db_utils.get_banner(event_doc['banner_id'])
            if not stats_utils.filter_event(event_doc, campaign_doc,
                                            banner_doc):
                max_human_score = max(
                    [max_human_score, event_doc['human_score']])

        user_value_doc = yield db_utils.get_user_value_in_campaign(
            campaign_doc['campaign_id'], uid)

        if user_value_doc is None or user_value_doc['payment'] <= campaign_doc[
                'max_cpm']:
            yield logger.info("Updating user value for {0}".format(uid))
            yield db_utils.update_user_value_in_campaign(
                campaign_doc['campaign_id'], uid, campaign_doc['max_cpm'],
                max_human_score)
예제 #5
0
def update_events_payments(campaign_doc, timestamp, uid, user_budget):
    """
    Update or create event payments in the database by dividing user budget among events.

    :param campaign_doc: Campaign document
    :param timestamp: Timestamp for the time period of calculation
    :param uid: User identifier
    :param user_budget: User budget
    :return:
    """
    logger = logging.getLogger(__name__)

    # Get all events for chosen campaign within chosen time period for a chosen user
    user_events_iter = yield db_utils.get_events_per_user_iter(
        campaign_doc['campaign_id'], timestamp, uid)
    while True:
        event_doc = yield user_events_iter.next()
        if event_doc is None:
            break

        event_type = event_doc['event_type']

        banner_doc = yield db_utils.get_banner(event_doc['banner_id'])

        payment_reason = filter_event(event_doc, campaign_doc, banner_doc)

        # Pay when not rejected
        if not payment_reason and event_type in stats_consts.PAID_EVENT_TYPES:
            event_value = int(user_budget[event_type]['event_value'])
        else:
            event_value = 0

        # Save to database
        yield db_utils.update_event_payment(campaign_doc['campaign_id'],
                                            timestamp, event_doc['event_id'],
                                            event_value, payment_reason)

        yield logger.debug("New payment ({0}, {1}): {2}, {3}. {4}, {5}".format(
            campaign_doc['campaign_id'], timestamp, event_doc['event_id'],
            event_type, event_value, payment_reason))