[PHP / MySQL] banner rotatie systeem

Pagina: 1
Acties:

  • HenkS
  • Registratie: Mei 2000
  • Laatst online: 06-05 07:49

HenkS

Da_king alias HenkS

Topicstarter
hallo,

ik zit niet met een programmeer probleem, maar meer met het probleem hoe ik iets op los

ik heb een site (zie sig) en daar staan banners op

nu is het straks zo dat we betalende en niet betalende banners erop hebben staan(nu wordt gewoon alles random getoond)

nu moet het natuurlijk zo zijn dat betalende banners meer getoond worden dan niet betalende banners (zeg 3x zo vaak) en in de db zet je dan bij die banner dat desbetreffende betalend is

maar nu vraag ik me af hoe ik moet gaan realisteren dat een betalende 3x zovaak getoond wordt als een niet betalende... je kunt natuurlijk wel zeggen: hou een teller bij, maar dit werkt niet echt want: stel je bent vrolijk aan het tellen, en dan komt halverwege de week een nieuwe banner erbij: dan gaat deze extreem veel getoond worden totdat die qua telling gelijk staat, dus hoe los je dit probleem op?

hoef geen code alleen een gedachte gang....

  • D2k
  • Registratie: Januari 2001
  • Laatst online: 09-01 11:25

D2k

gewicht :?
betaalde 3
niet betaalde 1
en dan aan de hand van een formule 3x zoveel de betaalde banners showen :)

Doet iets met Cloud (MS/IBM)


  • HenkS
  • Registratie: Mei 2000
  • Laatst online: 06-05 07:49

HenkS

Da_king alias HenkS

Topicstarter
D2k schreef op 23 augustus 2002 @ 16:35:
gewicht :?
betaalde 3
niet betaalde 1
en dan aan de hand van een formule 3x zoveel de betaalde banners showen :)
ja en dan krijg je toch het probleem wat ik voorlegde bij een nieuwe banner???

  • Peetman
  • Registratie: Oktober 2001
  • Laatst online: 19:50

Peetman

Tjah....

Ik zou toch iets met een teller doen. Die laat je tot 4 tellen, bij 1,2 en 3 laat je betalende banner zien, bij 4 een gewone banner. Elke keer dat je een banner laat zien hoog je teller op. Dit moet dan wel een applicatie variabele zijn

  • HGM
  • Registratie: April 2000
  • Niet online

HGM

En dat is met oa http://sourceforge.net/projects/phpadsnew heel gemakkelijk in te stellen ;)

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 17:26

gorgi_19

Kruimeltjes zijn weer op :9

HenkS schreef op 23 augustus 2002 @ 16:36:
[...]


ja en dan krijg je toch het probleem wat ik voorlegde bij een nieuwe banner???
Nee, want je werkt met kansen en verwachtingswaarde.. De kans dat een betalende banner getoond wordt, is drie keer zo groot. Bij 2 banners en 100 views zal NAAR verwachting de betalende 75 keer en de niet betalende 25 keer getoond worden.

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • D2k
  • Registratie: Januari 2001
  • Laatst online: 09-01 11:25

D2k

HenkS schreef op 23 augustus 2002 @ 16:36:
[...]


ja en dan krijg je toch het probleem wat ik voorlegde bij een nieuwe banner???

zie het probleem niet?
je hebt x betalende en y niet betalende en daar haal je dan met mijn eerdere opmerking 3 betalende uit tov 1 niet betalende
dan komt er 1 bij en heb je x betalende en y niet betalende en daar haal je dan met mijn eerdere opmerking 3 betalende uit tov 1 niet betalende
toch? ;)
je moet alleen onder de betaalde/niet betaalde random de banners eruit pikken

Doet iets met Cloud (MS/IBM)


  • HenkS
  • Registratie: Mei 2000
  • Laatst online: 06-05 07:49

HenkS

Da_king alias HenkS

Topicstarter
ja en dat hoef ik niet.... :)

banner rotatie is makkelijk te bouwen, alleen zit dus als er een nieuwe banner komt... die moet dan dus gewoon mee doen in het systeem

stel je hebt 5 banners... 2 niet betalende en 3 betalende

dan moeten die 3 evenveel geshowed worden en die 2 ook, alleen die 3 betalende moeten dus 3x zoveel als die 2

alleen als er dan een betalende bijkomt.. moet die wel meedoen in het roulerings systeem met die andere 3, maar moet niet het gelijke aantal views krijgen, want hij is later begonnen

  • cameodski
  • Registratie: Augustus 2002
  • Laatst online: 06-11-2023
En als je nou zorgt dat die nieuwe initialiseerd wordt met het aantal wat die andere banners ook hebben?

Never underestimate the power of


  • Nielsz
  • Registratie: Maart 2001
  • Niet online
