Avatar billede para7 Nybegynder
22. maj 2004 - 12:22 Der er 18 kommentarer og
3 løsninger

Random med retfærdighed

Jeg har en Access db med følgende felter:

ID | Firmanavn | Beskrivelse | Taeller | SidstVist | URLid | Aktiv |


Det er forhandlere, hvor én af dem skal vises ved hvert besøg på siden. Der må ikke være nogen, der "ved et tilfælde" næsten aldrig bliver vist. Derfor har jeg Taeller og SidstVist i min db.

Er nogen frisk på at hjælpe mig til at få integreret en retfærdig random udvælgelse ? Min kode er som udgangspunkt:

<%
strSQL = " select * from Forhandler where Aktiv = -1"
rs.open strSQL, conn
do until rs.EOF
    response.write "<font class='ParentSection_SectionTitle'>" & rs("Firmanavn") & "</font><br>"
    response.write "<div style='width:40%;font-style:italic'>"
    response.write rs("Beskrivelse") & "<br>"
    response.write "</div>"
    response.write "Vist " & rs("Taeller") & " gange<br>"
    response.write "Sidst vist " & rs("SidstVist") & "<br>"
    response.write "<a href='http://" & rs("URLid") & ".tni.dk' target='_blank' class='linkVisit'>" & rs("URLid") & ".tni.dk >></a><br>"
    response.write "<br>"
    strSQL = " update Forhandler set "
    strSQL =  strSQL & "Taeller =Taeller+1,"
    strSQL =  strSQL & "SidstVist ='" & nowCorr & "'"
    conn.execute(strSQL)
rs.movenext
loop
rs.Close
set rs = nothing
%>
Avatar billede vbcoder Nybegynder
22. maj 2004 - 13:11 #1
Opret et felt mere i din tabel der hedder vist af typen true/false med standardværdien 0

Nu kan du udelade dem som er blevet vist (værdi -1) og kun vælge random mellem dem som endnu ikke er vist.

Hvis alle er vist resettes alle til ikke vist og der startes forfra

<%
' udvælg alle som ikke er vist
strSQL = " select * from Forhandler where Aktiv = -1 AND Vist = 0"
rs.open strSQL, conn

' hvis alle er vist er recordset tomt og alle skal aktiveres igen
if rs.eof then
    'udvælg alle aktive
    strSQL = " select * from Forhandler where Aktiv = -1"
    do until rs.EOF
        'reset ved at sætte værdien 0
        strSQL = "update Forhandler set Vist = 0"
        conn.execute(strSQL)
        rs.movenext
    loop
    'udvælg alle aktive som ikke er vist
    strSQL = " select * from Forhandler where Aktiv = -1 AND Vist = 0"
    ' hent forhandlere
    rs.open strSQL, conn
end if

' din egen kode
do until rs.EOF
    response.write "<font class='ParentSection_SectionTitle'>" & rs("Firmanavn") & "</font><br>"
    response.write "<div style='width:40%;font-style:italic'>"
    response.write rs("Beskrivelse") & "<br>"
    response.write "</div>"
    response.write "Vist " & rs("Taeller") & " gange<br>"
    response.write "Sidst vist " & rs("SidstVist") & "<br>"
    response.write "<a href='http://" & rs("URLid") & ".tni.dk' target='_blank' class='linkVisit'>" & rs("URLid") & ".tni.dk >></a><br>"
    response.write "<br>"
    strSQL = " update Forhandler set "
    strSQL =  strSQL & "Taeller =Taeller+1,"

    'opdater forhandler med status vist
    strSql =  strSQL & "Vist=-1,"

    strSQL =  strSQL & "SidstVist ='" & nowCorr & "'"
    conn.execute(strSQL)
rs.movenext
loop
rs.Close
set rs = nothing
%>
Avatar billede vbcoder Nybegynder
22. maj 2004 - 13:12 #2
<%
' udvælg alle som ikke er vist
strSQL = " select * from Forhandler where Aktiv = -1 AND Vist = 0"
rs.open strSQL, conn

