[Pomysł] Nasz serwer statystyk

Zaczęty przez krzyszp, 13 Listopad 2010, 14:18

krzyszp

Cytat: mimeq w 19 Listopad 2010, 21:32
Tu nie widze "apostrofów", reszta wyglada ok 
Zrobione :)

Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

Troll81

 :respect: :respect: :respect:

krzyszp

#82
Co widać w podpisie, pierwsze wykresy się generują.
Statystyka województw gotowa do zamieszczenia, jeszcze tylko sformatować liczby :)

Edit:
Czy tylko mi tak powoli przeładowują się strony w dziale statystyk?

Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

mimeq

U mnie ok, nie ma wiekszej roznicy  w porownaniu do reszty.
"przyczepie" sie znow:

1. Top10 grup i Top10 liczydlowych moglyby byc znow separatory w liczbach jak juz pisalem  ;) Najlepiej wyglada wedlug mnie to tu:

Razem punktów
3 088 513 054,27
Poprzednia aktualizacja punkty
3 450 929 797,41

2.Oddzialy wewnetrzne B@P:

Krzysztof Piszczek - wspieram Stowarzyszenie Polski Projekt Boinc zgromadził 4'817'534.30 punktów

Ta grupa zdobyła: 123'150'510.02 punktów.

1 osoba w grupie majaca 4mln pkt. skad w sumie grupy 123mln ?

EDIT:
Jesli to tylko podgrupa BOINC@Poland to chyba nie powina byc w Top10 nad B@P


krzyszp

Cytat: mimeq w 20 Listopad 2010, 19:34
U mnie ok, nie ma wiekszej roznicy  w porownaniu do reszty.
"przyczepie" sie znow:

1. Top10 grup i Top10 liczydlowych moglyby byc znow separatory w liczbach jak juz pisalem  ;) Najlepiej wyglada wedlug mnie to tu:

Razem punktów
3 088 513 054,27
Poprzednia aktualizacja punkty
3 450 929 797,41

2.Oddzialy wewnetrzne B@P:

Krzysztof Piszczek - wspieram Stowarzyszenie Polski Projekt Boinc zgromadził 4'817'534.30 punktów

Ta grupa zdobyła: 123'150'510.02 punktów.

1 osoba w grupie majaca 4mln pkt. skad w sumie grupy 123mln ?

EDIT:
Jesli to tylko podgrupa BOINC@Poland to chyba nie powina byc w Top10 nad B@P

Generalnie poprawiłem błędy z formatowaniem liczb, wynikały z cache joomli...
Natomiast, co do wyników grupy Emigrancji, to miałem błąd w jednej pętli i punktacja tej grupy była sumą punktów dwóch pozostałych :) To też powodowało takie, a nie inne umiejscowienie jej w tabeli ;)

Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

mimeq



krzyszp

Jest sobie tabela z wynikami zawierająca kolumny:
ScoreID|UserID|ProjectID|Date|Score
Potrzebuję dla konkretnego UserID uzyskać listę wyników oraz projektów (ProjectID) za ostatnie siedem dni. Ktoś ma ochotę napisać zapytanie? :)

Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

Karlik

SELECT ProjectID, Score FROM tabela WHERE UserID=:x AND Date>DATE_ADD(NOW(), INTERVAL -7 DAY)Chyba, że masz bardziej skomplikowane wymagania albo ja nie zrozumiałem jak jest zbudowana tabela (w sensie co zawiera).

krzyszp

Generalnie o to chodziło, a ja miałem zaćmienie (czytaj: kac mnie dziś męczy)...

Fajnie by było stworzyć też zapytanie, które zwróci wyniki tylko dla projektów w których zmieniły się wyniki od dnia poprzedniego, to da nam wykresy dla projektów w których liczymy.


Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

apohawk

SELECT dzis.projectid, dzis.score FROM tabela AS dzis, tabela AS wczoraj WHERE dzis.projectid = wczoraj.projectid AND dzis.userid = wczoraj.userid AND dzisiaj.date = "dzisiaj" AND wczoraj.date = "wczoraj" AND NOT dzisiaj.score = wczoraj.score;"dzisiaj" i "wczoraj" sobie jakoś wylicz. Dla konkretnego użytkownika zamień dzisiaj.userid=wczoraj.userid na dzisiaj.userid = stefan.
Tylko to trochę masakratorskie chyba będzie.

Może lepiej pobrać część wyników, a potem obrobić w kodzie. Będzie prościej i mniej użerania się z datą.
SELECT projectid, score, date FROM tabela WHERE userid = stefan AND date > "wczoraj";Wczoraj podać bez godziny, to chyba 00:00:00 będzie i się timestamp porówna bez problemu. A potem to sobie do jakiejś tablicy asocjacyjnej wrzucić i porównać. Chyba będzie sprawniej.
No good deed goes unpunished.

krzyszp

Pierwsze zapytanie nie bardzo mogę zrozumieć, co masz namyśli pisząc dzis.projectid i dzis.score?

Problem z drugim jest taki, że serwery podają w plikach aktualne punkty, a nie tylko przyrost i ja tak samo zapisuję je w bazie, np.:
Budowa tabeli:

CREATE TABLE `tblScores` (
 `ScoreID` int(10) NOT NULL AUTO_INCREMENT,
 `UserID` int(10) NOT NULL,
 `ProjectID` int(11) NOT NULL,
 `Date` date NOT NULL,
 `Score` double(15,2) DEFAULT NULL,
 PRIMARY KEY (`ScoreID`),
 KEY `ProjectID` (`ProjectID`)
) ENGINE=InnoDB AUTO_INCREMENT=135412 DEFAULT CHARSET=latin1

