←  Pytania

AMXX.pl: Support AMX Mod X i SourceMod

»

[ROZWIĄZANE] Ilość znaków w stringu, usuwa...


Zablokowany

  • +
  • -
Sniper Elite - zdjęcie Sniper Elite 05.09.2014

Witam.

Próbuję wykorzystać poradnik GwynBleidD http://amxx.pl/topic...in-baza-danych/

aby stworzyć lepszy zapis mysql na moim serwerze.

Mam teraz problem z wykonaniem taska który automatycznie zapisuje doświadczenie do bazy. Otóż nie wiem jak w końcowym wpisie usunąć przecinek. Może i błache, ale nigdy się tym nie zajmowałem i nie mam pomysłu jak to zrobić.

 

Moje pytania:

- jak usunąć x ostatnich/pierwszych znaków w stringu?

- jak zwrócić ilość znaków w stringu (nie chodzi mi tu o rozmiar maksymalny tablicy, ale o to ile znaków jest tam przechowywanych)?

 

Dzięki za pomoc.

Odpowiedz

  • +
  • -
Puchate - zdjęcie Puchate 05.09.2014


- jak usunąć x ostatnich/pierwszych znaków w stringu?

Operacje na tablicach w PAWNie niestety nie sa przyjemne :P

 

Kodem na usuniecie znaku na pozycji X moze byc cos takiego - wklepane w notatniku i nietestowane, wiec moze nie dzialac 

stock removeChar(string[], pos) {
	
	new len = strlen(string)
	if(pos > len)
		return
	
	replace(string[pos], len - pos, string[pos], "")	
}


- jak zwrócić ilość znaków w stringu (nie chodzi mi tu o rozmiar maksymalny tablicy, ale o to ile znaków jest tam przechowywanych)?

strlen

 

 

 

 

Odpowiedz

  • +
  • -
Sniper Elite - zdjęcie Sniper Elite 05.09.2014

Zrobiłem sobie funkcje testową która ma za zadanie wypisać zapytanie jakie jest wysyłane do bazy danych. Oto ona:

public WypiszZapytanie()
{
    new name[48]
                
    for(new id = 1; id <= g_maxplayers; id++)
    {
        
        if(!is_user_connected(id) || !klasa_gracza[id])
            continue;
            
        get_user_name(id, name, 47);
        replace_all(name, 47, "'", "\'");
            
        giLen += formatex(ZapiszExp[giLen], giMax-giLen," ('%s',%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d),",
        name,klasa_gracza[id],poziom_gracza[id],doswiadczenie_gracza[id],inteligencja_gracza[id],zdrowie_gracza[id],wytrzymalosc_gracza[id],kondycja_gracza[id],grawitacja_gracza[id],niewidzialnosc_gracza[id],celneoko_gracza[id],moc_gracza1[id],moc_gracza2[id],moc_gracza3[id],quest_dzienny[id][0],klasa_pro[id],monety[id],honor[id],s_aw[id],s_apw[id],s_pas[id],quest_gracza[id],ile_juz[id],ile_wykonano[id],quest_dzienny[id][1],quest_dzienny[id][2])
        
        name = ""
    
    }
    
    new DlugoscStringa = strlen(ZapiszExp)
    
    replace(ZapiszExp[DlugoscStringa-1], DlugoscStringa, ZapiszExp[DlugoscStringa-1], "")
    
    giLen += formatex(ZapiszExp[giLen], giMax-giLen," ON DUPLICATE KEY UPDATE `lvl`=VALUES(`lvl`), `exp`=VALUES(`exp`), `int`=VALUES(`int`), `zdr`=VALUES(`zdr`), `wyt`=VALUES(`wyt`), `kon`=VALUES(`kon`), `gra`=VALUES(`gra`), `nie`=VALUES(`nie`), `cel`=VALUES(`cel`), `moc1`=VALUES(`moc1`), `moc2`=VALUES(`moc2`), `moc3`=VALUES(`moc3`), `m_dzien`=VALUES(`m_dzien`), `pro`=VALUES(`pro`), ")
    giLen += formatex(ZapiszExp[giLen], giMax-giLen,"`zlo`=VALUES(`zlo`), `hon`=VALUES(`hon`), `s_aw`=VALUES(`s_aw`), `s_apw`=VALUES(`s_apw`), `s_pas`=VALUES(`s_pas`), `q_gracza`=VALUES(`q_gracza`), `ile_juz`=VALUES(`ile_juz`), `ile_wyk`=VALUES(`ile_wyk`), `ile_qd1`=VALUES(`ile_qd1`), `ile_qd2`=VALUES(`ile_qd2`)")
    
    log_to_file("test_zapis.log", "%s", ZapiszExp);
    
    ZapiszExp = ""
    giLen=0, giMax=sizeof(ZapiszExp) - 1
    giLen += formatex(ZapiszExp[giLen], giMax-giLen,"INSERT INTO `cod_tablet` (`nick`,`klasa`,`lvl`,`exp`,`int`,`zdr`,`wyt`,`kon`,`gra`,`nie`,`cel`,`moc1`,`moc2`,`moc3`,`m_dzien`,`pro`,`zlo`,`hon`,`s_aw`,`s_apw`,`s_pas`,`q_gracza`,`ile_juz`,`ile_wyk`,`ile_qd1`,`ile_qd2`) VALUES")
    
    return PLUGIN_CONTINUE;
}