Ik had dus een gewicht aan een banner gehangen.
Dus t.net = 3
GoT = 2
fok = 1

Nou maakte ik een array:
t.net
t.net
t.net
got
got
fok

en pakte er dan een random uit B)

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Nielsz schreef op 23 augustus 2002 @ 17:27:
en pakte er dan een random uit B)

Jemig wat eng!
Banner1: 3ptn, banner2: 5ptn, banner3: 1ptn.

totaal: 9ptn.
Random waarde 1...9 -> 4
banner2 nemen :)

Niet moeilijk doen met potentieel heel groot wordende arrays (zeker als je waardes van 100 enzo toe gaat kennen.

  • HenkS
  • Registratie: Mei 2000
  • Laatst online: 06-05 07:49

HenkS

Da_king alias HenkS

Topicstarter
ACM schreef op 23 augustus 2002 @ 17:50:

[...]

Jemig wat eng!
Banner1: 3ptn, banner2: 5ptn, banner3: 1ptn.

totaal: 9ptn.
Random waarde 1...9 -> 4
banner2 nemen :)

Niet moeilijk doen met potentieel heel groot wordende arrays (zeker als je waardes van 100 enzo toe gaat kennen.
kijk dit is mooi en duidelijk

thanks :)


al krijg je op deze manier wel een kans dat banner 2 banners die evenveel 'punten' hebben, toch een groot aantal verschil in views krijgen door het random systeem.....

want random is natuurlijk iedere x een kans van 1 op 9 in bovenstaand voorbeeld... mmmm toch nog ff iets op verzinnen

[ Voor 0% gewijzigd door HenkS op 26-08-2002 09:11 . Reden: tja ]


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Mwoh, laat je random functie es 1000 getallen uit 1..9 trekken en bepaal de verdeling daarvan, als daar altijd een structurele afwijking inzit zou je daar nog een beetje met verstellingsfactoren aan kunnen sleutelen.
code:
1
2
3
4
5
6
7
8
9
10
0 = 9023
1 = 9031
2 = 9158
3 = 9032
4 = 9100
5 = 9076
6 = 9141
7 = 9102
8 = 9107
9 = 9154

Valt geloof ik wel redelijk mee, code:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?
        $start = 0;
        $end = 10;
        $count = 100000;
        $array = array();
        for($i = 0; $i < $count; $i++)
        {
                $array[rand($start, $end)]++;
        }

        for($i = $start; $i < $end; $i++)
        {
                echo $i . " = " . $array[$i] . "\n";
        }
?>

  • HenkS
  • Registratie: Mei 2000
  • Laatst online: 06-05 07:49

HenkS

Da_king alias HenkS

Topicstarter
thanks, erg duidelijk! supertje

  • HenkS
  • Registratie: Mei 2000
  • Laatst online: 06-05 07:49

HenkS

Da_king alias HenkS

Topicstarter
ACM schreef op 23 augustus 2002 @ 17:50:

[...]

Jemig wat eng!
Banner1: 3ptn, banner2: 5ptn, banner3: 1ptn.

totaal: 9ptn.
Random waarde 1...9 -> 4
banner2 nemen :)

Niet moeilijk doen met potentieel heel groot wordende arrays (zeker als je waardes van 100 enzo toe gaat kennen.
next problem:

al mijn banners staan in de db... die ken ik nu een waarde toe tussen 1 en 5

nu moet ik dus eerst een sum doen van al deze getallen met een query, ok dat is het probleem niet

hier komt dan bv 6 uit

dus als ik 6 banners heb
en de
1e heeft waarde 4
2e heeft waarde 1
3e heeft waarde 3
enz...

dan moet ik de 3e banner hebben.

maar zoals ACM uitlegd, kom ik naar mijn inziens alle banners in een array te zetten, anders kan ik niet kijken welke banner ik moet hebben

want lijkt me niet dat ik met een query kan gaan optellen totdat ik bij 6 ben en dan dus de 3e banner selecteer?? hoe moet ik me dit voorstellen???

want stel ik heb straks 100 banners (zijn er wel veel maar je weet maar nooit) dan moet ik er 100 in een array zetten, optellen, random doen enz.... is dit niet verlangzamend? want mijn site is gewoon supersnel en dat hou ik graag zo, zeker aangezien banners op hoofdpagina staan

  • Apollo_Futurae
  • Registratie: November 2000
  • Niet online
voorstel voor een wat algemeen algoritme voor dit probleem:

uitleg:
$array is van de vorm $array["key"] = $weight;
de functie retourneert een willekeurige key waarbij de kans dat een key gekozen wordt in verhouding is met de weight die aan die key is toegekend.

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function weightedRandom($keys)
{
    $randomnumber = mt_rand(1, array_sum($keys));
    while (list($key, $weight) = each ($keys))
    {
        if ($randomnumber > $weight)
        {
            $randomnumber -= $weight;
        }
        else
        {
            return $key;
        }
    }
}


op- en aanmerkingen zijn zeer welkom; ik ben nu niet in de gelegenheid om dit probeerseltje te testen; misschien zou iemand anders dit kunnen doen?

edit:
aangezien niemand geïnteresseerd lijkt te zijn ( :'( ;) ) heb ik zelf maar een test uitgevoerd.
als input voor bovenstaande functie gaf ik een array:
PHP:
1
2
3
4
$test["a"] = 1;
$test["d"] = 4;
$test["b"] = 2;
$test["c"] = 3;


de resultaten (server in kwestie is een p166 - maar performance lijkt niet echt een probleem te zijn :) ):

Test van weightedRandom()

aantal tests: 10000
totale tijd: 3.317111 seconden
tijd per iteratie: 0.0003317111 seconden

verdeling:
a: 1001
b: 2039
c: 3002
d: 3958

het werkt dus :).