Przykładowa zawartość:

'ScoreID', 'UserID', 'ProjectID', 'Date', 'Score'
118007, 1, 96, '2010-11-20', 237907.69
10828, 1, 96, '2010-11-11', 236457.63
114322, 1, 99, '2010-11-20', 100127.41
58176, 1, 99, '2010-11-15', 100127.41
86649, 1, 99, '2010-11-18', 100127.41

Jak widzisz, dla usera o id=1 i projektu o id = 96 wyniki były za każdym razem inne (rosnąco), ale już przy projekcie o id = 99 się nie zmieniają, co oznacza, że user go nie liczy lub projekt już nie jest aktywny... Te wyniki właśnie chcę odsiać i budować wykres z aktywnych projektów czyli w tym wypadku tych, które user liczy (dostaje punkty). Te wyniki chciałbym dostać dla ostatnich siedmiu dni, gdyż chcę załatwić także wykres z wynikami/punktami usera za ostatnie 7 dni. Całość odpaliłbym w pętli dla wszystkich 6400 userów i wygenerował sygnaturki :)

Jeszcze jedno - wolałbym jak najwięcej roboty zrzucić na serwer z bazą danych (stoi u mnie w biurze) zmniejszając tym samym obciążenie na serwerze...

Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

apohawk

SELECT dzis.projectid, dzis.score FROM tblScores AS dzis, tblScores AS wczoraj WHERE dzis.projectid = wczoraj.projectid AND dzis.userid = wczoraj.userid AND dzisiaj.date = "dzisiaj" AND wczoraj.date = "wczoraj" AND NOT dzisiaj.score = wczoraj.score;
Masz poprawione, wcześniej nie znałem nazwy tej tabeli. Chyba, że mysql nie wspiera "AS" i nie poradzi sobie z takim joinem, iloczynem kartezjańskim w zasadzie.
Zrobi się O(n^2) na całej tabeli i pewnie będzie masakra. Może query scheduler coś wykombinuje, ale po co go przemęczać.
A odsiać po indeksie z date, a potem na mocno przesianym zbiorze porównać parę rzeczy, to już w PHP czy w czym tam piszesz powinno być szybciutko, bo w pamięci.
np. tablica asocjacyjna tablica[(projectid,userid)]=(dzisiaj.score,wczoraj.score), kluczem jest krotka i wartością też krotka, a uzupełniasz ją liniowo przeglądając rezultat z bazy z drugiego query.
Albo inaczej, też jednym przebiegiem przeglądasz ten rezultat, ale dla daty wczorajszej robisz tablica[(projectid,userid)]-=score, a dla dzisiejszej tablica[(projectid,userid)]+=score, o ile czytasz dane w integerach. Potem jeszcze jeden przebieg filtrujący zera po tej tablicy i gotowe.
No good deed goes unpunished.

krzyszp

#92
To zapytanie niestety nie przejdzie. Nie ma możliwości zrobić zapytanie używając formy "dzis.projectid" (czy też za "dziś" wstawiając datę)...
Ok, zrozumiałem :) Podstawić tblScore zamiast dzis.
Oczywiście MySQL obsługuje "AS", z tym nie ma problemu, ale dane dla score są typem double, chyba, że na potrzeby obliczeń przemnożę je przez 100 a potem podzielę (są zawsze dwa miejsca po przecinku).

Ps. Ostatnie zdanie z poprzedniego postu, zabrakło wyrazu "hostowanym"... :)

Edit:
Popracowałem trochę nad zapytaniem:

SELECT ProjectID, Score FROM tblScores AS dzis, tblScores AS wczoraj WHERE ProjectID = ProjectID AND UserID = UserID AND tblScores.Date = '2010-11-20' AND Date = '2010-11-19' AND NOT Score = Score;


Niestety "Column 'ProjectID' in field list is ambiguous"... Dziś jestem już padnięty, jutro nad tym poprcuję...

Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

Karlik

Cytat: apohawk w 21 Listopad 2010, 23:35
SELECT dzis.projectid, dzis.score FROM tblScores AS dzis, tblScores AS wczoraj WHERE dzis.projectid = wczoraj.projectid AND dzis.userid = wczoraj.userid AND dzisiaj.date = "dzisiaj" AND wczoraj.date = "wczoraj" AND NOT dzisiaj.score = wczoraj.score;
Zrobi się O(n^2) na całej tabeli i pewnie będzie masakra. Może query scheduler coś wykombinuje, ale po co go przemęczać.
A odsiać po indeksie z date, a potem na mocno przesianym zbiorze porównać parę rzeczy, to już w PHP czy w czym tam piszesz powinno być szybciutko, bo w pamięci.
A może tak jawnym joinem:
SELECT dzis.projectid, dzis.score FROM tblScores AS dzis
JOIN tblScores AS wczoraj ON (
dzis.projektid = wczoraj.projectid
AND  dzis.userid = wczoraj.userid
AND NOT dzisiaj.score = wczoraj.score --wg Twojego zapisu, osobiście wolę znak nierówności ;)
) WHERE dzisiaj.date = "dzisiaj" AND wczoraj.date = "wczoraj"

