/** * Calculates number of operation intervals which are left till * the end of today. * * @return integer Number of remaining operation intervals */ public function getTodaysRemainingOperationIntervals() { $beginningOfTomorrow = $this->getBeginningOfTomorrow(); $campaignRemainingOperationIntervals = OX_OperationInterval::getIntervalsRemaining($this->aOIDates['start'], $beginningOfTomorrow); return $campaignRemainingOperationIntervals; }
/** * A method to distribute the calculated required campaign impressions between the campaign's * children advertisements. Impression allocation takes in to account ad weight, and the number * of operations intervals the ad will be active in given date/time delivery limitations, and * the pattern of available impressions for the zone(s) the advertisements are linked to. * * The calculated ad impressions are written to the temporary table tmp_ad_required_impression * for later analysis by the {@link OA_Maintenance_Priority_AdServer_Task_AllocateZoneImpressions} * class. * * @param array $aCampaigns An array of {@link OX_Maintenance_Priority_Campaign} objects which require * that their total required impressions be distributed between the * component advertisements. */ function distributeCampaignImpressions($aCampaigns) { // Create an array for storing required ad impressions $aRequiredAdImpressions = array(); // Get the current operation interval start/end dates $aCurrentOperationIntervalDates = OX_OperationInterval::convertDateToOperationIntervalStartAndEndDates($this->_getDate()); // For each campaign foreach ($aCampaigns as $oCampaign) { OA::debug(' - Distributing impression inventory requirements for campaign ID: ' . $oCampaign->id, PEAR_LOG_DEBUG); $adsCount = count($oCampaign->aAds); OA::debug(" - Campaign has {$adsCount} ads.", PEAR_LOG_DEBUG); // Get date object to represent campaign expiration date if ($oCampaign->impressionTargetDaily > 0 || $oCampaign->clickTargetDaily > 0 || $oCampaign->conversionTargetDaily > 0) { // The campaign has a daily target to meet, so treat the // campaign as if it expires at the end of "today", regardless // of the existance of any activation or expiration dates that // may (or may not) be set for the campaign $oCampaignExpiryDate = new Date($this->_getDate()); $oCampaignExpiryDate->setTZ($this->currentTz); $oCampaignExpiryDate->setHour(23); $oCampaignExpiryDate->setMinute(59); $oCampaignExpiryDate->setSecond(59); $oCampaignExpiryDate->toUTC(); // Unless the campaign has an expiry date and it happens before the end of today if (!empty($oCampaign->expireTime)) { if ($oCampaignExpiryDate->after($this->_getDate($oCampaign->expireTime))) { $oCampaignExpiryDate = $this->_getDate($oCampaign->expireTime); } } } else { if (!empty($oCampaign->expireTime) && ($oCampaign->impressionTargetTotal > 0 || $oCampaign->clickTargetTotal > 0 || $oCampaign->conversionTargetTotal > 0)) { // The campaign has an expiration date, and has some kind of // (total) inventory requirement, so treat the campaign as if // it expires at the expiration date/time $oCampaignExpiryDate = $this->_getDate($oCampaign->expireTime); } else { // Error! There should not be any other kind of high-priority // campaign in terms of activation/expiration dates and // either (total) inventory requirements or daily targets $message = "- Error calculating the end date for Campaign ID {$oCampaign->id}"; OA::debug($message, PEAR_LOG_ERR); continue; } } // Determine number of remaining operation intervals for campaign $message = " - Calculating campaign remaining operation intervals."; OA::debug($message, PEAR_LOG_DEBUG); $campaignRemainingOperationIntervals = OX_OperationInterval::getIntervalsRemaining($aCurrentOperationIntervalDates['start'], $oCampaignExpiryDate); // For all ads in the campaign, determine: // - If the ad is capable of delivery in the current operation // interval, or not, based on if it is linked to any zones, and, // if so: // - If the ad is capable of delivery in the current operation // interval, or not, based on delivery limitation(s), and if so; // - The result of the weight of the ad multiplied by the // number of operation intervals remaining in which the ad // is capable of delivering $aAdZones = array(); $aAdDeliveryLimitations = array(); $aAdBlockedForCurrentOI = array(); $aAdWeightRemainingOperationIntervals = array(); $aInvalidAdIds = array(); reset($oCampaign->aAds); while (list($key, $oAd) = each($oCampaign->aAds)) { // Only calculate values for active ads if ($oAd->active && $oAd->weight > 0) { $message = " - Calculating remaining operation intervals for ad ID: {$oAd->id}"; OA::debug($message, PEAR_LOG_DEBUG); // Get all zones associated with the ad $aAdsZones = $this->oDal->getAdZoneAssociationsByAds(array($oAd->id)); $aAdZones[$oAd->id] = @$aAdsZones[$oAd->id]; if (is_null($aAdZones[$oAd->id])) { $aInvalidAdIds[] = $oAd->id; $message = " - Ad ID {$oAd->id} has no linked zones, will skip..."; OA::debug($message, PEAR_LOG_ERR); continue; } // Prepare a delivery limitation object for the ad $aAdDeliveryLimitations[$oAd->id] = new OA_Maintenance_Priority_DeliveryLimitation($oAd->getDeliveryLimitations()); // Is the ad blocked from delivering in the current operation interval? $aAdBlockedForCurrentOI[$oAd->id] = $aAdDeliveryLimitations[$oAd->id]->deliveryBlocked($aCurrentOperationIntervalDates['start']); // Determine how many operation intervals remain that the ad can deliver in $adRemainingOperationIntervals = $aAdDeliveryLimitations[$oAd->id]->getActiveAdOperationIntervals($campaignRemainingOperationIntervals, $aCurrentOperationIntervalDates['start'], $oCampaignExpiryDate); // Determine the value of the ad weight multiplied by the number // of operation intervals remaining that the ad can deliver in if ($oAd->weight > 0) { $aAdWeightRemainingOperationIntervals[$oAd->id] = $oAd->weight * $adRemainingOperationIntervals; } else { $aAdWeightRemainingOperationIntervals[$oAd->id] = 0; } } } // Get the total sum of the ad weight * remaining OI values $sumAdWeightRemainingOperationIntervals = array_sum($aAdWeightRemainingOperationIntervals); // For each (active) ad that is capable of delivering in the current // operation interval, determine how many of the campaign's required // impressions should be alloced as the ad's required impressions // For each advertisement reset($oCampaign->aAds); while (list($key, $oAd) = each($oCampaign->aAds)) { if (in_array($oAd->id, $aInvalidAdIds)) { OA::debug(' - Skipping ad ID: ' . $oAd->id, PEAR_LOG_DEBUG); continue; } OA::debug(' - Calculating required impressions for ad ID: ' . $oAd->id, PEAR_LOG_DEBUG); // Get impressions required $totalRequiredAdImpressions = 0; if ($oAd->active && $oAd->weight > 0 && $aAdBlockedForCurrentOI[$oAd->id] !== true) { $totalRequiredAdImpressions = $oCampaign->requiredImpressions * ($aAdWeightRemainingOperationIntervals[$oAd->id] / $sumAdWeightRemainingOperationIntervals); } if ($totalRequiredAdImpressions <= 0) { OA::debug(' - No required impressions for ad ID: ' . $oAd->id, PEAR_LOG_DEBUG); continue; } // Based on the average zone pattern of the zones the ad is // linked to, calculate how many of these impressions should // be delivered in the next operation interval OA::debug(' - Calculating next OI required impressions for ad ID: ' . $oAd->id, PEAR_LOG_DEBUG); $oAd->requiredImpressions = $this->_getAdImpressions($oAd, $totalRequiredAdImpressions, $aCurrentOperationIntervalDates['start'], $oCampaignExpiryDate, $aAdDeliveryLimitations[$oAd->id], $aAdZones[$oAd->id]); $aRequiredAdImpressions[] = array('ad_id' => $oAd->id, 'required_impressions' => $oAd->requiredImpressions); } } // Save the required impressions into the temporary database table OA::setTempDebugPrefix('- '); // Check if table exists if (!isset($GLOBALS['_OA']['DB_TABLES']['tmp_ad_required_impression'])) { if ($this->oTable->createTable('tmp_ad_required_impression', null, true) !== false) { // Remember that table was created $GLOBALS['_OA']['DB_TABLES']['tmp_ad_required_impression'] = true; } } $this->oDal->saveRequiredAdImpressions($aRequiredAdImpressions); }
/** * A method to test the _getAdImpressions() method. * * Test 1: Test with invalid parameters, and ensure that zero impressions are * allocated. * Test 2: Test with an advertisement that is currently blocked, and ensure * that zero impressions are allocated. * Test 3: Test with an advertisement that is not currently blocked, but with * no impressions in the cumulative zone forecast, and ensure that * zero impressions are allocated. * Test 4: Test with a simple, single operation interval cumulative zone forecast, * and a blocking delivery limitation, and ensure that the correct number * of impressions are allocated. * Test 5: Test with a simple, even operation interval cumulative zone forecast, * and a blocking delivery limitation, and ensure that the correct number * of impressions are allocated. * Test 6: Test with an uneven operation interval cumulative zone forecast, and * a blocking delivery limitation, and ensure that the correct number of * impressions are allocated. */ function test_getAdImpressions() { $aConf =& $GLOBALS['_MAX']['CONF']; $aConf['maintenance']['operationInterval'] = 60; Mock::generatePartial('OA_Maintenance_Priority_Ad', 'PartialMockOA_Maintenance_Priority_Ad', array('getDeliveryLimitations')); Mock::generatePartial('OA_Maintenance_Priority_AdServer_Task_GetRequiredAdImpressionsLifetime', 'PartialMockOA_Maintenance_Priority_AdServer_Task_GetRequiredAdImpressionsLifetime', array('_getCumulativeZoneForecast')); // Test 1 $oAd = new OA_Maintenance_Priority_Ad(array('ad_id' => 1, 'weight' => 1, 'status' => OA_ENTITY_STATUS_RUNNING, 'type' => 'sql')); $totalRequiredAdImpressions = 10; $oDate = new Date(); $oCampaignExpiryDate = new Date(); $oGetRequiredAdImpressionsLifetime =& $this->_getCurrentTask(); $oDeliveryLimitaions = new OA_Maintenance_Priority_DeliveryLimitation(null); $aAdZones = array(); $result = $oGetRequiredAdImpressionsLifetime->_getAdImpressions('foo', $totalRequiredAdImpressions, $oDate, $oCampaignExpiryDate, $oDeliveryLimitaions, $aAdZones); $this->assertEqual($result, 0); $result = $oGetRequiredAdImpressionsLifetime->_getAdImpressions($oAd, 'foo', $oDate, $oCampaignExpiryDate, $oDeliveryLimitaions, $aAdZones); $this->assertEqual($result, 0); $result = $oGetRequiredAdImpressionsLifetime->_getAdImpressions($oAd, $totalRequiredAdImpressions, 'foo', $oCampaignExpiryDate, $oDeliveryLimitaions, $aAdZones); $this->assertEqual($result, 0); $result = $oGetRequiredAdImpressionsLifetime->_getAdImpressions($oAd, $totalRequiredAdImpressions, $oDate, 'foo', $oDeliveryLimitaions, $aAdZones); $this->assertEqual($result, 0); $result = $oGetRequiredAdImpressionsLifetime->_getAdImpressions($oAd, $totalRequiredAdImpressions, $oDate, $oCampaignExpiryDate, 'foo', $aAdZones); $this->assertEqual($result, 0); $result = $oGetRequiredAdImpressionsLifetime->_getAdImpressions($oAd, $totalRequiredAdImpressions, $oDate, $oCampaignExpiryDate, $oDeliveryLimitaions, 'foo'); $this->assertEqual($result, 0); // Test 2 $oAd = new PartialMockOA_Maintenance_Priority_Ad($this); $aParam = array('ad_id' => 1, 'weight' => 1, 'status' => OA_ENTITY_STATUS_RUNNING, 'type' => 'sql'); $oAd->setReturnValue('getDeliveryLimitations', array(array('ad_id' => 1, 'logical' => 'and', 'type' => 'deliveryLimitations:Time:Hour', 'comparison' => '!~', 'data' => '12', 'executionorder' => 0))); $oAd->OA_Maintenance_Priority_Ad($aParam); $totalRequiredAdImpressions = 120; $oDate = new Date('2006-02-15 12:07:01'); $oCampaignExpiryDate = new Date('2006-12-15 23:59:59'); $oGetRequiredAdImpressionsLifetime =& $this->_getCurrentTask(); $oDeliveryLimitaions = new OA_Maintenance_Priority_DeliveryLimitation($oAd->getDeliveryLimitations()); $aAdZones = array(array('zone_id' => 1)); $result = $oGetRequiredAdImpressionsLifetime->_getAdImpressions($oAd, $totalRequiredAdImpressions, $oDate, $oCampaignExpiryDate, $oDeliveryLimitaions, $aAdZones); $this->assertEqual($result, 0); // Test 3 $oAd = new PartialMockOA_Maintenance_Priority_Ad($this); $aParam = array('ad_id' => 1, 'weight' => 1, 'status' => OA_ENTITY_STATUS_RUNNING, 'type' => 'sql'); $oAd->setReturnValue('getDeliveryLimitations', array(array('ad_id' => 1, 'logical' => 'and', 'type' => 'deliveryLimitations:Time:Hour', 'comparison' => '!~', 'data' => '15', 'executionorder' => 0))); $oAd->OA_Maintenance_Priority_Ad($aParam); $totalRequiredAdImpressions = 110; $oDate = new Date('2006-02-15 12:07:01'); $oCampaignExpiryDate = new Date('2006-02-15 23:59:59'); $oGetRequiredAdImpressionsLifetime = new PartialMockOA_Maintenance_Priority_AdServer_Task_GetRequiredAdImpressionsLifetime($this); $oGetRequiredAdImpressionsLifetime->setReturnValue('_getCumulativeZoneForecast', array()); $oGetRequiredAdImpressionsLifetime->OA_Maintenance_Priority_AdServer_Task_GetRequiredAdImpressionsLifetime(); $oDeliveryLimitaions = new OA_Maintenance_Priority_DeliveryLimitation($oAd->getDeliveryLimitations()); $aAdZones = array(array('zone_id' => 1)); $result = $oGetRequiredAdImpressionsLifetime->_getAdImpressions($oAd, $totalRequiredAdImpressions, $oDate, $oCampaignExpiryDate, $oDeliveryLimitaions, $aAdZones); $this->assertEqual($result, 0); // Test 4 $oAd = new PartialMockOA_Maintenance_Priority_Ad($this); $aParam = array('ad_id' => 1, 'weight' => 1, 'status' => OA_ENTITY_STATUS_RUNNING, 'type' => 'sql'); $oAd->setReturnValue('getDeliveryLimitations', array(array('ad_id' => 1, 'logical' => 'and', 'type' => 'deliveryLimitations:Time:Hour', 'comparison' => '!~', 'data' => '15', 'executionorder' => 0))); $oAd->OA_Maintenance_Priority_Ad($aParam); $totalRequiredAdImpressions = 110; $oDate = new Date('2006-02-15 12:07:01'); $oCampaignExpiryDate = new Date('2006-02-15 23:59:59'); $oGetRequiredAdImpressionsLifetime = new PartialMockOA_Maintenance_Priority_AdServer_Task_GetRequiredAdImpressionsLifetime($this); $aCumulativeZoneForecast = array(); $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 12:00:01')); $aCumulativeZoneForecast[$intervalID] = 50; $aCumulativeZoneForecast = $this->_fillForecastArray($aCumulativeZoneForecast); $oGetRequiredAdImpressionsLifetime->setReturnValue('_getCumulativeZoneForecast', $aCumulativeZoneForecast); $oGetRequiredAdImpressionsLifetime->OA_Maintenance_Priority_AdServer_Task_GetRequiredAdImpressionsLifetime(); $oDeliveryLimitaions = new OA_Maintenance_Priority_DeliveryLimitation($oAd->getDeliveryLimitations()); $remainingOIs = OX_OperationInterval::getIntervalsRemaining($oDate, $oCampaignExpiryDate); $oDeliveryLimitaions->getActiveAdOperationIntervals($remainingOIs, $oDate, $oCampaignExpiryDate); $aAdZones = array(array('zone_id' => 1)); $result = $oGetRequiredAdImpressionsLifetime->_getAdImpressions($oAd, $totalRequiredAdImpressions, $oDate, $oCampaignExpiryDate, $oDeliveryLimitaions, $aAdZones); $this->assertEqual($result, 110); // Test 5 $oAd = new PartialMockOA_Maintenance_Priority_Ad($this); $aParam = array('ad_id' => 1, 'weight' => 1, 'status' => OA_ENTITY_STATUS_RUNNING, 'type' => 'sql'); $oAd->setReturnValue('getDeliveryLimitations', array(array('ad_id' => 1, 'logical' => 'and', 'type' => 'deliveryLimitations:Time:Hour', 'comparison' => '!~', 'data' => '15', 'executionorder' => 0))); $oAd->OA_Maintenance_Priority_Ad($aParam); $totalRequiredAdImpressions = 110; $oDate = new Date('2006-02-15 12:07:01'); $oCampaignExpiryDate = new Date('2006-02-15 23:59:59'); $oGetRequiredAdImpressionsLifetime = new PartialMockOA_Maintenance_Priority_AdServer_Task_GetRequiredAdImpressionsLifetime($this); $aCumulativeZoneForecast = array(); $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 12:00:01')); $aCumulativeZoneForecast[$intervalID] = 50; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 13:00:01')); $aCumulativeZoneForecast[$intervalID] = 50; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 14:00:01')); $aCumulativeZoneForecast[$intervalID] = 50; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 15:00:01')); $aCumulativeZoneForecast[$intervalID] = 50; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 16:00:01')); $aCumulativeZoneForecast[$intervalID] = 50; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 17:00:01')); $aCumulativeZoneForecast[$intervalID] = 50; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 18:00:01')); $aCumulativeZoneForecast[$intervalID] = 50; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 19:00:01')); $aCumulativeZoneForecast[$intervalID] = 50; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 20:00:01')); $aCumulativeZoneForecast[$intervalID] = 50; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 21:00:01')); $aCumulativeZoneForecast[$intervalID] = 50; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 22:00:01')); $aCumulativeZoneForecast[$intervalID] = 50; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 23:00:01')); $aCumulativeZoneForecast[$intervalID] = 50; $aCumulativeZoneForecast = $this->_fillForecastArray($aCumulativeZoneForecast); $oGetRequiredAdImpressionsLifetime->setReturnValue('_getCumulativeZoneForecast', $aCumulativeZoneForecast); $oGetRequiredAdImpressionsLifetime->OA_Maintenance_Priority_AdServer_Task_GetRequiredAdImpressionsLifetime(); $oDeliveryLimitaions = new OA_Maintenance_Priority_DeliveryLimitation($oAd->getDeliveryLimitations()); $remainingOIs = OX_OperationInterval::getIntervalsRemaining($oDate, $oCampaignExpiryDate); $oDeliveryLimitaions->getActiveAdOperationIntervals($remainingOIs, $oDate, $oCampaignExpiryDate); $aAdZones = array(array('zone_id' => 1)); $result = $oGetRequiredAdImpressionsLifetime->_getAdImpressions($oAd, $totalRequiredAdImpressions, $oDate, $oCampaignExpiryDate, $oDeliveryLimitaions, $aAdZones); $this->assertEqual($result, 10); // Test 6 $oAd = new PartialMockOA_Maintenance_Priority_Ad($this); $aParam = array('ad_id' => 1, 'weight' => 1, 'status' => OA_ENTITY_STATUS_RUNNING, 'type' => 'sql'); $oAd->setReturnValue('getDeliveryLimitations', array(array('ad_id' => 1, 'logical' => 'and', 'type' => 'deliveryLimitations:Time:Hour', 'comparison' => '!~', 'data' => '15', 'executionorder' => 0))); $oAd->OA_Maintenance_Priority_Ad($aParam); $totalRequiredAdImpressions = 110; $oDate = new Date('2006-02-15 12:07:01'); $oCampaignExpiryDate = new Date('2006-02-15 23:59:59'); $oGetRequiredAdImpressionsLifetime = new PartialMockOA_Maintenance_Priority_AdServer_Task_GetRequiredAdImpressionsLifetime($this); $aCumulativeZoneForecast = array(); $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 12:00:01')); $aCumulativeZoneForecast[$intervalID] = 10; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 13:00:01')); $aCumulativeZoneForecast[$intervalID] = 20; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 14:00:01')); $aCumulativeZoneForecast[$intervalID] = 30; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 15:00:01')); $aCumulativeZoneForecast[$intervalID] = 40; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 16:00:01')); $aCumulativeZoneForecast[$intervalID] = 50; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 17:00:01')); $aCumulativeZoneForecast[$intervalID] = 60; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 18:00:01')); $aCumulativeZoneForecast[$intervalID] = 50; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 19:00:01')); $aCumulativeZoneForecast[$intervalID] = 40; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 20:00:01')); $aCumulativeZoneForecast[$intervalID] = 30; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 21:00:01')); $aCumulativeZoneForecast[$intervalID] = 20; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 22:00:01')); $aCumulativeZoneForecast[$intervalID] = 10; $intervalID = OX_OperationInterval::convertDateToOperationIntervalID(new Date('2006-02-15 23:00:01')); $aCumulativeZoneForecast[$intervalID] = 10; $aCumulativeZoneForecast = $this->_fillForecastArray($aCumulativeZoneForecast); $oGetRequiredAdImpressionsLifetime->setReturnValue('_getCumulativeZoneForecast', $aCumulativeZoneForecast); $oGetRequiredAdImpressionsLifetime->OA_Maintenance_Priority_AdServer_Task_GetRequiredAdImpressionsLifetime(); $oDeliveryLimitaions = new OA_Maintenance_Priority_DeliveryLimitation($oAd->getDeliveryLimitations()); $remainingOIs = OX_OperationInterval::getIntervalsRemaining($oDate, $oCampaignExpiryDate); $oDeliveryLimitaions->getActiveAdOperationIntervals($remainingOIs, $oDate, $oCampaignExpiryDate); $aAdZones = array(array('zone_id' => 1)); $result = $oGetRequiredAdImpressionsLifetime->_getAdImpressions($oAd, $totalRequiredAdImpressions, $oDate, $oCampaignExpiryDate, $oDeliveryLimitaions, $aAdZones); $this->assertEqual($result, 3); TestEnv::restoreConfig(); }