Moogli: Sequentielle Weiterleitung (a, b, c, a, b, c, a, b, c, ...)

Hallo an das Forum!

Für ein Projekt an der Uni (eine Online-Umfrage) muß ich die Probanden auf verschiedene Versionen eines Fragebogens umleiten. Eine rein zufällige Weiterleitung habe ich bereits gefunden. Das Problem hierbei ist, daß dann ggf. die verschiedenen Gruppen unterschiedlich viele Besucher abbekommen können, daß also keine genaue Gleichverteilung stattfindet.

Daher bräuchte ich einen Code, der bei jedem Aufruf die Leute sequentiell verteilt. Heisst: Eine Aufrufadresse; der erste Aufrufer bekommt Seite A, der zweite Aufrufer bekommt Seite B, der dritte Aufrufer bekommt Seite C, [...] der x-te Aufrufer bekommt dann wieder Seite A und es geht von vorne los. Damit wäre die Verteilung "quasizufällig", und auf jeden Fall gleichverteilt.

Wie kann man dieses Problem möglichst einfach lösen? Ich weiß, für die Eingeweihten ist soetwas supereasy, aber ich bin in PHP und Datenbanken und so weiter gar nicht drinne, und vielleicht kann mir ja jemand aushelfen, bevor ich mich wegen so einem Miniproblem das Zeug ganz draufschaffen muß... Wäre jedenfalls supernett, wenn jemand helfen kann!