Nie wnikałem w dokumentację, ale powinien w tym wypadku nie tworzyć pełnej tablicy n^2, więc mocno zaoszczędzi się na pamięci (i siłą rzeczy lekko przyspieszy). Zaznaczam, że nie testowałem tego rozwiązania, więc może nie działać. Dodatkowo można dodać jeden warunek datowy do JOINa (na zasadzie wczoraj.date ma być o ileś mniejsze od dzis.date i wywalić wczoraj.date="wczoraj"). Co nie zmienia faktu, że to cały czas jest O(n^2). Można ew. kombinować z subquery.

Co zaś do powyższego błędu to krzyszp: używasz nazwy kolumny (pola), ale nie podajesz z której tablicy, więc się nie dziw, że nie chce działać.

krzyszp

Tak trochę się nudząc, wygenerowałem jeszcze jeden wykresik:

Kawałek kodu generuje go automatycznie dla wszystkich, którzy się zarejestrowali w serwisie i scalili swoje konto, wystarczy na końcu adresu (nazwa pliku) wpisać swoje ID z bazy danych serwisu (widoczne w prawym dolnym rogu po zalogowaniu) plus cyfrę 7. Np. dla mnie id=320 więc nazwa pliku będzie 3207.png

Wykres korzysta z nowej tabeli, tak więc na razie są tam tylko dwa dni, później będzie 7 :)

Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

apohawk

Ten przyrost na tym wykresie to tak nie bardzo widać  XP
No good deed goes unpunished.

krzyszp

Cytat: apohawk w 22 Listopad 2010, 16:02
Ten przyrost na tym wykresie to tak nie bardzo widać  XP
Jak ktoś zrobi sobie 50% punktów więcej codziennie to będzie widać  XD

Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

Karlik

Cytat: krzyszp w 22 Listopad 2010, 15:57
Wykres korzysta z nowej tabeli, tak więc na razie są tam tylko dwa dni, później będzie 7 :)
Mam nadzieję, że nie dublujesz sobie danych. Nie wiem jak z wydajnością, bo może faktycznie to jedyne rozwiązanie, ale polecałbym zainteresować się widokami (tymczasowymi, automatycznie generowanymi tabelami - tak w uproszczeniu).

krzyszp

Część danych faktycznie się dubluje (ok. 10%), ale w tej chwili to nie problem, te dane są u mnie na serwerze, więc miejsca jest sporo.
Widoki w tej chwili nie są konieczne, raczej staram się używać tabel tymczasowych (aktualnie 2) z zawartością generowaną raz dziennie (ale jak opracujemy lepszą metodę aktualizacji bazy z projektów, to będzie np. co godzinę).

Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

Szopler

Pobawiłem się chwilę - może się przyda:
$UserName = '"[BOINC@Poland] Szopler"';
$Score = 10000;

$query = ("SELECT `UserID` FROM `tblusers` where `UserName`=".$UserName);
$result = mysql_query($query);
$wektor = mysql_fetch_array($result);

echo '<p>'.'UserID: '.$wektor['UserID'].'</p>';
//$UserID = $wektor['UserID'];

$query = ("SELECT `ProjectID`,`Score` FROM `tblscores` WHERE `UserID`=".$wektor['UserID']." and `Score` >".$Score." ORDER BY `Score` DESC");
$result = mysql_query($query);
@$num_results = mysql_num_rows($result);

$il_projektow = $num_results;
echo '<p>'.'Ilość ProjectIDs dla: KREDYTY>'.$Score.' : '.$il_projektow.'</p>';

for ($i=1;$i<=$il_projektow;$i++)
{
$tablica = mysql_fetch_array($result);
$project_id[$i] = $tablica[0];

$query1 = ("SELECT `ProjectName` FROM `tblprojects` WHERE `ProjectID`=".$project_id[$i]);
$result1 = mysql_query($query1);
$tablica1 = mysql_fetch_array($result1);
echo '<br>'.$tablica1[0].' - '.$tablica[1];

}


Tekstowa wersja sygnaturki.
Wyświetla nazwę projektu i ilość punktów w projekcie.
Posortowane po ilości punktów (malejąco). Dodatkowo można wpisać ilość punktów powyżej której ma wypisywać projekty.

krzyszp

#100
Dzięki :)
Jutro to wrzucę na serwer, z userami w pętli (wszystkimi) i w formie graficznej... A przynajmniej spróbuję (chyba nie będzie problemu)...

Ps. Różnica między MySQL na Win X P i Linuksie jest taka, że na windzie nie jest rozróżniana wielkość liter. Musisz trochę na to uważać, bo potem dłuuugo można szukać błędu ;)

Edit:
Niestety, masz ten sam błąd, który i ja popełniałem... wyniki zwracane przez Twój skrypt też podają projekty, w których punktacja się nie zmieniła... Wiem, że można to ogarnąć programowo z poziomu PHP, ale bardziej elegancko było by to zrobić z poziomu SQL'a :)

Dla chętnych do zabawy, dzisiejszy zrzut bazy jest pod adresem http://krzyszp.info/KP/web115-kpbbb.sql.zip

Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

Karlik

Cytat: Szopler w 22 Listopad 2010, 21:28

for ($i=1;$i<=$il_projektow;$i++)
{

$query1 = ("SELECT `ProjectName` FROM `tblprojects` WHERE `ProjectID`=".$project_id[$i]);
(...)

}

