Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [PHP][MySQL]Algorytm przyporządkowujący losowo współrzędne na obszarze, Algorytm przyporządkowujący losowo współrzędne na obszarze
dexter00
post
Post #1





Grupa: Zarejestrowani
Postów: 5
Pomógł: 0
Dołączył: 15.11.2012
Skąd: warszawa

Ostrzeżenie: (0%)
-----


Witam,

No więc z php rozpocząłem swoją przygodę nie dawno (na początku października), w tej chwili pracuje na frameworku- Codeigniter, i stanąłem przed takim zadaniem muszę napisać w php i mysql algorytm który będzie przypisywał mi trzy współrzędne X,Y,Z dodawanego obiektu (punktu) na obszarze (np. obrazku) o wielkości 2560x1240 px . A teraz do rzeczy:

Dane:
punkt (0,0,0) znajduję się w lewym górnym rogu grupy powierzchni roboczej.
X - szerokość
Y- wysokość
Z- losowa wartość od 1 do 10
area- grupa do której należy obiekt (od 1 do 20 )

baza zawierająca dane obiektu:
(IMG:http://www.wyslij.nazwa.pl/praca/baza.png)

obszar jest podzielony na 20 części, każda ma swoją gęstość która będzie miała wyliczana dzięki danym z bazy (ilość wystąpień np 1 w kolumnie area) ,
(IMG:http://www.wyslij.nazwa.pl/praca/obszar.png)

No i na czym polega trudność - przy dodawaniu nowego obiektu muszę zbadać gęstość każdego obszaru (1-20) następnie wybrać ten z najmniejsza gęstością i przypisać ją do obiektu, przypisać w obszarze (np.2) losowe współrzędne (z zakresu X- 0:512 i Y - 0:248 Z- losowo od 1 do 10).

Nie wiem jak się do tego wszystkiego zabrać, jakieś podpowiedzi z jakich bibliotek, funkcji php,mysql mógłbym skorzystać przy tym zadaniu?

Z góry dziękuję za pomoc (IMG:style_emoticons/default/smile.gif)



Go to the top of the page
+Quote Post
b4rt3kk
post
Post #2





Grupa: Zarejestrowani
Postów: 1 933
Pomógł: 460
Dołączył: 2.04.2010
Skąd: Lublin

Ostrzeżenie: (0%)
-----


Nie wiem czy dobrze zrozumiałem, ale obszar o najmniejszej gęstości (tj. najmniejszej liczby przypisanych punktów) możesz zrealizować jednym prostym zapytaniem.

  1. SELECT area, COUNT(id) AS ile FROM star GROUP BY area ORDER BY ile ASC LIMIT 0,1


Jako wynik otrzymasz nazwę (identyfikator) obszaru oraz liczbę przypisanych punktów.

Nie wiem jak ustanawiasz te obszary, ale jeśli np. w bazie są współrzędne początku i końca obszaru, to teraz je pobierasz na podstawie wyniku poprzedniego zapytania. Załóżmy, że otrzymujesz już taki wynik:

  1. $x0, $x1, $y0, $y1; // współrzędne obszaru
  2.  
  3. // można teraz wylosować współrzędne nowego punktu
  4.  
  5. $newX = mt_rand($x0, $x1);
  6. $newY = mt_rand($y0, $y1);
  7. $z = mt_rand(0,10);
  8.  
  9. // sprawdzasz znów bazę czy punkt takowy już nie istnieje
  10. $query = "SELECT COUNT(id) FROM star WHERE x = '$newX' AND y = '$newY'";
  11. // jeśli punkt istnieje, losujesz ponownie współrzędne, a jeśli nie to możesz go zapisać do bazy


I to chyba tyle?

Ten post edytował b4rt3kk 15.11.2012, 17:32:59
Go to the top of the page
+Quote Post
dexter00
post
Post #3





Grupa: Zarejestrowani
Postów: 5
Pomógł: 0
Dołączył: 15.11.2012
Skąd: warszawa

Ostrzeżenie: (0%)
-----


Super to co napisałeś nie do końca działa ale pomogło mi zrozumieć o co chodzi, po przeszukaniu googla powstało coś takiego:

  1. public function addStar() {
  2.  
  3. // znajdowanie najmniejszej gęstości poprzez sprawdzenienie ile razy występuje dany rekord np. obszar 1
  4. for ($i = 1; $i <= 20; $i++) {
  5. $news_count[$i] = $this -> db -> query("SELECT COUNT(*) AS like" . $i . " FROM star WHERE area LIKE " . $i . "") -> row_array();
  6.  
  7. }
  8. //otrzymuje tablice 1 do 20 gdzie mam ilość wystąpień:
  9. /*Array
  10. (
  11.   [1] => Array
  12.   (
  13.   [like1] => 0
  14.   )
  15.  
  16.   [2] => Array
  17.   (
  18.   [like2] => 0
  19.   )
  20.  
  21.   [3] => Array
  22.   (
  23.   [like3] => 0
  24.   )
  25.  
  26.   [4] => Array
  27.   (
  28.   [like4] => 0
  29.   )
  30.  
  31.   [5] => Array
  32.   (
  33.   [like5] => 1
  34.   )
  35. itd...
  36.  */
  37.  
  38.  
  39. // wybieram najmniejsza wartość
  40. $choose = min(array_filter($news_count));
  41.  
  42. //zapisuje do zmiennej v indeks tablicy
  43. $v = array_keys($choose);
  44.  
  45. /* koniec konców zmienna v ma zapisaną ostatni obszar z najmniejszą gęstością,
  46. * i tu mam problem jak zrobić żeby zmienna v nie była tablicą
  47. * tylko miała wartość tak jak poniżej np 20 bez słowa like, no i jak zrobić że
  48. * kiedy mam dwa obszary które mają np 0 jak losować z pośród nich
  49. *
  50. *
  51. * Zwracana tablica:
  52. Array
  53. (
  54. [0] => like20
  55. )*/
  56.  
  57. $newX = mt_rand(0, 512);
  58. $newY = mt_rand(0, 248);
  59. $newZ = mt_rand(0, 10);
  60.  
  61. // na koniec zwracam wartości potrzebne do zapisania w bazie danych
  62. //oraz sprawdzam czy taka gwiazdka juz nie istnieje
  63.  
  64. $query = $this -> db -> query("SELECT COUNT(id) FROM star WHERE x = ".$newX." AND y = ".$newY."") -> row_array();
  65.  
  66. if ($query['COUNT(id)'] > 0) {
  67.  
  68. echo "Taka gwiazdka istnieje sprĂłbuj jeszcze raz!";
  69.  
  70. } else {
  71. return array($newX, $newY, $newY, $area);
  72.  
  73.  
  74. }
  75.  
  76. }





No i nie wiem tylko jak rozwiązać problem w miejscu gdzie zaczyna się komentarz linia 46.

Pozdrawiam (IMG:style_emoticons/default/smile.gif)

Ten post edytował dexter00 15.11.2012, 20:32:27
Go to the top of the page
+Quote Post
b4rt3kk
post
Post #4





Grupa: Zarejestrowani
Postów: 1 933
Pomógł: 460
Dołączył: 2.04.2010
Skąd: Lublin

Ostrzeżenie: (0%)
-----


  1. public function addStar() {
  2.  
  3. // nie jest potrzebna żadna tablica, pojedyncze zapytanie da od razu pożądany wynik (spróbuj)
  4.  
  5. $resource = $this -> db -> query("SELECT COUNT(*) AS ile, area FROM star GROUP BY area ORDER BY ile ASC LIMIT 0,1") -> row_array();
  6.  
  7. // jeśli dobrze zrozumiałem w jaki sposób przekazujesz wyniki zapytania to poniższe wyświetli liczbę punktów w obszarze, oraz nazwę obszaru
  8. echo 'Liczba: '.$resource['ile'].'<br/>';
  9. echo 'Nazwa: '.$resource['area'];
  10.  
  11. $newX = mt_rand(0, 512);
  12. $newY = mt_rand(0, 248);
  13. $newZ = mt_rand(0, 10);
  14.  
  15. // na koniec zwracam wartości potrzebne do zapisania w bazie danych
  16. //oraz sprawdzam czy taka gwiazdka juz nie istnieje
  17.  
  18. $query = $this -> db -> query("SELECT COUNT(id) FROM star WHERE x = ".$newX." AND y = ".$newY."") -> row_array();
  19.  
  20. if ($query['COUNT(id)'] > 0) echo "Taka gwiazdka istnieje sprĂłbuj jeszcze raz!"; else return array($newX, $newY, $newY, $area);
  21.  
  22. }


Co do Twojego rozwiązania to tak:

- w zapytaniu dajesz alias like$i co skutkuje tym co skutkuje:

  1. "SELECT COUNT(*) AS ile FROM star WHERE area LIKE " . $i . ""


Wykonujesz to w takiej pętli, że indeks tablicy wynikowej to również identyfikator dla area.

I myślę, że nie ma co losować spośród kilku co mają identyczną wartość minimalną, bierzesz pierwszą z brzegu, to co wybierze skrypt i po dodaniu punktu to już nie będzie area z min, także nie będzie brało jej pod uwagę i tak po kolei.
Go to the top of the page
+Quote Post
dexter00
post
Post #5





Grupa: Zarejestrowani
Postów: 5
Pomógł: 0
Dołączył: 15.11.2012
Skąd: warszawa

Ostrzeżenie: (0%)
-----


Super wielkie dzięki za pomoc! (IMG:style_emoticons/default/thumbsupsmileyanim.gif) a wiesz może co zrobić z obszarami które na początku mają wartość 0 (w sensie nie ma żadnego wpisu gdzie area ma wartość np.1) bo zapytanie nie bierze ich pod uwagę (IMG:style_emoticons/default/sad.gif)

Ten post edytował dexter00 16.11.2012, 10:42:20
Go to the top of the page
+Quote Post
b4rt3kk
post
Post #6





Grupa: Zarejestrowani
Postów: 1 933
Pomógł: 460
Dołączył: 2.04.2010
Skąd: Lublin

Ostrzeżenie: (0%)
-----


Zapytanie nie bierze ich pod uwagę, bo one nie istnieją w Twojej tabelce, bo są tam tylko punkty, a area tylko przy okazji. To już nieco utrudnia sprawę. Chyba najprościej było utworzyć tabelkę obszarów, bo trudno żeby zapytanie pobrało coś czego nie ma.
Go to the top of the page
+Quote Post
dexter00
post
Post #7





Grupa: Zarejestrowani
Postów: 5
Pomógł: 0
Dołączył: 15.11.2012
Skąd: warszawa

Ostrzeżenie: (0%)
-----


No i teraz moje tablice mają sens , już wszystko działa , tylko zastanawiam się czy to nie będzie za bardzo obciążało serwera bo pętla for wykonuje w sumie 20 zapytań do bazy (IMG:style_emoticons/default/smile.gif)


  1. public function addStar() {
  2.  
  3. // znajdowanie najmniejszej gęstości poprzez sprawdzenienie ile razy występuje dany rekord np. obszar 1
  4. for ($i = 1; $i <= 20; $i++) {
  5. $news_count[$i] = $this -> db -> query("SELECT COUNT(*) AS like" . $i . " FROM star WHERE area LIKE " . $i . "") -> row_array();
  6.  
  7. }
  8. //otrzymuje tablice 1 do 20 gdzie mam ilość wystąpień:
  9.  
  10. // wybieram najmniejsza wartość
  11. $choose = min(array_filter($news_count));
  12.  
  13. //zapisuje do zmiennej v indeks tablicy
  14. $v = array_keys($choose);
  15. //$area zwraca mi numer obszaru
  16.  
  17. $area = substr($v[0], 4, 10);
  18. $newX = mt_rand(0, 512);
  19. $newY = mt_rand(0, 248);
  20. $newZ = mt_rand(0, 10);
  21.  
  22. // na koniec zwracam wartości potrzebne do zapisania w bazie danych
  23. //oraz sprawdzam czy taka gwiazdka juz nie istnieje
  24.  
  25. $query = $this -> db -> query("SELECT COUNT(id) FROM star WHERE x = ".$newX." AND y = ".$newY."") -> row_array();
  26.  
  27. if ($query['COUNT(id)'] > 0) {
  28.  
  29. echo "Taka gwiazdka istnieje spróbuj jeszcze raz!";
  30.  
  31. } else {
  32. return array($newX, $newY, $newZ, $area);
  33. }
  34.  
  35. }
Go to the top of the page
+Quote Post
b4rt3kk
post
Post #8





Grupa: Zarejestrowani
Postów: 1 933
Pomógł: 460
Dołączył: 2.04.2010
Skąd: Lublin

Ostrzeżenie: (0%)
-----


COUNT(*) działa bardzo szybko, użytkownik nie zauważy żadnej różnicy, jeśli będzie to tylko 20 zapytań. Jeśli się rozkręcisz do 10 000 czy 100 000 to wtedy czas się nieco wydłuży.
Go to the top of the page
+Quote Post
dexter00
post
Post #9





Grupa: Zarejestrowani
Postów: 5
Pomógł: 0
Dołączył: 15.11.2012
Skąd: warszawa

Ostrzeżenie: (0%)
-----


Heh jednak nie działało już poprawiłem (IMG:style_emoticons/default/smile.gif) zastanawiam się czy spłaszczenie tablicy nie można zrobić w inny ładniejszy sposób (IMG:style_emoticons/default/smile.gif)

  1. public function addStar() {
  2.  
  3. // znajdowanie najmniejszej gęstości poprzez sprawdzenienie ile razy występuje dany rekord np. obszar 1
  4. for ($i = 1; $i <= 20; $i++) {
  5.  
  6. $news_count[$i] = $this -> db -> query("SELECT COUNT(*) AS like" . $i . " FROM star WHERE area LIKE " . $i . "") -> row_array();
  7.  
  8. }
  9.  
  10. //spłaszczam tablice
  11. $a=1;
  12. foreach($news_count as $k=>$v) foreach($v as $k2=>$v2) { $splash[$a] = $v2; $a++; } var_export($splash ,true);
  13.  
  14. // wybieram najmniejsza wartość
  15. $i_min = '1';
  16. for ( $i = 1; $i <= 20; $i++ ){
  17. if ( $splash[$i] < $splash[$i_min] )
  18. $i_min = $i;
  19. }
  20. $area = $i_min;
  21.  
  22. //generuje losowe położenie
  23. $newX = mt_rand(0, 512);
  24. $newY = mt_rand(0, 310);
  25. $newZ = mt_rand(0, 10);
  26.  
  27. // na koniec zwracam wartości potrzebne do zapisania w bazie danych
  28. //oraz sprawdzam czy taka gwiazdka juz nie istnieje
  29.  
  30. $query = $this -> db -> query("SELECT COUNT(id) FROM star WHERE x = " . $newX . " AND y = " . $newY . "") -> row_array();
  31.  
  32. if ($query['COUNT(id)'] > 0) {
  33.  
  34. echo "Taka gwiazdka istnieje spróbuj jeszcze raz!";
  35.  
  36. } else {
  37. return array($newX, $newY, $newZ, $area);
  38.  
  39. }


Ten post edytował dexter00 16.11.2012, 14:38:57
Go to the top of the page
+Quote Post
b4rt3kk
post
Post #10





Grupa: Zarejestrowani
Postów: 1 933
Pomógł: 460
Dołączył: 2.04.2010
Skąd: Lublin

Ostrzeżenie: (0%)
-----


Możesz ją spłaszczyć w łatwiejszy sposób. Mianowicie, trzeba zacząć od zmodyfikowania zapytania:

  1. for ($i = 1; $i <= 20; $i++) {
  2. $news_count[$i] = $this -> db -> query("SELECT COUNT(*) AS ile FROM star WHERE area LIKE " . $i . "") -> row_array();
  3. $flat[$i] = $news_count[$i]['ile'];
  4. }


Wszystko odbywa się w jednej pętli. I teraz $i to identyfikator obszaru (area), natomiast wartość $flat[$i] to liczba punktów w tym obszarze.
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 23.08.2025 - 20:43