/** * A private method to convert the ZIF update type from _getUpdateTypeRequired() into * a range of operation intervals where all zones require their ZIF values to be updated. * * @access private * @param mixed $type The update type required. Possible values are the same as * those returned from the * {@link OA_Maintenance_Priority_AdServer_Task_ForecastZoneImpressions::getUpdateTypeRequired()} * method. * @return array An array of hashes where keys are operation interval IDs, and * values are PEAR Dates. One element in the array indicates a * contiguous range, two elements indicate a non-contiguous range. */ function _getOperationIntervalRanges($type) { // Initialise result array $aResult = array(); switch (true) { case is_bool($type) && $type === false: // Update none, return an empty array return $aResult; case is_bool($type) && $type === true: // Update all - need one week's worth of operation intervals up until the end // of the operation interval *after* the one that statistics have been updated // to, as we need to predict one interval ahead of now $oStatsDates = OX_OperationInterval::convertDateToNextOperationIntervalStartAndEndDates($this->oDateNow); $oStartDate = new Date(); $oStartDate->copy($oStatsDates['start']); $oStartDate->subtractSeconds(SECONDS_PER_WEEK); $startId = OX_OperationInterval::convertDateToOperationIntervalID($oStartDate); $totalIntervals = OX_OperationInterval::operationIntervalsPerWeek(); break; case is_array($type) && $type[0] < $type[1]: // A contiguous (ie. inter-week) range, where the first operation interval // ID is the lower bound, and the second operation interval ID is the upper // The start operation interval ID is the operation interval ID right after // the operation interval ID that priority was updated to (ie. $type[0]) $aDates = OX_OperationInterval::convertDateToNextOperationIntervalStartAndEndDates($this->oPriorityUpdatedToDate); $oStartDate = $aDates['start']; $startId = OX_OperationInterval::nextOperationIntervalID($type[0], 1); $totalIntervals = $type[1] - $type[0]; break; case is_array($type) && $type[0] > $type[1]: // A non-contiguous range, so calculate as above, but use the first operation // interval ID as the upper bound, and the second operation interval ID as the // lower bound in the proceeding week // The start operation interval ID is the operation interval ID right after // the operation interval ID that priority was updated to (ie. $type[0]) $aDates = OX_OperationInterval::convertDateToNextOperationIntervalStartAndEndDates($this->oPriorityUpdatedToDate); $oStartDate = $aDates['start']; $startId = OX_OperationInterval::nextOperationIntervalID($type[0], 1); $totalIntervals = OX_OperationInterval::operationIntervalsPerWeek() - $type[0] + $type[1]; break; default: OA::debug('OA_Maintenance_Priority_AdServer_Task_ForecastZoneImpressions::getOperationIntRangeByType() called with unexpected type, exiting', PEAR_LOG_CRIT); exit; } // Build the update range array $aRange = array(); $totalIntervalPerWeek = OX_OperationInterval::operationIntervalsPerWeek(); for ($x = $startId, $y = 0; $y < $totalIntervals; $x++, $y++) { if ($x == $totalIntervalPerWeek) { $x = 0; } $aDates = array(); $aDates['start'] = new Date($oStartDate); //->format('%Y-%m-%d %H:%M:%S'); $oEndDate = new Date(); $oEndDate->copy($oStartDate); $oEndDate->addSeconds(OX_OperationInterval::secondsPerOperationInterval() - 1); $aDates['end'] = $oEndDate; //->format('%Y-%m-%d %H:%M:%S'); unset($oEndDate); $aRange[$x] = $aDates; $oStartDate->addSeconds(OX_OperationInterval::secondsPerOperationInterval()); } // Is the update range array a contiguous (inter-weeek) range? if (array_key_exists($totalIntervalPerWeek - 1, $aRange) && array_key_exists(0, $aRange)) { // The range contains the first and the last operation interval IDs, is the // last date before the first date? $oFirstIntervalStartDate = new Date($aRange[0]['start']); $oLastIntervalStartDate = new Date($aRange[$totalIntervalPerWeek - 1]['start']); if ($oLastIntervalStartDate->before($oFirstIntervalStartDate)) { // It's a non-contiguous range, so split into two ranges $aRange1 = array(); $aRange2 = array(); for ($x = $startId; $x < $totalIntervalPerWeek; $x++) { $aRange1[$x] = $aRange[$x]; } for ($x = 0; $x < $startId; $x++) { if (isset($aRange[$x])) { $aRange2[$x] = $aRange[$x]; } } $aResult[] = $aRange1; $aResult[] = $aRange2; return $aResult; } } $aResult[] = $aRange; return $aResult; }
/** * A method to test the convertDateToNextOperationIntervalStartAndEndDates() method. */ function testConvertDateToNextOperationIntervalStartAndEndDates() { // Test a date in the first operation interval ID in the week before the test was // written, using a default operation interval of 60 minutes $date = new Date('2004-08-08 00:40:00'); $aDates = OX_OperationInterval::convertDateToNextOperationIntervalStartAndEndDates($date, 60); $this->assertEqual($aDates['start'], new Date('2004-08-08 01:00:00')); $this->assertEqual($aDates['end'], new Date('2004-08-08 01:59:59')); // Test the same date, but with an operation interval of 30 minutes $aDates = OX_OperationInterval::convertDateToNextOperationIntervalStartAndEndDates($date, 30); $this->assertEqual($aDates['start'], new Date('2004-08-08 01:00:00')); $this->assertEqual($aDates['end'], new Date('2004-08-08 01:29:59')); }
/** * A method for obtaining the targeting statistics of an ad or placement * for a single day, where the data is summarised by operation interval. * * @param integer $id The ad or placement ID. * @param string $type Either "ad" or "placement". * @param PEAR::Date $oDate A date representing the day required. * * @return mixed Returns false in the event of incorrect input, or in the case * of being unable to connect to the database, otherwise, returns * an array of arrays: * * * array( * [$operationIntervalId] => array( * ['interval_start'] => PEAR::Date * ['interval_end'] => PEAR::Date * ['ad_required_impressions'] => integer * ['ad_requested_impressions'] => integer * ['ad_actual_impressions'] => integer * ['zones_forecast_impressions'] => integer * ['zones_actual_impressions'] => integer * ['average'] => integer * ) * . * . * . * ) * * or: * * array( * [$operationIntervalId] => array( * ['interval_start'] => PEAR::Date * ['interval_end'] => PEAR::Date * ['placement_required_impressions'] => integer * ['placement_requested_impressions'] => integer * ['placement_actual_impressions'] => integer * ['zones_forecast_impressions'] => integer * ['zones_actual_impressions'] => integer * ['average'] => integer * ) * . * . * . * ) * * For the ad or placement and day specified, returns an array for each * operation interval in the day, consisting of the operation interval start * and end dates, and the total number of impressions requested by the ad, or * all ads in the placement (for all zones the ads are linked to), as well as * the total number of impressions actually delivered by the ad, or all ads * in the placement (for all zones the ads are linked to). * * The individual ad/zone impressions requested values may need to be * calculated as an "averge" value, in the event that there are multiple, * differing values for an ad in a zone for an operation interval -- in * much the same way as is done in * OA_Dal_Maintenance_Priority::getPreviousAdDeliveryInfo() -- before * the total impressions requested value can be calculated. */ function getDailyTargetingStatistics($id, $type, $oDate) { if (!$this->_testGetTargetingStatisticsDayParameters($id, $type, $oDate)) { return false; } // Ensure that, if a placement, the placement has advertisements $aAdIds = $this->_testGetTargetingStatisticsSpanPlacement($id, $type); if ($aAdIds === false) { return false; } // Prepare the results array $aResult = array(); // Get a date for the start of the day $oStartDate = new Date(); $oStartDate->copy($oDate); $oStartDate->setHour(0); $oStartDate->setMinute(0); $oStartDate->setSecond(0); // Get a date for the end of the day $oEndOfDayDate = new Date(); $oEndOfDayDate->copy($oDate); $oEndOfDayDate->setHour(23); $oEndOfDayDate->setMinute(59); $oEndOfDayDate->setSecond(59); // Get the first operation interval of the day $aDates = OX_OperationInterval::convertDateToOperationIntervalStartAndEndDates($oStartDate); // Get dates to be used in date comparisons $oCompareDate = new Date(); $oCompareDate->copy($aDates['start']); $oCompareEndDate = new Date(); $oCompareEndDate->copy($oEndOfDayDate); while ($oCompareDate->before($oEndOfDayDate)) { // Get the operation interval ID $operationIntervalId = OX_OperationInterval::convertDateToOperationIntervalID($aDates['start']); // Get the results for this operation interval $aResult[$operationIntervalId] = $this->getOperationIntervalTargetingStatistics($aAdIds, $type, $aDates['start'], $aDates['end']); if ($aResult[$operationIntervalId] === false) { return false; } // Get the next operation interval dates $aDates = OX_OperationInterval::convertDateToNextOperationIntervalStartAndEndDates($aDates['start']); // Update the comparison dates $oCompareDate = new Date(); $oCompareDate->copy($aDates['start']); $oCompareEndDate = new Date(); $oCompareEndDate->copy($oEndOfDayDate); } return $aResult; }