Wysoce odradzam takie zagrywki, tym bardziej, że piszesz niskopoziomowo (używając frameworków czasem trudno to obejść). Pobierz z bazy RAZ i przetwórz w PHP. Szczególnie ważne to jest jeżeli masz mysql na innym serwerze niż php, ograniczasz liczbę potrzebnym połączeń/przesyłanych informacji.

krzyszp

To właśnie jeden z powodów dla których proszę o pomoc we właściwym sformułowaniu zapytań.
Oczywiście, wyjątkiem jest pętla, w której muszę to powtórzyć dla każdego usera osobno (choć i to dałoby się obejść), jednak sam mam ograniczony czas i umiejętności do robienia takich konstrukcji zwłaszcza, że do stronki siadam zwykle po zakończeniu normalnej pracy...

Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

buninek

#103
Cytat: krzyszp w 22 Listopad 2010, 19:17
[...]ale jak opracujemy lepszą metodę aktualizacji bazy z projektów, to będzie np. co godzinę.
Tak jak pisałem na priv ze skryptami w shellu nie mam do czynienia i zupełnie nie znam zasad ich poprawnego pisania. Możesz spróbować skorzystać z tego łamańca. Wydaje się, że działa. Po licznych poprawkach może uda się go wykorzystać.

#!/bin/sh
KAT=/mnt/hdd2/Temp/stats
DANE=/tmp/users

echo > $DANE/log.wget
if [ -f $DANE/newfile ]; then
rm -f $DANE/newfile
fi
inotifywait -m -r -q -o $DANE/newfile -e close_write $KAT >/dev/null &
pid=$!

cut -f2 $DANE/linki | while read f
do
wget -t 1 -T 30 -a $DANE/log.wget -N -P $KAT/$(echo $f | sed 's|^http://\([^/]*\)/.*|\1|') $f
done
kill -3 $pid

sed 's/ CLOSE_WRITE,CLOSE //' $DANE/newfile | while read line
do
TEAMID=$(cgrep "$(echo $line | cut -d/ -f6)" $DANE/linki | cut -f3)
gzip -cd $line | cgrep -D -w '<user>' +w '<\/user>' "^[\t ]*<teamid>$TEAMID</teamid>$" | sed -e '1i<users>' -e '$a<\/users>' | xsltproc -o $KAT/$(echo $line | cut -d/ -f6)/last.txt $DANE/users.xsl -
done

sed 's/ CLOSE_WRITE,CLOSE user.*gz/last\.txt/' $DANE/newfile | while read last
do
PROJECTID=$(cgrep "$(echo $last | cut -d/ -f6)" $DANE/linki | cut -f1)
PROJEKTKAT=$(echo $last | cut -d/ -f6)
:
if [ -e "$KAT/$PROJEKTKAT/first.txt" ]; then
  diff -a $KAT/$PROJEKTKAT/first.txt $last | sed -e '/^> /!d;s/^> //' -e "s,^,$PROJECTID|,g" >> $DANE/inserts
else
  cp $last $KAT/$PROJEKTKAT/first.txt
  sed "s,^,$PROJECTID|,g" $last >> $DANE/inserts
fi
done
#mysql -c "LOAD DATA LOCAL INFILE '$DANE/inserts' INTO TABLE users LINES TERMINATED BY '|';"
cp $DANE/inserts $DANE/inserts.prev

Do prawidłowego działania potrzebny jest cgrep
http://downloads.sourceforge.net/cgrep/cgrep-8.15.tar.gz
i z repozytorium
-inotifywait z pakietu inotify-tools,
-xsltproc (u mnie paczka libxslt-progs, szukać pod libxslt)

Można również zainstalować xmlstarlet.

1. Z bazy zrzucić do pliku "linki" w katalogu (DANE)
PROJECTID, pełny link do pliku user.gz, TEAMID
Wszystkie pola rozdzielone tabulatorem. Oczywiście mowa o projektach aktywnych w których nasz team uczestniczy.
Cytat1       http://abcathome.com/stats/user.gz      45
2       http://boinc.almeregrid.nl/stats/user.gz        89
...
Do katalogu wrzucić plik users.xsl z taką zawartością
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="no" method="text"/>
<xsl:param name="inputFile">-</xsl:param>
<xsl:template match="/">
 <xsl:for-each select="/users/user">
   <xsl:value-of select="concat(id,'|',name,'|',country,'|',create_time,'|',total_credit,'|',expavg_credit,'|',e
xpavg_time,'|',cpid,'|',url,'|',teamid)"/>
   <xsl:value-of select="'&#10;'"/>
 </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

2. W katalogu (KAT) w którym będziesz gromadził pliki, tworzysz wszystkie podkatalogi. Nazwa po domenie.
cd $KAT
cut -f2 linki | sed 's|^http://\([^/]*\)/.*|\1|' | while read f; do mkdir $f; done

3. W skrypcie zmienić KAT i DANE na właściwe.
Ustawić poprawne podstawienie dla PROJECTKAT, PROJECTID, TEAMID. Jest tam
Cytatcut -d/ -f6
który w tym skrypcie pobiera nazwę katalogu, pole 6 "boinc.gorlaeus.net", separatorem jest "/"
/mnt/hdd2/Temp/stats/boinc.gorlaeus.net/

Jeśli wszystko jest zainstalowane można testowo uruchomić.
Oczywiście zrezygnować z pól niechcianych - url, itp. Ta linijka z mysql to tak na odczepnego ;). Nie mam zainstalowanego nie importowałem do bazy.

