name = $name; $this->width = $width; $this->height = $height; $this->area = ($width*$height); $this->code = $code; if($this->code == ""){ $this->buildAdSense(); } $this->types = $types; } public function getName(){return $this->name;} public function getWidth(){return $this->width;} public function getHeight(){return $this->height;} public function getTypes(){return $this->types;} public function setBgColor($bgColor){$this->bgColor = $bgColor;} public function display(){ return $this->code; } //// // Given the properties of an ad, builds the AdSense javascript code to display and track the ad. //// private function buildAdSense(){ $types = $this->types; if($types == 0){ $types = AD_TYPE_TEXT | AD_TYPE_IMAGE; // the default if types was not set } $channels = array( 'links' => '9861204257', 'text' => '2735973429', 'image' => '4976358981', 'text_image' => '4600189986', 'video' => '8300127981', ); $code = "\n"; $code.= "\n"; $this->code = $code; } } // end class Ad class AdModule extends Module{ private $adFormats; // all available ads. private $myAd; private $bgColor; private $allowedTypes; public function AdModule($moduleId=0){ parent::Module( 'ad', STR_ADVERTISEMENTS, '', $moduleId ); $this->adFormats = array(); $this->myAd = ""; $this->bgColor = "#ff0080"; // atrocious-pink so that we remember to figure this out by the actual bg of the page. $this->allowedTypes = (AD_TYPE_TEXT | AD_TYPE_IMAGE); } public function setTypes($types){$this->allowedTypes = $types;} public function getTypes(){return $this->allowedTypes;} public function setBgColor($bgColor){ $this->bgColor= $bgColor; if($this->wasSet()){ $this->myAd->setBgColor($bgColor); } } public function wasSet(){return (get_class($this->myAd) == "Ad");} public function getContent(){ $retVal = ""; //if( WHICH_SERVER != SERVER_DEV ){ if(!$this->wasSet()){ $this->myAd = new Ad('Text/Image Wide Skyscraper', 160, 600, AD_TYPE_TEXT & AD_TYPE_IMAGE); } $retVal .= "
\n"; $retVal .= $this->myAd->display(); $retVal .= "
\n"; $this->setId($this->getId() + 1); // Logs the viewing of this ad (mainly to tell people how many ads they've seen to convince them to upgrade). $user = getUser(); if($user->isLoggedIn()){ sendQuery("UPDATE userStats SET adViews=adViews+1 WHERE user_id=".$user->getId()); } //} return $retVal; } public function setLeaderboard(){$this->myAd = new Ad('Text/Image Leaderboard', 728, 90, AD_TYPE_TEXT & AD_TYPE_IMAGE);} public function setByName($name){ $this->loadFormats(); foreach($this->adFormats as $currAd){ if($currAd->getName() == $name){ $this->myAd = $currAd; break; } } } //// // If the ad wasn't explicitly set before this point, sets the optimal ad /// based on it's best choice given the width, height, and // bgColor. If height isn't known, pass in 0 for the height. //// public function informSize($width, $height, $bgColor){ // Only choose an ad if this ad was not set explicitly yet. if(!$this->wasSet()){ $this->bgColor = $bgColor; $this->loadFormats(); $method = "pixels"; // this is way better than the width algorithm. if($method == "pixels"){ // Finds the ad with the greatest difference between the total pixels of ad-space minus // the total pixels of empty space. $bestScore = 0; foreach($this->adFormats as $currAd){ // Ignore ads that aren't allowed (for exapmle, most often video ads won't be allowed). if($this->getTypes() & $currAd->getTypes()){ // Ignore ads that won't fit in the given constraints. if(($currAd->getWidth() <= $width) && (($height <=0 ) || ($currAd->getHeight() <= $height))){ $adPixels = ($currAd->getWidth() * $currAd->getHeight()); if($height > 0){ // If there is a height limit, count all of the unused potentail space as empty. $emptyPixels = (($width * $height) - $adPixels); } else { $emptyPixels = (($width * $currAd->getHeight()) - $adPixels); } $pixelScore = ($adPixels - $emptyPixels); if($pixelScore >= $bestScore){ $this->myAd = $currAd; $bestScore = $pixelScore; } } } } } else if($method == "width"){// Finds the widest, then tallest module that will fit // Find all of the widest ads that fit. $maxW = 0; $biggest = array(); //array of all ads which have the widest fitting width (since several ads have the same width). foreach($this->adFormats as $currAd){ // Make sure it fits in the width provided and is of the right type. if(($currAd->getWidth() <= $width) && ($this->getTypes() & $currAd->getTypes())){ // bitwise '&' checks that this type is allowed if($currAd->getWidth() > $maxW){ $maxW = $currAd->getWidth(); $biggest = array($currAd); } else if($currAd->getWidth() == $maxW){ $biggest[] = $currAd; } } } // Find the tallest ad that will fit given the height constraints. $maxH = 0; $widest = $biggest; //copy so that biggest can be modified foreach($widest as $currAd){ // If there is a height constraint, make sure the ad fits it before even considering. if(($height <= 0) || ($currAd->getHeight() <= $height)){ if($currAd->getHeight() > $maxH){ $maxH = $currAd->getHeight(); $biggest = array($currAd); } else if($currAd->getHeight() == $maxH){ $biggest[] = $currAd; } } } if(count($biggest) > 0){ $this->myAd = $biggest[rand(0, count($biggest)-1)]; } } } $this->setBgColor($bgColor); // do this after creating the ad, otherwise the color will be overwritten } // end informSize //// // Given a layout string and background color, picks the ideal ad format, then returns // a modified layout string that indicates where the ad is located. //// public function modifyLayout($layout, $bgColor){ $this->bgColor = $bgColor; // If there is already an ad in the page, don't modify the layout $index = strpos($layout, "%ad"); if($index === false){ $index = strpos($layout, ",ad"); // second possibility for formatting } if($index === false){ // Determine where in the layout-string the ad belongs. $cols = explode("||", $layout); $widest = 0; foreach($cols as $currCol){ $matches = array(); if(0 < preg_match("/^([0-9a-f]*)%(([0-9a-f#]*[,]?)*)$/i", $currCol, $matches)){ $colWidth = $matches[1]; $mods = explode(",", $matches[2]); $widest = MAX($colWidth, $widest); } else { throw new Exception("Poorly formed layout string: \"$layout\" in column \"$currCol\""); } } // Places the ad at the bottom of the widest column for now. $origLayout = $layout; $layout = preg_replace("/($widest%(([0-9a-f]*[,]?)*))(\|\||$)/", "$1,ad$4", $layout, 1); if($origLayout == $layout){ $layout .= ",ad"; // emergency fallback is just to throw it on the bottom-right. } // Determine the best ad to go in that space. // TODO: SINCE THERE ARE A FINITE NUMBER OF LAYOUTS TO CHOOSE FROM, JUST HARDCODE THE BEST RESULTS TO START. } return $layout; } // end modifyLayout() private function loadFormats(){ GLOBAL $AD_FORMAT_CACHE; if(!isset($AD_FORMAT_CACHE)){ // Links $AD_FORMAT_CACHE[] = new Ad('Horizontal Links Long', 728, 15, AD_TYPE_LINK); $AD_FORMAT_CACHE[] = new Ad('Horizontal Links Medium', 468, 15, AD_TYPE_LINK); $AD_FORMAT_CACHE[] = new Ad('Square Links XL', 200, 90, AD_TYPE_LINK); $AD_FORMAT_CACHE[] = new Ad('Square Links Large', 180, 90, AD_TYPE_LINK); $AD_FORMAT_CACHE[] = new Ad('Square Links Medium', 160, 90, AD_TYPE_LINK); $AD_FORMAT_CACHE[] = new Ad('Square Links Small', 120, 90, AD_TYPE_LINK); // Text $AD_FORMAT_CACHE[] = new Ad('Text Leaderboard', 728, 90, AD_TYPE_TEXT); $AD_FORMAT_CACHE[] = new Ad('Text Banner', 468, 60, AD_TYPE_TEXT); $AD_FORMAT_CACHE[] = new Ad('Text Half-Banner', 234, 60, AD_TYPE_TEXT); $AD_FORMAT_CACHE[] = new Ad('Text Skyscraper', 120, 600, AD_TYPE_TEXT); $AD_FORMAT_CACHE[] = new Ad('Text Wide Skyscraper', 160, 600, AD_TYPE_TEXT); $AD_FORMAT_CACHE[] = new Ad('Text Vertical Banner', 120, 240, AD_TYPE_TEXT); $AD_FORMAT_CACHE[] = new Ad('Text Large Rectangle', 336, 280, AD_TYPE_TEXT); $AD_FORMAT_CACHE[] = new Ad('Text Medium Rectangle', 300, 250, AD_TYPE_TEXT); $AD_FORMAT_CACHE[] = new Ad('Text Square', 250, 250, AD_TYPE_TEXT); $AD_FORMAT_CACHE[] = new Ad('Text Small Square', 200, 200, AD_TYPE_TEXT); $AD_FORMAT_CACHE[] = new Ad('Text Small Rectangle', 180, 150, AD_TYPE_TEXT); $AD_FORMAT_CACHE[] = new Ad('Text Button', 125, 125, AD_TYPE_TEXT); // Text/image $AD_FORMAT_CACHE[] = new Ad('Text/Image Leaderboard', 728, 90, AD_TYPE_TEXT | AD_TYPE_IMAGE); $AD_FORMAT_CACHE[] = new Ad('Text/Image Banner', 468, 60, AD_TYPE_TEXT | AD_TYPE_IMAGE); $AD_FORMAT_CACHE[] = new Ad('Text/Image Half-Banner', 234, 60, AD_TYPE_TEXT | AD_TYPE_IMAGE); $AD_FORMAT_CACHE[] = new Ad('Text/Image Skyscraper', 120, 600, AD_TYPE_TEXT | AD_TYPE_IMAGE); $AD_FORMAT_CACHE[] = new Ad('Text/Image Wide Skyscraper', 160, 600, AD_TYPE_TEXT | AD_TYPE_IMAGE); $AD_FORMAT_CACHE[] = new Ad('Text/Image Vertical Banner', 120, 240, AD_TYPE_TEXT | AD_TYPE_IMAGE); $AD_FORMAT_CACHE[] = new Ad('Text/Image Large Rectangle', 336, 280, AD_TYPE_TEXT | AD_TYPE_IMAGE); $AD_FORMAT_CACHE[] = new Ad('Text/Image Medium Rectangle', 300, 250, AD_TYPE_TEXT | AD_TYPE_IMAGE); $AD_FORMAT_CACHE[] = new Ad('Text/Image Square', 250, 250, AD_TYPE_TEXT | AD_TYPE_IMAGE); $AD_FORMAT_CACHE[] = new Ad('Text/Image Small Square', 200, 200, AD_TYPE_TEXT | AD_TYPE_IMAGE); $AD_FORMAT_CACHE[] = new Ad('Text/Image Small Rectangle', 180, 150, AD_TYPE_TEXT | AD_TYPE_IMAGE); $AD_FORMAT_CACHE[] = new Ad('Text/Image Button', 125, 125, AD_TYPE_TEXT | AD_TYPE_IMAGE); // Image $AD_FORMAT_CACHE[] = new Ad('Image Leaderboard', 728, 90, AD_TYPE_IMAGE); $AD_FORMAT_CACHE[] = new Ad('Image Banner', 468, 60, AD_TYPE_IMAGE); $AD_FORMAT_CACHE[] = new Ad('Image Skyscraper', 120, 600, AD_TYPE_IMAGE); $AD_FORMAT_CACHE[] = new Ad('Image Wide Skyscraper', 160, 600, AD_TYPE_IMAGE); $AD_FORMAT_CACHE[] = new Ad('Image Large Rectangle', 336, 280, AD_TYPE_IMAGE); $AD_FORMAT_CACHE[] = new Ad('Image Medium Rectangle', 300, 250, AD_TYPE_IMAGE); $AD_FORMAT_CACHE[] = new Ad('Image Square', 250, 250, AD_TYPE_IMAGE); $AD_FORMAT_CACHE[] = new Ad('Image Small Square', 200, 200, AD_TYPE_IMAGE); /* $AD_FORMAT_CACHE[] = new Ad(, , , ); $AD_FORMAT_CACHE[] = new Ad(, , , ); $AD_FORMAT_CACHE[] = new Ad(, , , ); $AD_FORMAT_CACHE[] = new Ad(, , , ); $AD_FORMAT_CACHE[] = new Ad(, , , ); */ } $this->adFormats = $AD_FORMAT_CACHE; } } // end class AdModule ?>