Ponizej przedstawie (o po krotce opisze) pewna funkcje. Powoduje ona przeliczenie punktow zdobywanych przez graczy w cos na wzor ligi typerow.
mamy zatem nastepujace elementy 'ukladanki'
- gracze
- rodzaj ligi
- numer kolejki
- zestawienie meczow
- wyniki wytypowanwe przez graczy
- punkty
<?php function calculateWeekScore(){ $week_id = $_REQUEST["week"]; //id kolejki/tygodnia rozgrywek $comp_id = $_REQUEST["comp_id"]; //id rodzaju ligi $competition = new Competition($comp_id); $competition_type = new CompetitionType($competition->comp_type_id); // tworze tablice wszystkich graczy typujacych w danej lidze $qry = "SELECT sysuser.id as id FROM sysuser, sysuser_competition WHERE sysuser_competition.competition_id = $comp_id AND sysuser_competition.sysuser_id = sysuser.id ORDER BY id ASC"; $sth = $dbh->prepare($qry); $sth->execute(); while ($row = $sth->fetch()) { $users[] = $row; } // tworze tablice meczow w danej kolejce $qry = "SELECT * FROM fixture WHERE competition_id = $comp_id AND week_id = $week_id ORDER BY id ASC"; $sth = $dbh->prepare($qry); $sth->execute(); while ($row = $sth->fetch()) { $fixtures[] = $row; } //loopuje tablice graczy foreach ($users as $user){ $total_score = 0; $no_of_predictions = 0; //dla kazdego gracza sprawdzam, czy wytypowal wynik (prediction) na dany mecz kolejki foreach ($fixtures as $fixture){ $qry = "SELECT * FROM predictions WHERE fixture_id = ".$fixture["id"]." AND user_id = ".$user["id"].""; $sth = $dbh->prepare($qry); $sth->execute(); $row = $sth->fetch(); if($sth->rowCount() > 0){ $no_of_predictions++; } // jesli gracz wytypowal wynik, pobieram typ (1, X lub 2) i margines zwyciestwa (jaka iloscia bramek wygrala zwyciezka druzyna) $prediction = $row["prediction"]; $prediction_id = $row["id"]; $margin = $row["margin"]; //porownuje typy w prawdziwymi wynikami if($fixture["result"] == $prediction){ if($fixture["result"] == "X"){ $score = $competition_type->draw_score; //jesli remis - przypisuje ilosc punktow jaka w danym typie ligi przysluguje za celne wytypowanie remisu }elseif($fixture["result"] != ""){ $score = $competition_type->winner_score; //jesli zwyciestwo - przypisuje ilosc punktow jaka w danym typie ligi przysluguje za celne wytypowanie zwyciezcy $margin_score = getMarginScore($margin_accuracy, $comp_id); // przypisuje punkty za dokladnosc trafienia wyniku (funkcja getMarginScore wysyla zapytanie do bazy - sprawdzana jest jedna tablica w bazie) if(!$margin_score){ $margin_score = 0; } if(!$score){ $score = 0; } } $overal_score = $score + $margin_score; $total_score = $total_score + $overal_score; }else{ $overal_score = 0; } // updatuje tablice typow dodajac ilosc punktow jaka w sumie zdobyl gracz za wytypowanie meczu $qry = "UPDATE predictions SET score = $overal_score WHERE id = $prediction_id"; $sth = $dbh->prepare($qry); $sth->execute(); $margin_score = 0; $score = 0; $margin_accuracy = 0; } //koniec petli porownujacej typy z wynikami (tablica fixtures[]) $user_id = $user["id"]; if($no_of_predictions == 0){ $no_prediction_users .= "$user_id,"; }else{ //jesli kolejka nie jest zakonczona, dodaje do tabeli sysuser_week_score calkowita ilosc punktow zdobytych za wytypowanie wszystkich meczow w danej kolejce. if(!isCompleted($week_id)){ $qry = "INSERT INTO sysuser_week_score (sysuser_id, week_id, competition_id, score) VALUES ('$user_id', '$week_id', '$comp_id', '$total_score')"; $sth = $dbh->prepare($qry); $sth->execute(); // jesli jest zakonczona, updatuje istniejacy wpis (mowiac 'zakonczona' mam na mysli, ze admin dokonal juz wczesniej kalkulacji wynikow przynajmniej raz) }else{ $qry = "UPDATE sysuser_week_score SET score = '$total_score' WHERE sysuser_id = $user_id AND competition_id = $comp_id AND week_id = $week_id"; $sth = $dbh->prepare($qry); $sth->execute(); } // w celu updatowania sumy punktow zebranych w calej grze, na przestrzeni wszystkich kolejek, pobieram sume punktow zdobytych w tej i wszystkich poprzednich kolejkach. Funkcja getAllWeeksScore wysyla proste zapytanie do jednej tablicy (sysuser_week_score) $all_weeks_score = getAllWeeksScore($user_id, $comp_id); // update tablicy sysuser_score zawierajacej pole z suma punktow zdobytych w calej grze. Tu w zasadzie powinienem zamienic delete i insert na jedno zapytanie update $qry = "DELETE FROM sysuser_score WHERE sysuser_id = $user_id AND competition_id = $comp_id"; $sth = $dbh->prepare($qry); $sth->execute(); $qry = "INSERT INTO sysuser_score (sysuser_id, competition_id, score, last_week_score) VALUES ('$user_id', '$comp_id', '$all_weeks_score', '$total_score')"; $sth = $dbh->prepare($qry); $sth->execute(); } } // gracze, ktorzy nie dali zadnych typow w danej kolejce, otrzymuja usredniona ilosc punktow innych graczy (to nie moj wymysl, ino klienta :) ) //zatem, getAvgWeekScore wykonuje zapytanie na jednej tablicy sumujac punkty poszczegolnych graczy, zdobytych w bierzacej kolejce. Funkcja zwraca ilosc tych punktow podzielona oczywiscie przez ilosc graczy $avg_score = getAvgWeekScore($comp_id, $week_id); //wszyscy ci gracze, ktorzy nie wzieli udzialu w typowaniu w danym tygodniu, zostali wczesniej wpisani do zmiennej $no_prediction_users (string z id graczy po przecinkach) // funkcja updateUsersAvgScore 'exploduje' ta zmienna wyluskujac id graczy, a nastepnie odpala foreach dla kazdego gracza. W petli tej odbywa sie dokladnie to samo co mialo miejsce dla graczy, ktorzy typowali... tyle, ze tym razem nie ma porownania typow z wynikami. Odbywa sie zatem dodanie sredniej ilosci punktow do tablicy sysuser_week_score (punktacja w kolejnych kolejkach), zsumowanie punktow z calej gry (getAllWeeksScore) i wpisanie ich do tablicy z punktami (sysuser_score) updateUsersAvgScore($no_prediction_users, $avg_score, $comp_id, $week_id); // zamkniecie kolejki $qry = "UPDATE week SET completed = 1 WHERE id = $week_id;"; $sth = $dbh->prepare($qry); $sth->execute(); } ?>
Problem polega na tym, ze przy okolo 300 graczach, cala operacja trwa koszmarnie dlugo (2-3 minuty zanim strona zostanie odswiezona). Potrzebuje porady w jaki sposob zoptymalizowac funkcje aby dzialala szybciej. Jesli cos jest nie jasne albo potrzebujecie wiecej informacji, pytajcie...
Dzieki z gory za pomoc