Wget sprawdza timestamp pliku i pobiera tylko nowsze. Zaletą tego skryptu jest szybkość. Perl, python czy cóś innego nie zapewni tego co cgrep.

Ostatecznie wywoływać z crona, z tym że może będziesz musiał podać pełne ścieżki do programów.
Na moim złomie dla 59 plików user.gz (192MB) przekształcenie trwa ~90s. Na 2 rdzeniowcu >= 2GHz nie powinno zająć
dłużej jak 20s. Zamiast gzipa możesz skorzystać z pigz w celu wykorzystania dodatkowych rdzeni.
http://www.zlib.net/pigz/

Swoją drogą sposób dystrybucji tych dumpów jest absurdalny. Można by w cyklu dwutygodniowych checkpointów robić diffy z bazy lub nawet delty na gzipach.
Wtedy zamiast 1GB dziennie, pobierałoby się 40 MB.

EDIT:
Pojawił się błąd. Projekt gerasim korzysta z windowsowego znaku końca linii. We wzorze wyszukiwania dodałem [^M]*$

Wow. Poprzednia wersja nie mogła działać porprawnie, ponieważ zawierała kardynalny błąd.
W tej dodałem, diffa aby nie dublować danych. Na brudno działa.
Pozostał problem z polskimi znakami. Nie ogarniam tego.

Szopler

#104
Można też (to moje coś) zrobić tak - w sumie tylko 3 zapytania do bazy :).

mysql_pconnect ('localhost', 'boincstats', 'si#83') or die ('Nie można uzyskać połączenia z serwerem baz danych!');
mysql_select_db('boinc') or die ('Brak bazy danych "boinc"!');

$UserName = '"[BOINC@Poland] Szopler"';
$Score = 0;

$query = ("SELECT `UserID` FROM `tblusers` where `UserName`=".$UserName);
$result = mysql_query($query);
$wektor = mysql_fetch_array($result);

echo '<p>'.'UserID: '.$wektor['UserID'].'</p>';
//$UserID = $tablica['UserID'];

$query = ("SELECT `ProjectID`,`ProjectName` FROM `tblprojects`");
$result = mysql_query($query);
$ilosc = mysql_num_rows($result);

for ($i=0;$i<=$ilosc;$i++)
{
 $line = mysql_fetch_row($result);
$tbl_project[$i] = Array($line[0],$line[1]);

//echo '<br>'.$tbl_project[$i][0].' - '.$tbl_project[$i][1];
}

$query = ("SELECT `ProjectID`,`Score` FROM `tblscores` WHERE `UserID`=".$wektor['UserID']." and `Score` >".$Score." and ***data*** order by `Score` desc");
$result = mysql_query($query);

for ($i=0;$i<=$ilosc;$i++)
{
 $line = mysql_fetch_row($result);
$tbl_points[$i] = Array($line[0],$line[1]);

//echo '<br>'.$tbl_points[$i][0].' - '.$tbl_points[$i][1];
}

//echo '<br>+++ '.$tbl_project[1][0].' - '.$tbl_project[1][1];

$licznik=0;

while ($licznik<$ilosc)
{

for ($i=0;$i<=$ilosc;$i++)
{
if (($tbl_project[$i][0]) == ($tbl_points[$licznik][0]))
{
echo '<br>'.($tbl_project[$i][1]).' - '.($tbl_points[$licznik][1]);
$licznik++;
}
}
}


W miejscu *** trzeba wstawić do zapytania warunek z datą, żeby pobrało tylko aktualne dane z tabeli tblscores.
Tyle że ten warunek jest kłopotliwy bo jak wstawię proste - ... and `Date`='2010-11-22' to ...  wypisze mi punkty w projektach a którymi tego dnia udało się połączyć.

Wszystko dlatego że w tabeli tblscores ilość punktów przypisana do daty istnieje tylko dla projektów z którymi danego dnia udało się połączyć.
Gdyby w przypadku braku połączenia przepisywać wynik z ... to wyświetlało by punkty dla wszystkich projektów usera.

Projektów w bazie: 96
Projektów z dnia 2010-11-22: 50
Projektów nieaktywnych wg bazy: 30
Zostaje: 16 do ustalenia co z nimi nie tak...

krzyszp

Hint do daty: "Max"
UserID z bazy jest widoczny (przechowany w sesji, nie trzeba osobno pytać).

Tak w ogóle, to przetestuję skrypty dopiero w sobotę, bo do piątku mnie nie ma niestety...

Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

krzyszp


inotifywait -m -r -q -o $DANE/newfile -e close_write $KAT >/dev/null &
pid=$!



inotifywait: invalid option -- 'o'
kill: 16: No such process

Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

buninek

inotifywait -m -r -q -e close_write $KAT >$DANE/newfile 2>&1&

Masz starszą wersję.

krzyszp

#108
Ok, na tę chwilę, skrypt ściąga mi pliki user.gz do katalogów nazwanych tak jak ProjectID (1,2,itd)...
Wykonanie komendy:

cut -f2 linki | sed 's|^http://\([^/]*\)/.*|\1|' | while read f; do mkdir $f; done

Powoduje utworzenie katalogów o nazwach takich jak teamid z pliku linki, czyli tutaj jest błąd przy seedowaniu nazw projektów...
Edit: Poprawione, plik "linki" miałem źle sformatowany...


Pliki inserts, newfile mają długość zerową.