' hvis alle er vist er recordset tomt og alle skal aktiveres igen
if rs.eof then
    'udvælg alle aktive
    strSQL = " select * from Forhandler where Aktiv = -1"
    rs.open strSQL, conn
    do until rs.EOF
        'reset ved at sætte værdien 0
        strSQL = " update Forhandler set Vist = 0"
        conn.execute(strSQL)
        rs.movenext
    loop
    'udvælg alle aktive som ikke er vist
    strSQL = " select * from Forhandler where Aktiv = -1 AND Vist = 0"
    ' hent forhandlere
    rs.open strSQL, conn
end if

' din egen kode
do until rs.EOF
    response.write "<font class='ParentSection_SectionTitle'>" & rs("Firmanavn") & "</font><br>"
    response.write "<div style='width:40%;font-style:italic'>"
    response.write rs("Beskrivelse") & "<br>"
    response.write "</div>"
    response.write "Vist " & rs("Taeller") & " gange<br>"
    response.write "Sidst vist " & rs("SidstVist") & "<br>"
    response.write "<a href='http://" & rs("URLid") & ".tni.dk' target='_blank' class='linkVisit'>" & rs("URLid") & ".tni.dk >></a><br>"
    response.write "<br>"
    strSQL = " update Forhandler set "
    strSQL =  strSQL & "Taeller =Taeller+1,"

    'opdater forhandler med status vist
    strSql =  strSQL & "Vist=-1,"

    strSQL =  strSQL & "SidstVist ='" & nowCorr & "'"
    conn.execute(strSQL)
rs.movenext
loop
rs.Close
set rs = nothing
%>
Avatar billede para7 Nybegynder
22. maj 2004 - 18:52 #3
Det ser godt ud. Jeg kigger på det..
Avatar billede para7 Nybegynder
22. maj 2004 - 19:19 #4
Det virker ikke endnu, første opdatering af siden viser godtnok den første forhandler i db. Men alle bliver checket af i db, og ved næste opdatering:

ADODB.Recordset (0x800A0E79)
Handlingen er ikke tilladt, mens objektet er åbent.
default.asp, line 246
Avatar billede ellebaek Nybegynder
22. maj 2004 - 23:23 #5
er det her ikke lidt spild..?

do until rs.EOF
        'reset ved at sætte værdien 0
        strSQL = " update Forhandler set Vist = 0"
        conn.execute(strSQL)
        rs.movenext
    loop

synes det burde virke sådan her:

<%
' udvælg alle som ikke er vist
strSQL = " select * from Forhandler where Aktiv = -1 AND Vist = 0"
rs.open strSQL, conn

' hvis alle er vist er recordset tomt og alle skal aktiveres igen
if rs.eof then
rs.close
    'sæt alle til vist = 0
        strSQL = " update Forhandler set Vist = 0"
        conn.execute(strSQL)

    'udvælg alle aktive som ikke er vist
    strSQL = " select * from Forhandler where Aktiv = -1 AND Vist = 0"
    ' hent forhandlere
    rs.open strSQL, conn
end if

' din egen kode
do until rs.EOF
    response.write "<font class='ParentSection_SectionTitle'>" & rs("Firmanavn") & "</font><br>"
    response.write "<div style='width:40%;font-style:italic'>"
    response.write rs("Beskrivelse") & "<br>"
    response.write "</div>"
    response.write "Vist " & rs("Taeller") & " gange<br>"
    response.write "Sidst vist " & rs("SidstVist") & "<br>"
    response.write "<a href='http://" & rs("URLid") & ".tni.dk' target='_blank' class='linkVisit'>" & rs("URLid") & ".tni.dk >></a><br>"
    response.write "<br>"
    strSQL = " update Forhandler set "
    strSQL =  strSQL & "Taeller =Taeller+1,"

    'opdater forhandler med status vist
    strSql =  strSQL & "Vist=-1,"

    strSQL =  strSQL & "SidstVist ='" & nowCorr & "'"
    conn.execute(strSQL)
rs.movenext
loop
rs.Close
set rs = nothing
%>
Avatar billede vbcoder Nybegynder
23. maj 2004 - 06:16 #6
Jeg forstod på dit spm at du havde en random udvælgelse og derfor spekulerede jeg ikke på den.

mht fejlen så skal rs lukkes

<%
' udvælg alle som ikke er vist
strSQL = " select * from Forhandler where Aktiv = -1 AND Vist = 0"
rs.open strSQL, conn