Pokombinowałem trochę i udałosię usunąć ten przecinek, ale powstał kolejny problem.

Nie dodaje kolejnych linijek po użyciu funkcji replace tj.

    giLen += formatex(ZapiszExp[giLen], giMax-giLen," ON DUPLICATE KEY UPDATE `lvl`=VALUES(`lvl`), `exp`=VALUES(`exp`), `int`=VALUES(`int`), `zdr`=VALUES(`zdr`), `wyt`=VALUES(`wyt`), `kon`=VALUES(`kon`), `gra`=VALUES(`gra`), `nie`=VALUES(`nie`), `cel`=VALUES(`cel`), `moc1`=VALUES(`moc1`), `moc2`=VALUES(`moc2`), `moc3`=VALUES(`moc3`), `m_dzien`=VALUES(`m_dzien`), `pro`=VALUES(`pro`), ")
    giLen += formatex(ZapiszExp[giLen], giMax-giLen,"`zlo`=VALUES(`zlo`), `hon`=VALUES(`hon`), `s_aw`=VALUES(`s_aw`), `s_apw`=VALUES(`s_apw`), `s_pas`=VALUES(`s_pas`), `q_gracza`=VALUES(`q_gracza`), `ile_juz`=VALUES(`ile_juz`), `ile_wyk`=VALUES(`ile_wyk`), `ile_qd1`=VALUES(`ile_qd1`), `ile_qd2`=VALUES(`ile_qd2`)")

I zapytanie wygląda tak:


INSERT INTO `cod_tablet` (`nick`,`klasa`,`lvl`,`exp`,`int`,`zdr`,`wyt`,`kon`,`gra`,`nie`,`cel`,`moc1`,`moc2`,`moc3`,`m_dzien`,`pro`,`zlo`,`hon`,`s_aw`,`s_apw`,`s_pas`,`q_gracza`,`ile_juz`,`ile_wyk`,`ile_qd1`,`ile_qd2`) VALUES ('Sniper Elite',2,2,120,0,2,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,1,-1,0,0,0,0)

Wiesz może czemu?

 

Odpowiedz

  • +
  • -
GwynBleidD - zdjęcie GwynBleidD 05.09.2014

1. DlugoscStringa = giLen + 1, więc nie musisz tego obliczać na nowo.
2. po replace giLen powinno zostać zaktualizowane, a tego nie robisz. string kurczy się o 1 znak, przez co dalszy ciąg napisu jest za nullem, zostanie on więc zignorowany.

replace powinien zwrócić nową długość, tak jak inne funkcje operujące na stringach. Jeśli zwraca, to po prostu dodaj przed nim giLen =

jeśli nie zwraca, po prostu odejmij od giLen 1 po użyciu replace.
GwynBleidD (05.09.2014 13:44):
A i jak już Ci się uda to uruchomić to:
1. usuń wszelkie niepotrzebne znaki z zapytania
2. Policz "pesymistyczny" przypadek, tj gdy będziesz miał max ilość graczy do zapisania i każdy z graczy będzie miał maksymalne dopuszczalne wartości (pod względem ilości znaków) i według tego tablicę wymierz
3. Zrób przy zapisie sprawdzanie, ilu graczy już dodałeś do zapisania, jeśli jest max, to zapytanie wyślij i utwórz następne, bo Ci się tablica na string może skończyć.
Odpowiedz

  • +
  • -
Sniper Elite - zdjęcie Sniper Elite 05.09.2014

Zrobiłem, działa :D

Zrobię większą tablicę (na 64 wpisy). Gracze będą do niej dopisywani gdy rozłączą się z serwerem lub zmienią klasę + dodatkowo sprawdzę czy nie ma już wpisu z tym samym nickiem i nr klasy (co by się nie dublowało)