Struktura katalogów u mnie:
Katalog główny (ze skryptem) - /media/Składowisko/Temp/Boinc
Katalog z danymi - /media/Składowisko/Temp/Boinc/Dane
Katalog z plikami (w podkatalogach jak opisałem wyżej) user.gz - /media/Składowisko/Temp/Boinc/KAT, np. /media/Składowisko/Temp/Boinc/KAT/1, /media/Składowisko/Temp/Boinc/Kat/2 itd

Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

buninek

#109
Punkt wyjścia.
1. Z bazy zrzucić do pliku "linki" w katalogu (DANE)
PROJECTID, pełny link do pliku user.gz, TEAMID
Wszystkie pola rozdzielone znakiem tabulacji. Oczywiście mowa o projektach aktywnych w których nasz team uczestniczy.

Cytat1       http://abcathome.com/stats/user.gz      45
2       http://boinc.almeregrid.nl/stats/user.gz        89
...
Jeśli zmieniasz strukturę tego pliku (kolejność pól), to wtedy musisz poprawić skrypt.

2. Zamienić w skrypcie wszystkie "cut -d/ -f6" na takie pole, które prawidłowo wskazuje katalog z zawartością user.gz
/media/Składowisko/Temp/Boinc/boinc.bakerlab.org
czyli
echo "/media/Składowisko/Temp/Boinc/boinc.bakerlab.org" | cut -d/ -f6
boinc.bakerlab.org
lub
echo "/bla/blabla/blablabla/boinc.bakerlab.org" | cut -d/ -f5

Skrypt jest mało przejrzysty.

krzyszp

po wywołaniu skryptu mam:

krzyszp@Ubuntu64:/media/Składowisko/Temp/Boinc$ sh dow.sh
wget: brakujący URL
Składnia: wget [OPCJE]... [URL]...

Polecenie `wget --help' wyświetli więcej opcji.
-:1: parser error : Document is empty

^
-:1: parser error : Start tag expected, '<' not found

^
I/O error : Invalid seek
unable to parse -
-:1: parser error : Document is empty

^
-:1: parser error : Start tag expected, '<' not found

^
I/O error : Invalid seek
unable to parse -
-:1: parser error : Document is empty

^
-:1: parser error : Start tag expected, '<' not found

^
I/O error : Invalid seek
unable to parse -
cp: nie można wykonać stat na `/media/Składowisko/Temp/Boinc/KAT/boinc.bakerlab.org/last.txt': No such file or directory
sed: nie można odczytać /media/Składowisko/Temp/Boinc/KAT/boinc.bakerlab.org/last.txt: No such file or directory
cp: nie można wykonać stat na `/media/Składowisko/Temp/Boinc/KAT/burp.renderfarming.net/last.txt': No such file or directory
sed: nie można odczytać /media/Składowisko/Temp/Boinc/KAT/burp.renderfarming.net/last.txt: No such file or directory
cp: nie można wykonać stat na `/media/Składowisko/Temp/Boinc/KAT/www.distributeddatamining.org/last.txt': No such file or directory
sed: nie można odczytać /media/Składowisko/Temp/Boinc/KAT/www.distributeddatamining.org/last.txt: No such file or directory


Myślę, że za błąd odpowiada część:

do
TEAMID=$(cgrep "$(echo $line | cut -d/ -f6)" $DANE/linki | cut -f3)
gzip -cd $line | cgrep -D -w '<user>' +w '<\/user>' "^[\t ]*<teamid>$TEAMID</teamid>$" | sed -e '1i<users>' -e '$a<\/users>' | xsltproc -o $KAT/$(echo $line | cut -d/ -f6)/last.txt $DANE/users.xsl -
done


Dla jasności, wklejam cały skrypt:

#!/bin/sh
KAT=/media/Składowisko/Temp/Boinc/KAT
DANE=/media/Składowisko/Temp/Boinc/Dane

echo > $DANE/log.wget
if [ -f $DANE/newfile ]; then
rm -f $DANE/newfile
fi
inotifywait -m -r -q -e close_write $KAT >$DANE/newfile 2>&1&
pid=$!

cut -f2 $DANE/linki | while read f
do
wget -t 1 -T 30 -a $DANE/log.wget -N -P $KAT/$(echo $f | sed 's|^http://\([^/]*\)/.*|\1|') $f
done
kill -3 $pid

sed 's/ CLOSE_WRITE,CLOSE //' $DANE/newfile | while read line
do
TEAMID=$(cgrep "$(echo $line | cut -d/ -f6)" $DANE/linki | cut -f3)
gzip -cd $line | cgrep -D -w '<user>' +w '<\/user>' "^[\t ]*<teamid>$TEAMID</teamid>$" | sed -e '1i<users>' -e '$a<\/users>' | xsltproc -o $KAT/$(echo $line | cut -d/ -f6)/last.txt $DANE/users.xsl -
done

sed 's/ CLOSE_WRITE,CLOSE user.*gz/last\.txt/' $DANE/newfile | while read last
do
PROJECTID=$(cgrep "$(echo $last | cut -d/ -f6)" $DANE/linki | cut -f1)
PROJEKTKAT=$(echo $last | cut -d/ -f6)
:
if [ -e "$KAT/$PROJEKTKAT/first.txt" ]; then
   diff -a $KAT/$PROJEKTKAT/first.txt $last | sed -e '/^> /!d;s/^> //' -e "s,^,$PROJECTID|,g" >> $DANE/inserts
else
   cp $last $KAT/$PROJEKTKAT/first.txt
   sed "s,^,$PROJECTID|,g" $last >> $DANE/inserts