' hvis alle er vist er recordset tomt og alle skal aktiveres igen
if rs.eof then

    ' luk ubrugeligt recordset
    rs.close

    'lav nyt recordset til at resette alle
    'udvælg alle aktive
    strSQL = " select * from Forhandler where Aktiv = -1"

    'åben rs med aktive
    rs.open strSQL, conn
   
    'loop rs og reset feltet vist hos alle
    do until rs.EOF
        'reset ved at sætte værdien 0
        strSQL = " update Forhandler set Vist = 0"
        conn.execute(strSQL)
        rs.movenext
    loop

    'nu har vi vores recordset med alle
    'aktive forhandlere og ingen er vist
end if

'den næste kode er fælles enten det førstenævnte recordset indeholdt
'nogle få records eller vi har resat og derfor har alle records
'
'Vi laver så en random på rs.recordcount og bruger rs.recordcount til
'placere os på den record der er udvalgt.
'
'her skal du lave din random og der kan bruges rs.recordcount som seed
'Int((upperlimit - lowerlimit + 1)*Rnd() + lowerlimit)

'variabler
dim rndForhandler
dim intNumRecords

'initer variabler
intNumrecords = rs.recordcount

'find en tilfældig forhandler baseret på recordcount
rndForhandler = Int((intnumrecords + 1)*Rnd() + 1)

'sæt dit recordset til den tilfældigt fundne forhandler
rs.absoluteposition = rndForhandler

'gammel loop skal ikke bruges
'do until rs.EOF

'udskriv link
    response.write "<font class='ParentSection_SectionTitle'>" & rs("Firmanavn") & "</font><br>"
    response.write "<div style='width:40%;font-style:italic'>"
    response.write rs("Beskrivelse") & "<br>"
    response.write "</div>"
    response.write "Vist " & rs("Taeller") & " gange<br>"
    response.write "Sidst vist " & rs("SidstVist") & "<br>"
    response.write "<a href='http://" & rs("URLid") & ".tni.dk' target='_blank' class='linkVisit'>" & rs("URLid") & ".tni.dk >></a><br>"
    response.write "<br>"

    ' opdaterings sql
    strSQL = " update Forhandler set " & _
            "Taeller =Taeller+1," & _
            "Vist=-1," & _
            "SidstVist ='" & nowCorr & "'"

    ' udfør opdatering
    conn.execute(strSQL)

'gammel loop slut skal ikke bruges
'rs.movenext
'loop

'oprydning
rs.Close
set rs = nothing
%>
Avatar billede para7 Nybegynder
23. maj 2004 - 09:41 #7
Tak til ellebaek for korrektioner. Og tak igen til vbcoder for veldokumenterede koder.

Jeg får nu:
"
ADODB.Recordset (0x800A0CB3)
Det aktuelle postsæt understøtter ikke bogmærker. Det kan skyldes en begrænsning af provideren eller af den valgte markørtype.
"
Hvordan er det nu der skal stå som option. Er det noget med ,1 når man åbner recordset og vil bevæge sig frit for og baglæns?
Jeg har tilføjet , 1:
"
rs.open strSQL, conn, 1
"
- og der kommer nu ikke fejl mere, men af de tre testforhandlere jeg har i db, vises kun den sidste med det højeste autonummererings ID. Og alle får check mark. Jeg kan ikke rigtigt overskue hvor fejlen ligger. Hjæælp..
Avatar billede para7 Nybegynder
23. maj 2004 - 09:49 #8
ellebaek
Med dine koder får jeg kun vist den forhandler med det laveste autonummer ID. Og alle bliver ligesom vbcoder's koder også checket af som vist.
Avatar billede para7 Nybegynder
23. maj 2004 - 09:54 #9
Jeg vil jo gerne have en løsning med random, så jeg satser på dine koder, vbcoder. Jeg ved det er lidt bøvlet hvis du skal lave en db for at teste selv. Men vi har vel også snart styr på det ?
Avatar billede para7 Nybegynder
23. maj 2004 - 10:40 #10
Jeg har i min test her tilføjet det med * og nu ser det ud til at virke. Random giver nu et tal fra 1-3.

"
'initer variabler
intNumrecords = rs.recordcount-1 '*