Pas de replâtrage, la structure est pourrie.


  • Megamind
  • Registratie: Augustus 2002
  • Laatst online: 28-02 20:33
HenkS schreef op maandag 26 augustus 2002 @ 15:11:
[...]


next problem:

al mijn banners staan in de db... die ken ik nu een waarde toe tussen 1 en 5

nu moet ik dus eerst een sum doen van al deze getallen met een query, ok dat is het probleem niet

hier komt dan bv 6 uit

dus als ik 6 banners heb
en de
1e heeft waarde 4
2e heeft waarde 1
3e heeft waarde 3
enz...

dan moet ik de 3e banner hebben.

maar zoals ACM uitlegd, kom ik naar mijn inziens alle banners in een array te zetten, anders kan ik niet kijken welke banner ik moet hebben

want lijkt me niet dat ik met een query kan gaan optellen totdat ik bij 6 ben en dan dus de 3e banner selecteer?? hoe moet ik me dit voorstellen???

want stel ik heb straks 100 banners (zijn er wel veel maar je weet maar nooit) dan moet ik er 100 in een array zetten, optellen, random doen enz.... is dit niet verlangzamend? want mijn site is gewoon supersnel en dat hou ik graag zo, zeker aangezien banners op hoofdpagina staan
Sorry voor de erg grote kick :P maar ik zit nu ook met dit probleem, ik ken dus alle banners een waarde van 1 tot 5 toe, dan de sum daaruit halen, een random getal eruit trekken en dan de records langslopen totdat ik bij het goede getal zit.

Dit kan ik ook met een while loepje doen die de records 1 voor 1 doorloopt en kijkt of het getal bereikt of overschreden is, maar kan langzaam zijn denk ik. Dat array idee lijkt me ook langzaam. Zijn er mysql oplossingen?

  • Stilgar
  • Registratie: Maart 2002
  • Niet online
Megamind schreef op zondag 15 mei 2005 @ 16:22:
[...]
Zijn er mysql oplossingen?
Met een hulp tabel wel. Maak een tabel aan met daarin per weging een aantal records dat gelijk is aan de weging. Dus als je weging 1, 2 en 3 hebt, krijg je een tabel met records 1, 2, 2, 3, 3, 3.

Nu vraag je eerst de som van je de wegingen in je banner tabel op met een query, bijv:
code:
1
select rand() * sum(weging) as record_nummer from banners

Dat getal haal je op in php, je hebt het nodig voor de volgende query

Nu kun je de nieuwe hulp tabel icm met een outer join gebruiken om de 'array' in je mysql aan te leggen. bijv:
code:
1
2
3
4
5
6
select 
  weging.weeg_factor, 
  banners.id 
from weging 
  left join banners on (weging.weeg_factor = banners.weegfactor) 
limit record_nummer - 1,1

waarin voor record_nummer het getal ingevuld moet worden (bijv mbv string manipulatie van je query in php).

Dit is trouwens 100% ongetest, dus misschien moet je hier en daar wat aanpassen. Maar het concept zou moeten werken.
Hoe efficient deze methode is weet ik niet. Misschien is de php oplossing wel sneller, geen idee. Je laat in ieder geval wel de database het zware werk doen.

  • Megamind
  • Registratie: Augustus 2002
  • Laatst online: 28-02 20:33
Stilgar schreef op zondag 15 mei 2005 @ 18:29:
[...]


Met een hulp tabel wel. Maak een tabel aan met daarin per weging een aantal records dat gelijk is aan de weging. Dus als je weging 1, 2 en 3 hebt, krijg je een tabel met records 1, 2, 2, 3, 3, 3.

Nu vraag je eerst de som van je de wegingen in je banner tabel op met een query, bijv:
code:
1
select rand() * sum(weging) as record_nummer from banners