fi
done
#mysql -c "LOAD DATA LOCAL INFILE '$DANE/inserts' INTO TABLE users LINES TERMINATED BY '|';"
cp $DANE/inserts $DANE/inserts.prev


Zapytanie SQL nie ruszam, zajmiemy się tym, jak już zobaczę jak wyglądają gotowe pliki insertów :)

Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

buninek

#111
W skrypcie dodaj set -x
#!/bin/sh
set -x

pozwoli to prześledzić, błędy.
Wyświetl zawartość katalogu /media/Składowisko/Temp/Boinc/KAT
ls -1 /media/Składowisko/Temp/Boinc/KAT
Powinnenneś mieć tam utworzone podkatalogi (nazwy katalogów pod domenie)
Cytatabcathome.com
aqua.dwavesys.com
bearnol.is-a-geek.com
boinc.almeregrid.nl
boinc.bakerlab.org
boinc.bio.wzw.tum.de
boinc.cs.uct.ac.za
boinc.drugdiscoveryathome.com
boinc.freerainbowtables.com

Prosiłem o zamianę "cut -d/ -f6" - pola f6 na takie jaki wskazuje wybrany przez ciebie katalog.
czyli powinno być wszędzie cut -d/ -f7. Utworzyłeś podkatalogi?????????
man cut
separatorem jest "/", liczymy
1/2/3/4/5/6/
/media/Składowisko/Temp/Boinc/KAT/boinc.bakerlab.org

Zachęcam jeszcze raz do zastosowania się do wskazówek podanych w poście ze skryptem.

Nie jestem programistą. Moja umiejętność pisania skryptów w shellu, sprowadza się do jedno-dwu linijkowców, usprawniających codzienne korzystanie z kompa. Ewentualnie do adaptacji na własne potrzeby gotowców.

Nie potrafię napisać tak uniwersalnego skryptu, który uruchomi go osoba nie mająca pojęcia o shellu.

EDIT:
Zachęcam do większej samodzielności, czytaj rozłożenia skryptu na czynniki pierwsze.
Co robi tu inotifywait?! Jake zadanie spełnia.
Sprawdź co jak działa, wklep w terminalu
KAT=/tmp/moj_katalog
echo $KAT
inotifywait -m -r -q -e close_write /tmp
echo "test" > /tmp/test.txt
wget -O /tmp/user_id.gz http://burp.renderfarming.net/stats/user_id.gz
gzip -cd /tmp/user_id.gz | cgrep -D -w '<user>' +w '<\/user>' "^[\t ]*<teamid>26</teamid>$" > /tmp/renderfarmi_BP.txt
sed -e '1i<?xml version="1.0" encoding="iso-8859-1"?>' -e '1i<users>' -e '$a<\/users>' /tmp/renderfarmi_BP.txt > /tmp/renderfarmi_BP.xml
xsltproc --encoding iso-8859-1 -o /tmp/dane_do_mysql.txt /tmp/stylesheet.xsl /tmp/renderfarmi_BP.xml


Potestuj troszkę. Wpisz
man inotifywait
man cut
man wget

Zobacz co jakie opcje powodują.

krzyszp


ls -1 /media/Składowisko/Temp/Boinc/KAT

abcathome.com
allprojectstats.com
aqua.dwavesys.com
bearnol.is-a-geek.com
boinc.almeregrid.nl
boinc.bakerlab.org
boinc.bio.wzw.tum.de
boinc.drugdiscoveryathome.com
boinc.fzk.de
boinc.gorlaeus.net
boinc.thesonntags.com
boinc.umiacs.umd.edu
boinc.unsads.com
boinc.vanderbilt.edu
burp.renderfarming.net
casathome.ihep.ac.cn
cbl-boinc-server2.cs.technion.ac.il
climateapps2.oucs.ox.ac.uk
dnetc.net
docking.cis.udel.edu
einstein.phys.uwm.edu
eon.ices.utexas.edu
escatter11.fullerton.edu
falua.cesfelipesegundo.com
gerasim.boinc.ru
home.edges-grid.eu
hydrogenathome.org
isaac.ssl.berkeley.edu
lhcathome.cern.ch
milkyway.cs.rpi.edu
mindmodeling.org
orbit.psi.edu
qah.uni-muenster.de
qcn.stanford.edu
ralph.bakerlab.org
registro.ibercivis.es
setiathome.berkeley.edu
setiweb.ssl.berkeley.edu
spin.fh-bielefeld.de
sudoku.nctu.edu.tw
szdg.lpds.sztaki.hu
vcsc.cs.uh.edu
wuprop.boinc-af.org
www.chess960athome.org
www.cosmologyathome.org
www.depspid.net
www.distributeddatamining.org
www.enigmaathome.net
www.freehal.net
www.fti.dn.ua
www.gpugrid.net
www.luxrenderfarm.de
www.malariacontrol.net
www.primaboinca.com
www.primegrid.com
www.rechenkraft.net
www.renderfarm.fi
www.rnaworld.de
www.ufluids.net
www.worldcommunitygrid.org
xw01.lri.fr:4320


Ta część jest ok.

Przepraszam, wcześniej źle zrozumiałem uwagę odnośnie separatora...

Dodałem set -x do skryptu.

Jak na razie wygląda, że plik inserts się tworzy :)

Zaraz przyjdzie czas na pytanie, jak to ugryźć...