'find en tilfældig forhandler baseret på recordcount
Randomize '*Initialize random-number generator.
rndForhandler = Int((intNumRecords + 1)*Rnd() + 1)
response.write rndForhandler
response.end
"
Avatar billede para7 Nybegynder
23. maj 2004 - 10:53 #11
Men det er nu ikke OK endnu:
1.
Stadig får alle flueben som vist i db allerede ved første opdatering.

2.
Taeller tæller op så mange gange som det er siden en forhandler blev vist sidst.

3.
Retfærdighedsprincippet virker vist ikke endnu ?
Avatar billede ellebaek Nybegynder
23. maj 2004 - 17:14 #12
du mangler at fortælle hvor det er du skal have opdateret i databasen..


<%
' udvælg alle som ikke er vist
strSQL = " select * from Forhandler where Aktiv = -1 AND Vist = 0"
rs.open strSQL, conn

' hvis alle er vist er recordset tomt og alle skal aktiveres igen
if rs.eof then

    ' luk ubrugeligt recordset
    rs.close

    'lav nyt recordset til at resette alle
    'udvælg alle aktive
    strSQL = " select * from Forhandler where Aktiv = -1"

    'åben rs med aktive
    rs.open strSQL, conn
   
    'loop rs og reset feltet vist hos alle
    do until rs.EOF
        'reset ved at sætte værdien 0
        strSQL = " update Forhandler set Vist = 0"
        conn.execute(strSQL)
        rs.movenext
    loop

    'nu har vi vores recordset med alle
    'aktive forhandlere og ingen er vist
end if

'den næste kode er fælles enten det førstenævnte recordset indeholdt
'nogle få records eller vi har resat og derfor har alle records
'
'Vi laver så en random på rs.recordcount og bruger rs.recordcount til
'placere os på den record der er udvalgt.
'
'her skal du lave din random og der kan bruges rs.recordcount som seed
'Int((upperlimit - lowerlimit + 1)*Rnd() + lowerlimit)

'variabler
dim rndForhandler
dim intNumRecords

'initer variabler
intNumrecords = rs.recordcount

'find en tilfældig forhandler baseret på recordcount
rndForhandler = Int((intnumrecords + 1)*Rnd() + 1)

'sæt dit recordset til den tilfældigt fundne forhandler
rs.absoluteposition = rndForhandler

'gammel loop skal ikke bruges
'do until rs.EOF

'udskriv link
    response.write "<font class='ParentSection_SectionTitle'>" & rs("Firmanavn") & "</font><br>"
    response.write "<div style='width:40%;font-style:italic'>"
    response.write rs("Beskrivelse") & "<br>"
    response.write "</div>"
    response.write "Vist " & rs("Taeller") & " gange<br>"
    response.write "Sidst vist " & rs("SidstVist") & "<br>"
    response.write "<a href='http://" & rs("URLid") & ".tni.dk' target='_blank' class='linkVisit'>" & rs("URLid") & ".tni.dk >></a><br>"
    response.write "<br>"

    ' opdaterings sql
    strSQL = " update Forhandler set " & _
            "Taeller =Taeller+1," & _
            "Vist=-1," & _
            "SidstVist ='" & nowCorr & "' where id = " & rs.fields("id")

    ' udfør opdatering
    conn.execute(strSQL)

'gammel loop slut skal ikke bruges
'rs.movenext
'loop

'oprydning
rs.Close
set rs = nothing
%>
Avatar billede vbcoder Nybegynder
23. maj 2004 - 17:53 #13
www.visualcoder.dk/eksperten/501094

koden er her

<%
Option explicit

'variabler
dim rndForhandler
dim intNumRecords
dim conn
dim rs
dim strSql
dim nowCorr
dim taeller
dim ForhandlerID

Set Conn = Server.CreateObject("ADODB.Connection")
set Rs = Server.CreateObject("ADODB.Recordset")

Conn.open "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=" & Server.MapPath(".") & "/forhandler.mdb;PWD=admin;"

' udvælg alle som ikke er vist
strSQL = " select * from Forhandler where Aktiv = -1 AND Vist = 0"
rs.open strSQL, conn, 1