Viele Grüße,
Moogli

  1. Hallo,

    Daher bräuchte ich einen Code, der bei jedem Aufruf die Leute sequentiell verteilt ...

    Nimm einen Counter, also eine Datei mit einer Zahl, die hochzählt. Wenn sie 4 ist, wird sie wieder auf 0 zurückgesetzt.

    Der nächste Besucher bekommt die nächste Zahl.

      $file = "./counter.txt";  
      list( $counter ) = @file( $file );  
      $counter++;  
      if ( $counter > 3 ) $counter = 0;  
      
      $out = fopen( $file, "w" ); // w = write (zum Schreiben oeffnen  
      if ( $out ) {  
        fwrite( $out, $counter );  
        fclose( $out );  
      }  
    
    

    Kalle

    1. Moin!

      Nimm einen Counter, also eine Datei mit einer Zahl, die hochzählt. Wenn sie 4 ist, wird sie wieder auf 0 zurückgesetzt.

      Counter - na gut.

      Aber doch bitte nicht so, wie du es demonstrierst, vollkommen ohne Locking etc.

      Abgesehen: Wieso der Vergleich mit 4 - es gibt nur drei Ziele.

      - Sven Rautenberg

    2. Hallo,

      Daher bräuchte ich einen Code, der bei jedem Aufruf die Leute sequentiell verteilt ...

      Nimm einen Counter, also eine Datei mit einer Zahl, die hochzählt. Wenn sie 4 ist, wird sie wieder auf 0 zurückgesetzt.

      Wie Sven schon sagte, 0 bis 3 sind vier Zustände :)

      0 bis 2 oder 1 bis 3 wäre bei drei Wunschzuständen vernünftiger

      In deinem beispiel müsstest du also ein > 2 oder >= 3 statt dem > 3 einbauen - oder $counter mit 1 beginnen.

    3. Hi Kalle,

      danke für den Code. Was ist das jetzt? Java Script? Kann das also mit "<script type="text/javascript">" in HTML eingebunden werden?

      Kann ich das folgende hier dann so anfügen?

      function weiter() {
        var adresse = new Array('seite1.htm', 'seite2.htm', 'seite3.htm', 'seite4.htm', 'seite5.htm');
        var nummer = $counter;
        location.href = adresse[nummer];
        }
      </script>

      </head>
      <body onLoad="setTimeout('weiter()', 0)">

      Danke!
      Moogli

      1. Hi,

        danke für den Code. Was ist das jetzt? Java Script? Kann das also mit "<script type="text/javascript">" in HTML eingebunden werden?

        Welchen Themenbereich hattest du noch mal gewählt?
        Welche lang-Angabe hat Kalle im code-Tag gemacht?

        Kann ich das folgende hier dann so anfügen?

        Man könnte es mit JavaScript kombinieren, aber da gibt es eigentlich keinen plausiblen Grund für.

        Die Speicherung des Counters muss auf jeden Fall serverseitig erfolgen.

        MfG ChrisB

        --
        Light travels faster than sound - that's why most people appear bright until you hear them speak.
    4. Hello,

      Der nächste Besucher bekommt die nächste Zahl.

      $file = "./counter.txt";

      list( $counter ) = @file( $file );
        $counter++;

      if ( $counter > 3 ) $counter = 0;

      $out = fopen( $file, "w" ); // w = write (zum Schreiben oeffnen
        if ( $out ) {
          fwrite( $out, $counter );
          fclose( $out );
        }

        
      Es ist ganz ungünstig, füe einen Prozess, der als atomarer Prozess gebunden werden müsste, zwei unabhängige Handles zu benutzen. Und an das handle von file() kommt man noch nicht einnmal heran, da file() nach außen als namensbasierte Funktion arbeitet.  
        
      Dieser Code schafft ein TOCTOU-Problem (Race-Condition nicht abgefangen) und ist daher unbrauchbar.  
      <http://en.wikipedia.org/wiki/Time-of-check-to-time-of-use>  
      <http://www.owasp.org/index.php/File_Access_Race_Condition:_TOCTOU>  
      <http://en.wikipedia.org/wiki/Race_condition>  
        
      ~~~php
        
        $file = "./counter.txt";    ## muss vorhanden sein!  
        
      function counter($file)  
      {  
        $fh = fopen($file, 'rb+');  
        if (!$fh) return false;     ## Datei konnte nicht geöffnet werden, -> Ende im Gelände  
        if (!flock($fh, LOCK_EX)    ## Datei konnte nicht exclusiv gesperrt werden  
        {  
            fclose($fh);            ## Datei schließen  
            return false;           ## -> Ende im Gelände  
        }  
        
        $line = fgets($fh);         ## eine _Textzeile_ aus der Datei holen mit Default-Länge  
        $count = intval($line);     ## wir wandeln das Gelesene in eine numerische Größe (ganez Zahl) um  
        $count++;                   ## und erhöhen den Wert um 1  
        
        if ( $count > 3 ) $count = 0;  ## Wenn 0,1,2,3 abgearbeitet wurden, kommt wieder 0  
        
        fseek($fh, 0, SEEK_SET);    ## Dateizeiger wieder auf Anfang zurück  
        
        fwrite($fh, $count);        ## Den Counterwert in die Datei zurückschreiben  
        ftruncate($fh, ftell($fh)); ## Die Datei an der Stelle abschneiden, an der der  
                                    ## Dateizeiger gerade steht (er steht auf der nächsten Byteposition,  
                                    ## daher ist die Länge gerade der Byteposition. Die Positionszählung  
                                    ## beginnt bei 0)  
        fclose($fh);                ## Datei schließen und Lock freigeben  
        
        return $count;              ## Den Counterwert zurückgeben  
      }  
      
      

      Die Anzahl, wann rückzusetzen wäre, könntest Du der Funktion ebenfalls als Argument übergeben

      Liebe Grüße aus dem schönen Oberharz

      Tom vom Berg

      --
      Nur selber lernen macht schlau
      http://bergpost.annerschbarrich.de
      Den obligatorischen (Ab-)Satz mit Uschi und Wolle verkneife ich mir diesmal
  2. Moin!

    Wie kann man dieses Problem möglichst einfach lösen? Ich weiß, für die Eingeweihten ist soetwas supereasy, aber ich bin in PHP und Datenbanken und so weiter gar nicht drinne, und vielleicht kann mir ja jemand aushelfen, bevor ich mich wegen so einem Miniproblem das Zeug ganz draufschaffen muß... Wäre jedenfalls supernett, wenn jemand helfen kann!

    Wenn jeder Proband eine fortlaufend aufsteigende Identifikationsnummer hat, kannst du diese Nummer einfach modulo 3 rechnen, erhältst dann 0, 1 oder 2, und kannst das als Ausgangswert für deine Weiterleitung zum richtigen Fragebogen verwenden.

    Ansonsten kannst du natürlich auch an einer zentralen Stelle mitzählen, wieviele Fragebögen schon ausgeliefert wurden, und von dieser Zahl modulo 3 ausgehen.

    - Sven Rautenberg