Dat getal haal je op in php, je hebt het nodig voor de volgende query

Nu kun je de nieuwe hulp tabel icm met een outer join gebruiken om de 'array' in je mysql aan te leggen. bijv:
code:
1
2
3
4
5
6
select 
  weging.weeg_factor, 
  banners.id 
from weging 
  left join banners on (weging.weeg_factor = banners.weegfactor) 
limit record_nummer - 1,1

waarin voor record_nummer het getal ingevuld moet worden (bijv mbv string manipulatie van je query in php).

Dit is trouwens 100% ongetest, dus misschien moet je hier en daar wat aanpassen. Maar het concept zou moeten werken.
Hoe efficient deze methode is weet ik niet. Misschien is de php oplossing wel sneller, geen idee. Je laat in ieder geval wel de database het zware werk doen.
Je methode werkt idd, alleen hij is niet zo snel als een simpele PHP oplossing:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?
  $query=mysql_query("SELECT SUM(ratio) FROM ad_banners");
  $max=mysql_result($query,0);
  $rand=mt_rand(1,$max);
  $query=mysql_query("SELECT * FROM ad_banners");
  $addup=0;
  while($banner=mysql_fetch_object($query)){
    $ratio=$banner->ratio;
    $addup+=$ratio;
    if($addup>=$rand){
      $banners[$banner->id]++;

      break;
    };
  };
?>


Maar toch bedankt, kon ik teminste beide resultaten vergelijken.

Als je wilt kijken of de resultaten betrouwbaar zijn kan je dit nog even draaien (er vanuit gaan dat je 4 banners in je DB hebt)

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?
$perc1=($banners[1]/$totaal)*100;
$perc2=($banners[2]/$totaal)*100;
$perc3=($banners[3]/$totaal)*100;
$perc4=($banners[4]/$totaal)*100;
$showratio1=$max*($perc1/100);
$showratio2=$max*($perc2/100);
$showratio3=$max*($perc3/100);
$showratio4=$max*($perc4/100);

echo "1: Ratio:1 Shows:$banners[1] Perc:$perc1% ShowRatio:$showratio1/$max<BR>";
echo "2: Ratio:3 Shows:$banners[2] Perc:$perc2% ShowRatio:$showratio2/$max<BR>";
echo "3: Ratio:2 Shows:$banners[3] Perc:$perc3% ShowRatio:$showratio3/$max<BR>";
echo "4: Ratio:5 Shows:$banners[4] Perc:$perc4% ShowRatio:$showratio4/$max<BR>";
?>


Bij 10.000 hits:
1: Ratio:1 Shows:878 Perc:8.78% ShowRatio:0.9658/11
2: Ratio:3 Shows:2763 Perc:27.63% ShowRatio:3.0393/11
3: Ratio:2 Shows:1862 Perc:18.62% ShowRatio:2.0482/11
4: Ratio:5 Shows:4497 Perc:44.97% ShowRatio:4.9467/11

[ Voor 12% gewijzigd door Megamind op 16-05-2005 10:28 ]


  • Stilgar
  • Registratie: Maart 2002
  • Niet online
Megamind schreef op maandag 16 mei 2005 @ 10:27:
[...]
Je methode werkt idd, alleen hij is niet zo snel als een simpele PHP oplossing
Zo'n loop door alle banners lijkt me niet heel efficient als je veel banners hebt. Ik heb even gekeken naar hoe de php oplossing tov de sql oplossing schaalt met het aantal banners.
Ik heb het stukje code van Megamind gebruikt voor de 'php' versie, en de volgende code voor de 'sql' versie:
PHP:
1
2
3
4
5
  $query=mysql_query("SELECT RAND() * SUM(ratio) FROM ad_banners");
  $nr=mysql_result($query,0);
  $query=mysql_query(sprintf("SELECT ad_banners.id FROM ratio 
        LEFT JOIN ad_banners ON (ratio.ratio = ad_banners.ratio) 
        LIMIT %d,1", $nr));

Ik heb gekeken naar de 'opzoektijd' van 1000 banners, bij 10, 50 en 100 banners in de database. Ik heb dit steeds 5 keer herhaalt. Ik heb een draaitabel (en grafiek) van de uitvoertijd gemaakt (in seconden, lager is beter):
code:
1
2
3
4
aant   php        sql
 10 1,5957656   1,839239
 50 2,1347182   2,01569
100 2,8261744   2,4209816

Tot (ongeveer) 35-40 banners is de php oplossing bij mij duidelijk sneller, daarboven is de sql oplossing sneller. Overigens is het natuurlijk wel belangrijk dat je de juiste indices maakt op de tabellen.

Dus als je een kleine tot middelgrote site hebt met minder dan 40 banners is de php oplossing inderdaad het snelst.
Pagina: 1