Funkcję zapisu expa do bazy danych będę wywoływał co 2-3 min + dodatkowo w plugin_end.

Odpowiedz

  • +
  • -
GwynBleidD - zdjęcie GwynBleidD 05.09.2014

Daj później IP serwera, postaram się to zepsuć i pokażę Ci dlaczego sprawdzanie ile graczy już jest do listy zapisanych jest niezbędne. Ewentualnie możesz porównywać długość zapytania.
Odpowiedz

  • +
  • -
Puchate - zdjęcie Puchate 05.09.2014

Jako że używasz MySQL'a to mam radę jak lepiej zbudować takie zapytanie.

 

Teraz budujesz takie zapytanie

INSERT INTO `tabela` (`wartosc1`, `wartosc2`) VALUES ('123', '123') ON DUPLICATE KEY UPDATE `wartosc1` = 'hihihi', `wartosc2` = 'blabla'

Żebyś nie miał za łatwo to pokażę Ci na przykładzie PHP :P jak można ułatwić budowanie takiego zapytania do MySQL, przy założeniu ze aktualizujesz to samo co dodajesz.

// obecnie zapytanie budujesz z 3 (a nawet 4 w PAWNIE) kawalkow                                                                   
$insert = "INSERT INTO `tabela` (`wartosc1`, `wartosc2`) VALUES";
$values = "('wartosc1', 'wartosc2')";
$duplicate = "ON DUPLICATE KEY UPDATE `wartosc1` = 'hihihi', `wartosc2` = 'blabla'";

// a pozniej laczysz je w calosc i masz gotowe zapytanie
$sql = implode(" ", array($insert, $values, $duplicate));

//
// A MOZNA ZROBIC TO LATWIEJ :)
//

$insert = "INSERT INTO `tabela` SET";
$values = "`wartosc1` = 'hihihi', `wartosc2` = 'blabla'";

$sql = implode(" ", array($insert, $values, "ON DUPLICATE KEY UPDATE", $values));

O ile w PHP budowa takiego zapytania w obu wersjach jest łatwa, o tyle w pawnie... sam widzisz ;)


Użytkownik Puchate edytował ten post 05.09.2014 19:47
Odpowiedz

  • +
  • -
GwynBleidD - zdjęcie GwynBleidD 05.09.2014

Zauważ róźnicę w "`wartosc1` = 'hihihi'" i "`wartosc1` = VALUES(`wartosc1`)" przy wykonywaniu zapytania dla kilku rekordów na raz. Poza tym sam SET już taką operację utrudnia.
Odpowiedz

  • +
  • -
Puchate - zdjęcie Puchate 05.09.2014


przy założeniu ze aktualizujesz to samo co dodajesz.


Zauważ róźnicę w "`wartosc1` = 'hihihi'" i "`wartosc1` = VALUES(`wartosc1`)" przy wykonywaniu zapytania dla kilku rekordów na raz. Poza tym sam SET już taką operację utrudnia.

 
Spójrz w zapytanie z pluginu. Przy pisaniu zapytania wstałem bzdetne dane, niekoniecznie pasujące do omawianego sposobu. :P
Odpowiedz

  • +
  • -
Sniper Elite - zdjęcie Sniper Elite 05.09.2014


Daj później IP serwera, postaram się to zepsuć i pokażę Ci dlaczego sprawdzanie ile graczy już jest do listy zapisanych jest niezbędne. Ewentualnie możesz porównywać długość zapytania.

 

Wiem o co biega :D i zrobiłem zabezpieczenie, które pozwoli maksymalnie na 64 wpisy.

 

Miałem jeszcze zapytać o asynchroniczne i synchroniczne zapytanie do bazy danych. Jakiego używa się w plugin end i jak ono wygląda?

Odpowiedz

  • +
  • -
GwynBleidD - zdjęcie GwynBleidD 05.09.2014

W plugin_end po prostu nie używasz ThreadQuery, ale "zwykłego" zapytania SQL.
Odpowiedz

  • +
  • -
Sniper Elite - zdjęcie Sniper Elite 05.09.2014

Dalej nie wiem jak to zrobić :)

Jakaś funkcja jest do tego?

Odpowiedz

  • +
  • -
Sniper Elite - zdjęcie Sniper Elite 06.09.2014

Dzięki :D

Zrobiłem cały zapis i jak na razie sprawuje się nieźle (ip masz w sygnaturze jak chcesz zepsuć :) - cod mod)

Może niedługo napiszę własny poradnik jak zrobić takie zapis od podstaw.

 

Można zamknąć.

Odpowiedz
Zablokowany