' hvis alle er vist er recordset tomt og alle skal aktiveres igen
if rs.eof then

    ' luk ubrugeligt recordset
    rs.close

    'lav nyt recordset til at resette alle
    'udvælg alle aktive
    strSQL = " select * from Forhandler where Aktiv = -1"

    'åben rs med aktive
    rs.open strSQL, conn, 1
   
    'loop rs og reset feltet vist hos alle
    do until rs.EOF
        'reset ved at sætte værdien 0
        strSQL = " update Forhandler set Vist = 0"
        conn.execute(strSQL)
        rs.movenext
    loop

    'nu har vi vores recordset med alle
    'aktive forhandlere og ingen er vist
end if

'den næste kode er fælles enten det førstenævnte recordset indeholdt
'nogle få records eller vi har resat og derfor har alle records
'
'Vi laver så en random på rs.recordcount og bruger rs.recordcount til
'placere os på den record der er udvalgt.
'
'her skal du lave din random og der kan bruges rs.recordcount som seed
'Int((upperlimit - lowerlimit + 1)*Rnd() + lowerlimit)

'initer variabler
intNumrecords = rs.recordcount
response.write ("intNumrecords = " & intNumrecords & "<br>")
nowCorr = now

' Hvis der er forhandlere i forhandler tabellen så
if intNumrecords > 0 then
  'sørg for at initere random
  randomize time
  'find en tilfældig forhandler baseret på recordcount
  rndForhandler = (Int((intnumrecords + 1)*Rnd() + 1))
 
  'kontrol af random forhandler
  'kan ikke være nul
  'og ikke større end antallet af records i tabellen
  if rndForhandler > intNumRecords then
    rndForhandler = rndForhandler -1
  end if
  if rndForhandler < 1 then
    rndForhandler = 1
  end if

  response.write ("rndForhandler = " & rndForhandler & "<br>")
 
  'sæt aktive record til den random forhandler
  rs.absoluteposition = rndForhandler
  forhandlerid = rs("ID")
 
  'udskriv link
      response.write "<font class='ParentSection_SectionTitle'>" & rs("Firmanavn") & "</font><br>"
      response.write "<div style='width:40%;font-style:italic'>"
      response.write rs("Beskrivelse") & "<br>"
      response.write "</div>"
      response.write "Vist " & rs("Taeller") & " gange<br>"
      response.write "Sidst vist " & rs("SidstVist") & "<br>"
      response.write "<a href='http://" & rs("URLid") & ".tni.dk' target='_blank' class='linkVisit'>" & rs("URLid") & ".tni.dk >></a><br>"
      response.write "<br>"
 
      ' opdaterings sql
      strSQL = "update forhandler set " & _
              "Taeller = " & rs("Taeller") + 1 & "," & _
              "Vist = -1," & _
              "SidstVist = '" & nowCorr & "' " & _
              "WHERE ID = " & forhandlerID & ";"
 
      ' udfør opdatering
      conn.execute(strSQL) 
else
  response.write ("Forhandlertabellen er tom" & "<br>")
end if

'oprydning
taeller = 0
rs.Close
set rs = nothing
%>
Avatar billede vbcoder Nybegynder
23. maj 2004 - 17:56 #14
Avatar billede vbcoder Nybegynder
23. maj 2004 - 17:56 #15
Så vidt jeg kan se virker det som du har tænkt dig
Avatar billede para7 Nybegynder
23. maj 2004 - 17:56 #16
Tak ellebaek (havde nær sagt ellehammer ;)
Nu ser det ud til at køre. 40 point til vbcoder og 20 til dig OK?
Send lige et svar.
Avatar billede ellebaek Nybegynder
23. maj 2004 - 17:59 #17
ok..
et svar ;-)
Avatar billede para7 Nybegynder
23. maj 2004 - 18:05 #18
Og tak for denne gang :)
Avatar billede para7 Nybegynder
23. maj 2004 - 18:08 #19
(jeg har trykket Accepter 3 gange nu uden knappen virker så pointene bliver fordelt ?)
Avatar billede para7 Nybegynder
23. maj 2004 - 18:10 #20
".. du selv angive point fordelingen" virker ikke. Jeg må forsøge at fordele lige mellem Jer.
Avatar billede para7 Nybegynder
23. maj 2004 - 18:10 #21
Det kunne godt lade sig gøre.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester