24. november 2010 - 10:36Der er
35 kommentarer og 1 løsning
PHP Interval - matematisk helvede
Kære Eksperter. Mangler jeres hjælp!
Lad os antage Anders opretter en opgave i mit system.
Her skal den så sige: o Brugere med rating over 4 får opgaven tilsendt med det samme.
o Brugere med en rating over 3 bliver synlige 30 minutter efter oprettelsestidspunktet af opgaven.
o Resten (Brugere under en rating på 3) - bliver synlig en time efter, hvis der stadig er opgaver, der ikke er fuldført.
o Hvis der er gået 4 timer, og der stadig er ledige tests (ingen som har accepteret opgaven), så udsendes en mail til alle testere.
Hvordan laver jeg dette rent praktisk med struktur? Jeg mener, jeg har et felt som hedder "oprettelsestidspunkt" i min db, hvor det er tidspunktet en opgave er blevet oprettet på.
Der skal være køre noget cronjob etc., men hvor tit, hvordan og hvorledes?
Er der en klog en der vil komme med kodeeksempler og et godt råd til at komme i gang?
$e = mysql_query("SELECT * FROM test WHERE aktiv = 1"); while ( $row = mysql_fetch_assoc($e ) ) {
//Tjek om opgaven er blevet oprettet for 30 min. siden if ( $row['tid'] >=( time()-1800)) { //Tjek om nogen har accepteret denne opgave endnu.
$tjek = mysql_query("SELECT id FROM accepteret WHERE opgave_id = '".$row['id']."' AND accepteret = 1"); if ( mysql_num_rows ( $tjek ) >= $row['antal_brugertest']) { // Ikke brug for flere testere. } else { //Der er brug for flere testere, derfor send til dem med rating på over 3.
$HentBrugere = mysql_query("SELECT * FROM testere WHERE aktiv = 1"); while ($r = mysql_fetch_assoc($HentBrugere ) ) { $rating = mysql_query("SELECT AVG(rating) AS rating FROM rating WHERE tester = '".$r['id']."'"); $ratingn = mysql_fetch_assoc($rating);
if ( $ratingn == 3 ) { //Udsend til tester } } } }
Det mest praktiske ville egentlig være at give dine opgaver et status-felt også som eventuelt hænger sammen med rangen:
<?php
// Nyoprettede opgaver oprettes med opgavestatus 4 og opgaven ikke er udført $sql = "SELECT * FROM opgaver WHERE opgavestatus != 0 AND aktiv = 1"; $res = mysql_query($sql);
while( $row = mysql_fetch_object($res) ) { // En hurtig sætning til at opdatere den pågældende opgave, om nødvendigt. $sql = "UPDATE opgaver SET opgavestatus = opgavestatus - 1 WHERE opgaveId = ".$row->opgaveId;
// Alderen på opgaven kan vi jo godt hente $age = time() - strtotime($row->oprettelsestidspunkt);
if($row->opgavestatus == 4) { // send til alle med rang 4 eller derover }
if($row->opgavestatus == 3) { // Hvis ikke opgaven er 30 min (eller mere) gammel, skal databasen ikke opdateres og vi fortsætter (vha. 'continue') vores løkke med næste opgave if( $age < 1800 ) continue;
// Hvis opgaven er 30 min gammel, kan vi godt opdatere databasen. // Opdater blot status til opgavestatus 2, så du kan sætte den ind på hjemmesiden for rang 3 brugere efter 30 minutter }
if($row->opgavestatus == 2) { // Igen - her behøver vi ikke foretage os noget, hvis den pågældende opgave ikke er blevet mere end en time gammel if( $age < 3600 ) continue;
// Opdater blot status til opgavestatus 1, så du kan sætte den ind på hjemmesiden for brugere under rang 3 efter en time }
if($row->opgavestatus == 1) { // Er den fire timer gammel? Ellers hopper vi bare videre... if( $age > 14400 ) continue;
// Send mail ud til alle brugere under rang 4 med opgaven (så brugerne med rang 4 og derover ikke får den samme mail) // Opdater status til opgavestatus 0, så du kan sætte den ind på hjemmesiden for alle }
//Opdater databasen, hvis ikke en 'continue' er mødt mysql_query($sql);
opgavestatus er et feltnavn (et integer) du skal tilføje til tabellen i databasen. Og som jeg skrev i koden, skal alle nystartede opgaver starte med opgavestatus 4.
Min kode er et cronjob, som skal køre hvert minut (eller lignende). Hvert minut vil den så kontrollere opgavens statusnummer og agere ud fra det. Hvis opgaven har status 3, skal den ikke gøre noget før de 30 minutter er gået:
if( $age < 1800 ) continue;
Hvordan du kontrollerer rangen, må du selv om - det er nogle ting der skal ind imellem de if-sætninger der bestemmes af af statusopgaven og tiden.
Dit cronjob vil jo kun gøre noget med opgaverne hvis de er mindst 30 minutter gamle - sender du opgaven til brugere med rating 4+ på en anden måde, så?
Og hvad er det lige du laver på linierne 20-22?
Du laver mangle SQL kald henover de to while løkker. Hvorfor har du en 'accepteret' tabel? Er der mere end en tester der kan påtage sig opgaven?
Der mangler desuden også noget af koden - din yderste while bliver ikke afsluttet.
Hvorfor kunne du ikke bruge noget af det jeg gav i mit eksempel?
Rating 4 (Dvs. de skal have opgaven med det samme) får den bare tilsendt på samme side når en kunde har oprettet en opgave.
Linje 20-22 tjekker jeg om der er flere "pladser". Da en kunde kan vælge om de f.eks ønsker 20 testere. Så skal den jo ikke sende hvis de er ikke e ledige pladser.
Accepteret -tabellen tjekker om en bruger har accepteret med tidspunkt.
Ved flere ratings, laver jeg en ny fil og ændre sekund-tallet og kører dem hvert 10 min også... Er det en dålig løsning da?
Problemet er, at jeg ikke helt forstår din måde at gøre tingene på.
Selvfølgelig. Har deadline i morgen, så hvis du kan nå at strikke en løsning op, så kvitter jeg naturligvis med lidt penge eller en god vingave.
accepteret:
id - bare ID tester_id - hvem er testeren der har accepteret eller fået tildelt? opgave_id - hvilken opgave taler vi om? accepteret - enten 0 eller 1 . 0 er nej 1 er ja accepteret_tidspunkt - timestamp (unix), fortæller hvornår testeren trykkede accepter opgave i deres oversigt done - enten 0 eller 1 = 0 er nej 1 er ja.
ratings: id - id kunde - kunde id (hvem har ratet?) tester - tester id (hvem er testeren?) opgave - opgave id (hvilken opgave er der tale om?) rating - hvilken rating er der gået? 1-5
-- her tager jeg gennemsnittet (AVG(..)) for at fange brugerens rating gennemsnit.
test:
antal_test - hvor mange tests ønsker kunden? kunde_id - hvilken kunde er er der tale om? afsluttet - 0 eller 1 = 0 er nej 1 er ja tid - hvornår er testen oprettet (unix time) oprettet - hvornår er testen oprettet i NOW() format aktiv - er opgaven aktiv? 0 = nej, 1 = ja prove - er det en prøvetest? Den skal ikke tage med, hvis prove er 1.
gør ikke andet end springer den aktuelle opgave over, hvis den ikke er mindst en halv time gammel.
if( $alder > 3600 ) $rating = 0;
sørger blot for at alle, som har en rating med og over 0, skal modtage opgaven, hvis ikke de allerede har modtaget den - ellers vil rating være 3, hvis opgaven er mellem en halv og en hel time gammel.
Og ja, den tjekker om potentielle modtager allerede har modtaget den.
Ellers, tak - jeg nøjes bare med et accepteret svar :)
Det vil ikke virke - du har mange mangler i både data og indkapslinger. Samtidig ændrer du i logikken og laver duplikerende kode- det er altså lidt svært at holde motivationen oppe til at hjælpe dig færdig med dette, når du laver så meget om i koden; Så vidt jeg kan se - ud fra din kode - er det åbenbart kun nødvendigt at få dit cronjob til at sende en mail ud til dine testere, hvis opgaven er mere end fire timer gammel og den ikke er udført efter kriterierne - hvilket gør det meste af koden overflødig.
Den tjekker om en test er halv time gammel, og tjekker om de allerede har accepteret den og der er ledige pladser derfor send til dem med rating 4.
Den tjekker om en test er en time gammel, og tjekker om de allerede har accepteret den og der er ledige pladser derfor send til dem med rating 3.
Den tjekker om en test er en 4 gammel, og tjekker om de allerede har accepteret den og der er ledige pladser derfor send til alle, og udsend mail med det.
Jeg skal lige have nogle ting på plads, med det rating og mail halløj, selvom du sikkert synes du har besvaret det et par gange:
1. Du fortæller på et tidspunkt at opgaven bliver sendt ud til brugere med rating 4 og derover når den bliver oprettet. Men i #21 fortæller du at cronjobbet skal, hvis opgaven er mindst en halv time gammel, sende en mail ud til brugere med rating 4, hvis de ikke har påtaget sig opgaven. Hvad er det præcist der skal ske efter en halv time?
2. Hvad skal der præcist ske efter en time?
3. Og hvad skal der præcist ske når den er 4 timer gammel?
Sendt ud, mener jeg den havner i deres oversigt når de logger ind, har lige hørt fra "the boss", at den kun skulle udsende en EMAIL når det er mere end 4 timer siden.
Dvs. halv time gammel, tilføj til "brugertest_accepteret( ... ) " og IKKE send e-mail.
Samme med efter en time.
Blot effter 4 timer, skal den både indsætte i accepteret-databasen samt sende mail ud til alle testerne :)
Så 'brugertest_accepteret' tabellen, bruges til at vise opgaverne på testernes oversigt og er egentlig ikke en indikation på at en bruger har accepteret en opgave?
Mjaeh, ikke uden at ændre tabel strukturen, så du kan fortælle cronjobbet at admin allerede har fået en mail - ellers vil du jo i princippet modtage en email for hver gang cronjobbet kører indtil der ikke er flere ledige tests på den pågældende opgave.
Så jo, det er da muligt - men så skal du lave et felt mere i din brugertest_test tabel til at kontrollere op imod...
Ja - noget i den stil; men du mangler naturligvis stadig det hvor du opdaterer tabellen som fortæller om der faktisk er sendt en mail ud til admin eller ej.
Ok, men så hvis jeg kører cronjob hver 10 min., bliver den vel ved med at udsende mails til testerne?
if ( $sendmail == 1 ) { $tjekModtaget = mysql_query("SELECT id FROM brugertest_harmodtaget WHERE opgave = '".$opgave['id']."' AND bruger = '".$bruger['id']."'"); if ( mysql_num_rows($tjekModtaget)==0) { $htmlMail = file_get_contents("mailheader.php"); mail($bruger['email'], "Der er ny brugertest klar!", $htmlMail, $header); mysql_query("INSERT INTO brugertest_harmodtaget (opgave, tester) VALUES ('".$opgave['id']."','".$bruger['id']."')"); } else { }
Tak Repox. Har oprettet et nyt spørgsmål lign. dette også. Send mig din email så sender jeg dig 500 kr.
Synes godt om
Ny brugerNybegynder
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.