Ze względu na moje (nikłe) umiejętności pod linuksem, pierwszy pomysł jest taki, aby to wyeksportować do katalogu dostępnego dla mnie spod windy, ale to proteza.
Drugie wyjście, to użyć naszego skryptu i komend eksportować wszystko do bazy lokalnie (tzn, skrypt jest lokalny - jestem w domu, a serwer w pracy) - i tak chyba zrobimy. Jeszcze tylko jeden szczegół - mamy teraz więcej danych w krótszym czasie, więc chyba warto by było przebudować bazę danych i przygotować ją "solidnie" do pracy...

Potem tylko całość wrzucić do cron'a i mamy serwer statystyk w wersji produkcyjnej :)


Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

krzyszp

Jeszcze tylko potrzebuję dokładnej informacji o zawartości poszczególnych pól w pliku inserts:
http://simple-crm.co.uk/ppb/inserts

Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

buninek

Jest taka jaką sobie ustalisz w stylesheet (users.xsl) + PROJECTID. Pisałem w pierwszym poście - wybierz tylko te, które uważasz za niezbędne.

PROJECTID|id|name|country|create_time|total_credit|expavg_credit|expavg_time|cpid|url|teamid

krzyszp

Dzięki.
Teraz drobiazgi (mogę dojść do tego sam, powolutku, ale trochę szkoda czasu):

Użyteczne kolumny, to projectid, name, country, total_credit, cpid, url, temid (z punktu widzenia naszego serwera), teraz trzeba powiązać kolumny z tego pliku z kolumnami (i tabelami) w bazie danych. Może rozbić plik "insert" na pliki z nazwami (lub id) projektów z BD?
Myślę, że poważnie też trzeba się zastanowić nad strukturą bazy danych naszego serwera, to co ja przygotowałem, niestety nie zda raczej egzaminu w dłuższej perspektywie...

Macie jakieś propozycje?

Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

buninek

#116
sed 's/ CLOSE_WRITE,CLOSE user.*gz/last\.txt/' $DANE/newfile | while read last
do
PROJECTID=$(cgrep "$(echo $last | cut -d/ -f6)" $DANE/linki | cut -f1)
PROJEKTKAT=$(echo $last | cut -d/ -f6)
PROJECTTABLENAME=$(cgrep "$(echo $last | cut -d/ -f6)" $DANE/linki | cut -f4)
:
if [ -e "$KAT/$PROJEKTKAT/first.txt" ]; then
  diff -a $KAT/$PROJEKTKAT/first.txt $last | sed -e '/^> /!d;s/^> //' -e "s,^,$PROJECTID|,g" > $KAT/$PROJEKTKAT/insert.txt
  mysql -c "LOAD DATA LOCAL INFILE '$KAT/$PROJEKTKAT/insert.txt' INTO TABLE $PROJECTTABLENAME LINES TERMINATED BY '|';"
else
  cp $last $KAT/$PROJEKTKAT/first.txt
  sed "s,^,$PROJECTID|,g" $last > $KAT/$PROJEKTKAT/insert.txt
  mysql -c "LOAD DATA LOCAL INFILE '$KAT/$PROJEKTKAT/insert.txt' INTO TABLE $PROJECTTABLENAME LINES TERMINATED BY '|';"
 fi
done

W takim układzie bazy, trzeba dodać do pliku linki - 4 kolumnę, PROJECTTABLENAME. Popraw, cut -d/ -f6.
Zrób takie zmiany. Ilość "cut-ów" i "sed-ów" robi się obrzydliwie wielka ;D Trzeba by wszystko od nowa po ludzku napisać :closedeyes:
Dwa, nie jestem pewien czy to podstawienie w linii z mysql zadziała '$KAT/$PROJEKTKAT/insert.txt'.

Trzy. Proponowałem analizę działania, ponieważ ten skrypt nie jest odporny na błędy. Jak coś będzie nie działać, dobrze wiedzieć w czym rzecz.
Proponuję się z nim przespać :D

EDIT:
Pozostaje nadal nie rozwiązana kwestia polskich znaków. W tym momencie xsltproc zamienia na UTF-8, zgodnie z tym
http://en.wikipedia.org/wiki/List%5Fof%5FXML%5Fand%5FHTML%5Fcharacter%5Fentity%5Freferences

W linii z cgrep dodaj [^M]*$, wymagane dla projektu Gerasim.
cgrep -D -w '<user>' +w '<\/user>' "^[\t ]*<teamid>$TEAMID</teamid>[^M]*$"
Nie masz statystyk projektu Pirates@Home.

krzyszp

Łączność z bazą danych przywrócona. W tej chwili aktualizują się wyniki, dodana tabela dla liczb pierwszych...

Muszę jeszcze uaktualnić województwa naszych liczydłowynch...

Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

krzyszp

Czy ktoś może mi powiedzieć, dlaczego zapytnie:
$sql = "LOAD DATA LOCAL INFILE '/var/www/inserts' INTO TABLE tblUpload FIELDS TERMINATED BY '|'";
działa z poziomu PHPMyAdmin'a ale już z poziomu skryptu wywala błąd "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''tblUpload'' at line 1: "???

Fajne zegarki :)
Należę do drużyny BOINC@Poland
 Moja wizytówka

buninek

Średnik przed cudzysłowem.

Znak '|' rozdzielający pola jest niebezpieczny jeśli się go nie eskejpuje. Ktoś może w nicku wykorzystać.
Może lepiej będzie użyć tabulacji.