/** * A method to be run before all tests. */ function setUp() { // Set up the configuration array to have an operation interval // of 60 minutes, and set the timezone to GMT $aConf =& $GLOBALS['_MAX']['CONF']; $aConf['maintenance']['operationInteval'] = 60; OA_setTimeZone('GMT'); //setTimeZoneLocation($aConf['timezone']['location']); // Set up the database handler object $this->oDbh =& OA_DB::singleton(); // Set up the service locator object $this->oServiceLocator =& OA_ServiceLocator::instance(); // Discover the number of operation intervals per week $this->intervalsPerWeek = OX_OperationInterval::operationIntervalsPerWeek(); // This test was written with a ZONE_FORECAST_DEFAULT_ZONE_IMPRESSIONS value of 10 in mind. OA_Dal_Maintenance_Priority::$ZONE_FORECAST_DEFAULT_ZONE_IMPRESSIONS = 10; }
/** * 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 private method to return the current cumulative zone forecast data for all zones * associated with a given advertisement. The returned array is keyed by operation interval * ID (i.e. from 0 [zero] to the maximum operation interval ID value, depending on the current * configuration value for the operation interval length). The zone forecast values used * in calculating the cumulative forecast are taken from the end of the current operation * interval to one week prior (i.e. the most recent week's worth of forecasts). * * @access private * @param integer $adId The advertisement ID. * @param array $aAdZones An array of arrays, no particular index in the outer array, in the * inner arrays, each as an index "zone_id" containing one zone ID that * the ad is linked to. * @return mixed Array on success, false on failure. If an array, it is of the format: * array( * [operation_interval_id] => forecast_impressions, * [operation_interval_id] => forecast_impressions * . * . * . * ) */ function _getCumulativeZoneForecast($adId, $aAdZones) { $aConf = $GLOBALS['_MAX']['CONF']; if (empty($adId) || !is_numeric($adId)) { OA::debug('- Invalid advertisement ID argument', PEAR_LOG_ERR); return false; } if (!is_array($aAdZones)) { OA::debug('- Invalid zone array argument', PEAR_LOG_ERR); return false; } // Initialise the results array with the number operation intervals in a week $aResults = array_fill(0, OX_OperationInterval::operationIntervalsPerWeek(), 0); // Get the forcast impressions for the previous week if (!empty($aAdZones)) { foreach ($aAdZones as $aZone) { if (!is_array($this->aZoneForecasts[$aZone['zone_id']])) { $this->aZoneForecasts[$aZone['zone_id']] = $this->oDal->getPreviousWeekZoneForcastImpressions($aZone['zone_id']); } if (is_array($this->aZoneForecasts[$aZone['zone_id']]) && !empty($this->aZoneForecasts[$aZone['zone_id']])) { foreach ($this->aZoneForecasts[$aZone['zone_id']] as $aValues) { $aResults[$aValues['operation_interval_id']] += (int) $aValues['forecast_impressions']; } } } } return $aResults; }
/** * A method to return the forecast impressions for a zone, indexed by operation interval, * from the current operation interval through the past week. If no forecast stored in * the database for a given OI, uses average of forecasts found. * * @param integer $zoneId The Zone ID. * @return mixed An array on success, false on failure. The array is of the format: * array( * [operation_interval_id] => array( * ['zone_id'] => zone_id, * ['_impressions'] => forecast_impressions, * ['operation_interval_id'] => operation_interval_id * ) * [operation_interval_id] => array( * ['zone_id'] => zone_id, * ['forecast_impressions'] => forecast_impressions, * ['operation_interval_id'] => operation_interval_id * ) * . * . * . * ) */ function getPreviousWeekZoneForcastImpressions($zoneId) { if (empty($zoneId) || !is_numeric($zoneId)) { OA::debug('Invalid zone ID argument', PEAR_LOG_ERR); return false; } $aConf = $GLOBALS['_MAX']['CONF']; $oServiceLocator =& OA_ServiceLocator::instance(); $oDate =& $oServiceLocator->get('now'); if (!$oDate) { return false; } // Get previous OI $oPreviousOI = new Date($oDate); $oPreviousOI->subtractSeconds(OX_OperationInterval::getOperationInterval() * 60); // Get the start and end ranges of the current week, up to the previous OI $aDates = OX_OperationInterval::convertDateToOperationIntervalStartAndEndDates($oPreviousOI); $oDateWeekStart = new Date(); $oDateWeekStart->copy($aDates['end']); $oDateWeekStart->subtractSeconds(SECONDS_PER_WEEK - 1); $oDateWeekEnd = new Date(); $oDateWeekEnd->copy($aDates['end']); // Select the zone forecasts from the database $tableName = $this->_getTablename('data_intermediate_ad'); $oneHourInterval = OA_Dal::quoteInterval(1, 'hour'); $query = "\n SELECT\n SUM(impressions) AS forecast_impressions,\n operation_interval_id AS operation_interval_id,\n interval_start AS interval_start,\n interval_end AS interval_end\n FROM\n {$tableName}\n WHERE\n zone_id = {$zoneId}\n AND operation_interval = {$aConf['maintenance']['operationInterval']}\n AND interval_start >= '" . $oDateWeekStart->format('%Y-%m-%d %H:%M:%S') . "'\n AND interval_end <= '" . $oDateWeekEnd->format('%Y-%m-%d %H:%M:%S') . "'\n AND date_time > DATE_SUB('" . $oDateWeekStart->format('%Y-%m-%d %H:%M:%S') . "', {$oneHourInterval})\n AND date_time < DATE_ADD('" . $oDateWeekEnd->format('%Y-%m-%d %H:%M:%S') . "', {$oneHourInterval})\n AND zone_id != 0\n GROUP BY\n \tinterval_start,\n \tinterval_end,\n \toperation_interval_id\n ORDER BY\n interval_start"; $rc = $this->oDbh->query($query); $totalForecastImpressions = 0; $count = 0; if (!PEAR::isError($rc)) { // Sort the results into an array indexed by the operation interval ID $aFinalResult = array(); while ($aRow = $rc->fetchRow()) { $aFinalResult[$aRow['operation_interval_id']] = array('zone_id' => $zoneId, 'forecast_impressions' => $aRow['forecast_impressions'], 'operation_interval_id' => $aRow['operation_interval_id']); $count++; $totalForecastImpressions += $aRow['forecast_impressions']; } } $averageForecastImpressions = 0; if ($count > 0) { $averageForecastImpressions = floor($totalForecastImpressions / $count); } if ($averageForecastImpressions == 0) { $averageForecastImpressions = $this->getZoneForecastDefaultZoneImpressions(); } // Check each operation interval ID has a forecast impression value, // and if not, set to the system default. for ($operationIntervalID = 0; $operationIntervalID < OX_OperationInterval::operationIntervalsPerWeek(); $operationIntervalID++) { if (!isset($aFinalResult[$operationIntervalID])) { $aFinalResult[$operationIntervalID] = array('zone_id' => $zoneId, 'forecast_impressions' => $averageForecastImpressions, 'operation_interval_id' => $operationIntervalID); } } // Overwrite current OI with previous OI to match the zone forecasting algorithm $currOI = OX_OperationInterval::convertDateToOperationIntervalID($oDate); $prevOI = OX_OperationInterval::previousOperationIntervalID($currOI); $aFinalResult[$currOI]['forecast_impressions'] = $aFinalResult[$prevOI]['forecast_impressions']; // Return data return $aFinalResult; }
/** * A method to return the forcast impressions for a zone, indexed by operation interval, * from the current operation interval through the past week. If no forecast stored in * the database, uses the defualt value from the configuration file. * * @param integer $zoneId The Zone ID. * @return mixed An array on success, false on failure. The array is of the format: * array( * [operation_interval_id] => array( * ['zone_id'] => zone_id, * ['forecast_impressions'] => forecast_impressions, * ['operation_interval_id'] => operation_interval_id * ) * [operation_interval_id] => array( * ['zone_id'] => zone_id, * ['forecast_impressions'] => forecast_impressions, * ['operation_interval_id'] => operation_interval_id * ) * . * . * . * ) */ function getPreviousWeekZoneForcastImpressions($zoneId) { if (empty($zoneId) || !is_numeric($zoneId)) { OA::debug('Invalid zone ID argument', PEAR_LOG_ERR); return false; } $aConf = $GLOBALS['_MAX']['CONF']; $oServiceLocator =& OA_ServiceLocator::instance(); $oDate =& $oServiceLocator->get('now'); if (!$oDate) { return false; } // Get the start and end ranges of the current week $aDates = OX_OperationInterval::convertDateToOperationIntervalStartAndEndDates($oDate); $oDateWeekStart = new Date(); $oDateWeekStart->copy($aDates['end']); $oDateWeekStart->subtractSeconds(SECONDS_PER_WEEK - 1); $oDateWeekEnd = new Date(); $oDateWeekEnd->copy($aDates['end']); // Select the zone forecasts from the database $tableName = $this->_getTablename('data_summary_zone_impression_history'); $query = "\n SELECT\n zone_id AS zone_id,\n forecast_impressions AS forecast_impressions,\n operation_interval_id AS operation_interval_id,\n interval_start AS interval_start,\n interval_end AS interval_end\n FROM\n {$tableName}\n WHERE\n zone_id = {$zoneId}\n AND operation_interval = {$aConf['maintenance']['operationInterval']}\n AND interval_start >= '" . $oDateWeekStart->format('%Y-%m-%d %H:%M:%S') . "'\n AND interval_end <= '" . $oDateWeekEnd->format('%Y-%m-%d %H:%M:%S') . "'\n AND zone_id != 0\n ORDER BY\n interval_start"; $rc = $this->oDbh->query($query); if (!PEAR::isError($rc)) { // Sort the results into an array indexed by the operation interval ID $aFinalResult = array(); while ($aRow = $rc->fetchRow()) { $aFinalResult[$aRow['operation_interval_id']] = array('zone_id' => $aRow['zone_id'], 'forecast_impressions' => $aRow['forecast_impressions'], 'operation_interval_id' => $aRow['operation_interval_id']); } } // Check each operation interval ID has a forecast impression value, // and if not, set to the system default. for ($operationIntervalID = 0; $operationIntervalID < OX_OperationInterval::operationIntervalsPerWeek(); $operationIntervalID++) { if (!isset($aFinalResult[$operationIntervalID])) { $aFinalResult[$operationIntervalID] = array('zone_id' => $zoneId, 'forecast_impressions' => ZONE_FORECAST_DEFAULT_ZONE_IMPRESSIONS, 'operation_interval_id' => $operationIntervalID); } } return $aFinalResult; }
/** * A method to obtain the sum of the zone forecast impression value, for all the zones * an advertisement is linked to, cloned out over the advertisement's entire remaining * lifetime in the campaign, with any blocked operation intervals removed. * * Requires that the getActiveAdOperationIntervals() method have previously been * called to function correctly. * * @param PEAR::Date $oNowDate The current date. * @param PEAR::Date $oEndDate The end date of the campaign. Note that if the end * date supplied is not at the end of a day, it will be * converted to be treated as such. * @param array $aCumulativeZoneForecast The cumulative forecast impressions, indexed * by operation interval ID, of all the zones the * advertisement is linked to. * array( * [operation_interval_id] => forecast_impressions, * [operation_interval_id] => forecast_impressions * . * . * . * ) * @return integer The ad's total remaining zone impression forecast for all zone for * the remaining life of the ad. */ function getAdLifetimeZoneImpressionsRemaining($oNowDate, $oEndDate, $aCumulativeZoneForecast) { $totalAdLifetimeZoneImpressionsRemaining = 0; // Test the parameters, if invalid, return zero if (!is_a($oNowDate, 'date') || !is_a($oEndDate, 'date') || !is_array($aCumulativeZoneForecast) || count($aCumulativeZoneForecast) != OX_OperationInterval::operationIntervalsPerWeek()) { OA::debug(' - Invalid parameters to getAdLifetimeZoneImpressionsRemaining, returning 0', PEAR_LOG_ERR); return $totalAdLifetimeZoneImpressionsRemaining; } // Ensure that the end of campaign date is at the end of the day $oEndDateCopy = new Date($oEndDate); $oEndDateCopy->setHour(23); $oEndDateCopy->setMinute(59); $oEndDateCopy->setSecond(59); // Ensure that the $aCumulativeZoneForecast array is sorted by key, so that it can // be accessed by array_slice, regardless of the order that the forecast data was added // to the array ksort($aCumulativeZoneForecast); // Step 1: Calculate the sum of the forecast values from "now" until the end of "today" $aDates = OX_OperationInterval::convertDateToOperationIntervalStartAndEndDates($oNowDate); $oEndOfToday = new Date($aDates['start']); $oEndOfToday->setTZ($oEndDate->tz); $oEndOfToday->setHour(23); $oEndOfToday->setMinute(59); $oEndOfToday->setSecond(59); $oStart = $aDates['start']; while ($oStart->before($oEndOfToday)) { // Find the Operation Interval ID for this Operation Interval $operationIntervalID = OX_OperationInterval::convertDateToOperationIntervalID($oStart); // As iteration over every OI is required anyway, test to see if // the ad is blocked in this OI; if not, add the forecast values to the // running total if (empty($this->aBlockedOperationIntervalDates[$oStart->format('%Y-%m-%d %H:%M:%S')])) { $totalAdLifetimeZoneImpressionsRemaining += $aCumulativeZoneForecast[$operationIntervalID]; } // Go to the next operation interval in "today" $oStart = OX_OperationInterval::addOperationIntervalTimeSpan($oStart); } // Step 2: Calculate how many times each day of the week occurs between the end of // "today" (i.e. starting "tomorrow morning") and the last day the ad can run $aDays = array(); $oStartOfTomorrow = new Date($oEndOfToday); $oStartOfTomorrow->addSeconds(1); $oTempDate = new Date(); $oTempDate->copy($oStartOfTomorrow); $aDates = OX_OperationInterval::convertDateToOperationIntervalStartAndEndDates($oTempDate); while ($aDates['start']->before($oEndDateCopy)) { // Increase the count for this day of the week $aDays[$aDates['start']->getDayOfWeek()]++; // Go to the next day $oTempDate->addSeconds(SECONDS_PER_DAY); $aDates = OX_OperationInterval::convertDateToOperationIntervalStartAndEndDates($oTempDate); } // Step 3: For every possible day of the week (assuming that day of the week is in the // ad's remaining lifetime), calculate the sum of the forecast values for every // operation interval in that day if (!empty($aDays)) { $operationIntervalsPerDay = OX_OperationInterval::operationIntervalsPerDay(); $oTempDate = new Date($oStartOfTomorrow); $aDates = OX_OperationInterval::convertDateToOperationIntervalStartAndEndDates($oTempDate); for ($counter = 0; $counter < 7; $counter++) { // Are there any instances of this day in the campaign? if ($aDays[$oTempDate->getDayOfWeek()] > 0) { // Calculate the sum of the zone forecasts for this day of week $aDates = OX_OperationInterval::convertDateToOperationIntervalStartAndEndDates($oTempDate); $dayStartOperationIntervalId = OX_OperationInterval::convertDateToOperationIntervalID($aDates['start']); $aDayCumulativeZoneForecast = array_slice($aCumulativeZoneForecast, $dayStartOperationIntervalId, $operationIntervalsPerDay); $forecastSum = array_sum($aDayCumulativeZoneForecast); // Multiply this day's forecast sum value by the number of times this // day of week appears in the remainder of the campaign and add the // value to the running total $totalAdLifetimeZoneImpressionsRemaining += $forecastSum * $aDays[$oTempDate->getDayOfWeek()]; } // Go to the next day $oTempDate->addSeconds(SECONDS_PER_DAY); } } // Step 4: Subtract any blocked interval values if ($this->blockedOperationIntervalCount > 0) { OA::debug(" - Subtracting {$this->blockedOperationIntervalCount} blocked intervals", PEAR_LOG_DEBUG); foreach ($this->aBlockedOperationIntervalDates as $aDates) { if ($aDates['start']->after($oEndOfToday)) { $blockedOperationInvervalID = OX_OperationInterval::convertDateToOperationIntervalID($aDates['start']); $totalAdLifetimeZoneImpressionsRemaining -= $aCumulativeZoneForecast[$blockedOperationInvervalID]; } } } // Return the calculated value return $totalAdLifetimeZoneImpressionsRemaining; }
/** * A private method to fill an array with 1 as the default forecast * for and operation interval that is not yet set. * * @param array $aArray */ function _fillForecastArray($aArray) { $intervalsPerWeek = OX_OperationInterval::operationIntervalsPerWeek(); for ($counter = 0; $counter < $intervalsPerWeek; $counter++) { if (empty($aArray[$counter])) { $aArray[$counter] = 1; } } return $aArray; }
/** * A method to test the getPreviousWeekZoneForcastImpressions() method. * * Test 1: Test with bad input, and ensure false is returned. * Test 2: Test with no date in the service locator, and ensure that * false is returned. * Test 3: Test with no data, and ensure that an array with the default * forecast for each zone is returned. * Test 4: Test with data, and ensure that an array with the correct * forecasts is returned. */ function testGetPreviousWeekZoneForcastImpressions() { $aConf = $GLOBALS['_MAX']['CONF']; $oDbh =& OA_DB::singleton(); $oDal = new OA_Dal_Maintenance_Priority(); // Test 1 $aResult = $oDal->getPreviousWeekZoneForcastImpressions('foo'); $this->assertFalse($aResult); // Test 2 $oServiceLocator =& OA_ServiceLocator::instance(); $oServiceLocator->remove('now'); $aResult = $oDal->getPreviousWeekZoneForcastImpressions(1); $this->assertFalse($aResult); // Test 3 $oDate = new Date(); $oServiceLocator->register('now', $oDate); $aResult = $oDal->getPreviousWeekZoneForcastImpressions(1); $this->assertTrue(is_array($aResult)); $this->assertEqual(count($aResult), OX_OperationInterval::operationIntervalsPerWeek()); for ($operationIntervalID = 0; $operationIntervalID < OX_OperationInterval::operationIntervalsPerWeek(); $operationIntervalID++) { $expected = array('zone_id' => 1, 'forecast_impressions' => $oDal->getZoneForecastDefaultZoneImpressions(), 'operation_interval_id' => $operationIntervalID); $this->assertEqual($aResult[$operationIntervalID], $expected); } // Test 4 // Insert impressions for the previous operation interval $aDates = OX_OperationInterval::convertDateToOperationIntervalStartAndEndDates($oDate); $aDates = OX_OperationInterval::convertDateToPreviousOperationIntervalStartAndEndDates($aDates['start']); $firstIntervalID = OX_OperationInterval::convertDateToOperationIntervalID($aDates['start']); $startDate = $aDates['start']->format('%Y-%m-%d %H:%M:%S'); $endDate = $aDates['start']->format('%Y-%m-%d %H:%M:%S'); $doDIA = OA_Dal::factoryDO('data_intermediate_ad'); $aDIAs = DataGenerator::generate($doDIA, 4); $doDIA = OA_Dal::staticGetDO('data_intermediate_ad', $aDIAs[0]); $startDate = $aDates['start']->format('%Y-%m-%d %H:%M:%S'); $endDate = $aDates['start']->format('%Y-%m-%d %H:%M:%S'); $doDIA->date_time = $startDate; $doDIA->interval_start = $startDate; $doDIA->interval_end = $endDate; $doDIA->operation_interval = $aConf['maintenance']['operationInterval']; $doDIA->operation_interval_id = $firstIntervalID; $doDIA->zone_id = 1; $doDIA->ad_id = 1; $doDIA->impressions = 4000; $doDIA->update(); // Insert forcast for the (N - 2) OI // for two different ads in this OI $aDates = OX_OperationInterval::convertDateToPreviousOperationIntervalStartAndEndDates($aDates['start']); $secondIntervalID = OX_OperationInterval::convertDateToOperationIntervalID($aDates['start']); $startDate = $aDates['start']->format('%Y-%m-%d %H:%M:%S'); $endDate = $aDates['start']->format('%Y-%m-%d %H:%M:%S'); $doDIA = OA_Dal::staticGetDO('data_intermediate_ad', $aDIAs[1]); $doDIA->date_time = $startDate; $doDIA->interval_start = $startDate; $doDIA->interval_end = $endDate; $doDIA->operation_interval = $aConf['maintenance']['operationInterval']; $doDIA->operation_interval_id = $secondIntervalID; $doDIA->zone_id = 1; $doDIA->ad_id = 1; $doDIA->impressions = 4990; $doDIA->update(); $doDIA = OA_Dal::staticGetDO('data_intermediate_ad', $aDIAs[2]); $doDIA->date_time = $startDate; $doDIA->interval_start = $startDate; $doDIA->interval_end = $endDate; $doDIA->operation_interval = $aConf['maintenance']['operationInterval']; $doDIA->operation_interval_id = $secondIntervalID; $doDIA->zone_id = 1; $doDIA->ad_id = 2; $doDIA->impressions = 10; $doDIA->update(); // Insert forcast for the second previous operation interval, but // one week ago (so it should not be in the result set) $oNewDate = new Date(); $oNewDate->copy($aDates['start']); $oNewDate->subtractSeconds(SECONDS_PER_WEEK); $aDates = OX_OperationInterval::convertDateToPreviousOperationIntervalStartAndEndDates($oNewDate); $intervalID = OX_OperationInterval::convertDateToOperationIntervalID($aDates['start']); $startDate = $aDates['start']->format('%Y-%m-%d %H:%M:%S'); $endDate = $aDates['start']->format('%Y-%m-%d %H:%M:%S'); $doDIA = OA_Dal::staticGetDO('data_intermediate_ad', $aDIAs[3]); $doDIA->date_time = $startDate; $doDIA->interval_start = $startDate; $doDIA->interval_end = $endDate; $doDIA->operation_interval = $aConf['maintenance']['operationInterval']; $doDIA->operation_interval_id = $intervalID; $doDIA->zone_id = 1; $doDIA->ad_id = 1; $doDIA->impressions = 1000; $doDIA->update(); // What's the current OI? $currentIntervalID = OX_OperationInterval::convertDateToOperationIntervalID($oServiceLocator->get('now')); $aResult = $oDal->getPreviousWeekZoneForcastImpressions(1); $this->assertTrue(is_array($aResult)); $this->assertEqual(count($aResult), OX_OperationInterval::operationIntervalsPerWeek()); for ($operationIntervalID = 0; $operationIntervalID < OX_OperationInterval::operationIntervalsPerWeek(); $operationIntervalID++) { $this->assertTrue(is_array($aResult[$operationIntervalID])); $this->assertEqual(count($aResult[$operationIntervalID]), 3); $this->assertEqual($aResult[$operationIntervalID]['zone_id'], 1); if ($operationIntervalID == $firstIntervalID || $operationIntervalID == $currentIntervalID) { // Current and previous OI forecasts should be the same $this->assertEqual($aResult[$operationIntervalID]['forecast_impressions'], 4000); } elseif ($operationIntervalID == $secondIntervalID) { $this->assertEqual($aResult[$operationIntervalID]['forecast_impressions'], 5000); } else { $this->assertEqual($aResult[$operationIntervalID]['forecast_impressions'], 4500); // average between both known forecast } $this->assertEqual($aResult[$operationIntervalID]['operation_interval_id'], $operationIntervalID); } DataGenerator::cleanUp(); }