Azure Functions iliti kako kupiti njivu preko SMS-a

Imao sam dva skroz dijametralno suprotna use case-a gde sam želeo da dobijem brza obaveštenja (po mogućstvu SMS) o “ponudama” (oglasima). Npr. hteo sam da kupim njivu, ali sam provalio da mi je OK da čekam da se njiva pojavi na doboš preko banke. Drugi use case je da sam hteo da kupim mobilni telefon. U prvom slučaju, nisam želeo da obilazim sajt banke svaki dan za nešto što se pojavi svaka 3 meseca, a u drugom sam želeo jako brza obaveštenja kad se u ponudi pojavi jako jeftin telefon (koji se obično proda za 2-3h od objavljivanja).
Rešio sam da oba problema rešim na isti način, koristeći što više iz Azure stack-a što je moguće. Ne, možda se nismo razumeli, stvarno sam overarchitect-ovao što je više moguće, koristeći što novije i što hipsterskije tehnologije.

<cinizam>

da se ne lažemo, sve ove tehnologije su stare koliko i računarstvo, samo su implementacije drugačije…

</cinizam>

Ovo nije bilo uzaludno iz dva razloga: prvo, naučio sam dosta novih stvari, a i ovakvo rešenje bi imalo smisla za neke veće sisteme, gde skaliranje stvarno može biti problem (ali ne, definitivno ne i za kupovinu njive).
Jedini constraint koji sam imao je da želim da isprobam Azure Functions – serverless ekvivalent AWS-ovim Lambdama. Međutim, bilo je tu par problema, pa evo da prođemo sve natenane.

Šta su Azure funkcije

(preskočite ovaj pasus ako ste upoznati sa Azure funkcijama, ovo je samo uvod)

Azure Functions (ili Azure funkcije, po naški), su Microsoft-ov odgovor na AWS Lambde. Način da se implementira stateless arhitektura što, u zavisnosti od vaše biznis logike, može dosta da uštedi para (plaćate samo izvršavanje funkcija, ali ne i ceo VM koji zvrji prazan ostatak vremena). Slanje SMS-a i skrejpovanje sajtova je baš dobar primer. Ako želite više da znate o Azure funkcijama, krenite odavde.

<cinizam>

Opet moram da se umešam. Nema ništa inherentno stateless u stateless arhitekturi, samo vi ne morate da brinete o tome. Sviđa mi se kako je to sročeno ovde: Serverless = “someone else is responsible for these servers going down”

</cinizam>

Ukratko objašnjenje je da vi pišete samo jednu funkciju (u jeziku u kom hoćete, dosta ih je podržano), i definišete šta je:

  • trigger (kada se funkcija startuje, može biti npr. tajmer, može biti kad stigne nešto na message queue…)
  • input (šta vam je ulaz u funkciju, može biti npr. blob, Document DB dokument…)
  • output (šta je izlaz iz funkcije; može biti sve što i input, ali i razne druge stvari, kao što su HTTP request, slanje mail-a, ili ono što ćemo mi ovde iskoristiti – slanje SMS-a preko Twilio platforme

Za sva ova tri gorepomenuta (trigger, input i output) niste ograničeni na samo jedan, već ih može biti i više od jednog (npr. output je u našem slučaju i Table Storage i Twilio SMS, videćete kasnije), i svi su definisani kao argumenti u toj vašoj funkciji koju pišete.

Ima tu još par gremlina na koje sam naletao, ali ih i dosta brzo rešavao uz pomoć dokumentacije i SO-a, tipa kako da dodaš nove nuget pakete, kako da funkcije dele zajednički kod, a pošto Azure funkcije koriste web apps ispod, sve ostala pitanja su dobila automatski odgovor (kao kako da postavim environment variable, kako da upload-ujem fajl FTP-om, a čak i Kudu radi sa adrese https://<function_app_name>.scm.azurewebsites.net).

Overall, rešenje je bilo prilično očigledno – skrejpuj sajt unutar Azure Functions-a, sačuvaj to negde i pošalji SMS. Al’ ne lezi vraže…

Gde čuvati state sistema u stateless arhitekturi

Prvi problem ovde je bio gde čuvati state sistema, tj. gde čuvati već obrađene njive, odnosno telefone. Od ponuđenih opcija, Azure Functions je nudio Document DB i Table Storage, ali ne i npr. SQL. Hteo sam nešto jeftino i lightweight, pa sam se odlučio za Azure Table Storage (Document DB mi je bio preskup za ovu namenu, mada mislim da bi on bio bolji izbor kad bi ovo trebalo da skalira).

Jedna zanimljiva stvar na koju treba paziti i koja može da vas ujede je da Azure Functions može pokrenuti vašu funkciju više puta konkurentno. Mislite o tome ako vam treba atomičnost. Prost primer je da se dve funkcije pokrenu paralelno, u funkcijama se skrejpuju iste ponude, onda se provere u obe da li postoje u Table Storage-u, i pošto ne postoje, da se pošalje SMS dva puta iz obe. Pazite se!

Kako merge-ovati ponude

OK, sada kad znamo gde je state, kako Azure Function-u da kažemo da ne želimo da ubacimo novi red ako postojeći već postoji. Ispostavlja se da tako nešto ne postoji (što ima logike pošto Azure Functions radi samo sa nekim ulaznom i izlaznom komponentom, ne sa hipotetičkim ulazom koji zadovoljava neki query). Tu sam morao da zasučem rukave i da napravim upit koji će proveriti da li postoji već takva ponuda u Azure Table Storage-u. Da se razumemo, nije ovo teško, nego nije bilo u duhu Azure funkcija. Što se tiče primarnog ključa u Table Storage-u, on podržava dva odvojena entiteta – PartitionKey i RowKey (pretpostavljam da su značenja jasna iz imena). Nekako mi je bilo logično da za PartitionKey postavim sajt sa koga skidam ponudu, tj. tip ponude (njive, telefoni, avioni, kamioni…), a da RowKey dobijem od sajta i da on bude specifičan za datu ponudu.

Ima ovde još jedna bitna stvar vredna pomena. Azure funkcije rade po principu da, ukoliko ste naveli neki output (Table Storage, u našem slučaju), on nije opciona stvar, već Azure očekuje da prosledite novi red i tačka. U ovom slučaju, mi želimo red samo ako ponuda ne postoji već u tabeli. Srećom, Azure funkcije podržavaju ovo, i to tako što output funkcije nije objekat T koji se upisuje u tabelu, već ICollector<T>. Ovakav napravljena kolekcija dozvoljava da krajnji izlaz bude i 0 redova, ali i više od jednog reda!

Decoupling različitih tipova ponuda

Osnovna ideja je da možemo da imamo različite tipove ponuda (njive, telefoni) koje prolaze kroz sistem. Malo bi glupo bilo da sva skrejpovanja svih sajtova budu u istoj Azure funkciji. Takođe, period skrejpovanja za mobilne telefone (npr. 15 minuta) nije isti kao i za njive (max. jednom dnevno). Naravno, kad god je ovakav decoupling u pitanju, uvek je odgovor naš dobar drugar message queue. Azure Functions podržava taj scenario (queue može da bude trigger), a Microsoft-ovo rešenje se zove Azure Service Bus. Naravno, format ponuda koje ćemo trpati u queue će biti JSON (zato što je XML so 1990s). Sada je iz aviona jasno rešenje – napraviti N različitih Azure funkcija, gde će svaka da skrejpuje po jedan tip sajtova sa ponudama, trigger će im biti tajmer, a output će im biti Azure Service Bus. JSON koji pumpaju u Service Bus može da bude kakav god dictionary, ali mora da ima ključeve “partition” i “id” u njemu. Sa druge strane queue-a je funkcija kojoj je trigger Service Bus, a kojoj je zadatak da čita ponudu iz Service Bus-a, proveri da li zadata ponuda postoji već u Table Storage-u, a ima dva output-a – jedan je opet Table Storage (opcioni, i ima ga samo ako se pojavi nova ponuda koja treba da se upiše), a drugi je, takođe opcioni Twilio SMS servis.

Krajnje rešenje

Posle svih ovih problema, evo i šematski prikaz kako izgleda ovaj moj overarchitect-ovani Frankenštajn:

Jeste ružno, ali i treba da bude ružno. Inače, cela ova zezancija košta oko 1$ mesečno (plus 1$ za Twilio SMS servis), što je mnogo manje nego da sam uzeo VM na koji bih npr. potrpao neki Python plus Mongo. Nisam ekspert, a nisam ni probao AWS Lambdu da bih dao bolji pregled i imao bolju referentnu tačku, ali evo stvari koje treba da se unaprede, po meni:

  • Podrška za SQL (ima nas matorih koji bi ipak koristili SQL) i druga NoSQL rešenja
  • Podrška za lokalno testiranje (to danas nije moguće)
  • Twilio SMS servis nije radio, morao sam “ručno” da ga dodajem (ovaj OOB je imao problema) – loš prvi experience za Micorosft i Azure.

Ako vas zanima neki detalj o ovome što sam pričao, ceo source code je dostupan na GitHub-u. Ako vas ne zanima nijedan detalj i sve vam je jasno, možete uvek otići na ovaj link da vidite moj broj telefona i da mi me pozovete i zahvalite na kristalno jasnom opisu Azure funkcija:)

Evo i za kraj kako to izgleda na portalu:

Posted in Programiranje | Tagged , , | Leave a comment

Visualizing world’s births and deaths

All data presented here is available as spreadsheet.

World population grows exponentially. Can we graph accurately world’s births and deaths since the dawn of the civilization? Of course not, but in this post I will try something (that I don’t think) anyone tried before. Idea is simple – every wikipedia article about a person has a category that is like “YYYY births” and “YYYY deaths” (if that person is dead). We can use this metadata to create a graph depicting births and deaths  in that specific year. I used Pywikibot to fetch this data. Here is the source code:

#!/usr/bin/env python
import wikipedia as pywikibot
import catlib
 
def main():
    site = pywikibot.getSite(code='en')
    for year in range(1, 2010):
        #cat = catlib.Category(site, "%s:%s" % (site.namespace(14), "%d_deaths" %year))
        cat = catlib.Category(site, "%s:%s" % (site.namespace(14), "%d_births" %year))
        print "%d - %d" % (year, len(cat.articlesList()))
 
if __name__ == '__main__':
    main()

And as already said, here is the spreadsheet with all the data. Before presenting results, just a small disclaimer – this approach has several disadvantages. First of all, results are collected from English Wikipedia, and as huge as it is, it is still western-centric, so probably in this statistics we are missing a lot of Chinese and other eastern world related persons. Secondly, a lot of people, especially those born in the distant past don’t have accurate year of birth or death. In a way, presented result will reflect our knowledge of the historical people’s life more than it will present world population growth, but some interesting results can be observed nonetheless. Thirdly, these are statistics just for notable persons, but I think, it can scale to whole population as well. Please feel free to comment whatever you see I missed or to further explain things on graphs where I don’t have explanations. All the data presented here is up to year 2009.

Births

This is graph of people’s births. On the x-axis are years, and on y-axis are number of births (click to enlarge):

births

Graph presented above is not very useful, so we’ll construct better one. Graph shown below is constructed by taking averages of births in range of 10 years (to see general trends) and is in logarithmic scale (due to the exponential nature of this kind of data). It reveals much more now (click to enlarge):

births-log

Now that we have these graphs, let’s see what we can conclude from them. We’ll start chronologically:

  • (red logarithmic graph) There is large rise of births around year 170, mostly all of them are Chinese military generals (you can see that here and here). I don’t know Chinese history, but they all relate to period of Three Kingdom era. Question now is – is this era period of great development in China or  is this the period when nothing important happened in Europe?
  • (red logarithmic graph) Around 600-1100 you can see there is no rise in birth’s graph. Of course, there should be, because population growth was constant, so I think this could be explained by Dark age period.
  • (red logarithmic graph) You can see rise in the first half of 17th century that I can’t explain. Is it large rise or large fall that happened after? Can that large fall be because of some catastrophic events like plague in Europe at that time? Or, there is large, but century long continuous rise because of also some large, but century long continuous catastrophe? Can baby boomer generation happen, but in large scale, spanning for decades? Or maybe it is just a pinnacle of renaissance, so there was a lot of famous people at that time?
  • (blue, linear graph) You can see very large rise in births after WWII (concrete year is 1947, you can see that in spreadsheet). I think this is very good visualization of baby boomer generation.
  • (blue, linear graph) Highest peak in births is around 1979-1985 (largest number of people born in Wikipedia is in 1982.), so I guess that you can, looking at this, see what is the most probable year of one’s affirmation and recognition. If you’re older than this, then your chances to become famous are becoming slimmer and slimmer every day:)

Deaths

Let’s take a look on number of deaths over the years. Here’s a linear graph (click to enlarge):

deaths

And here’s the same graph, but averaged in 10 years period and in logarithmic scale (click to enlarge):

deaths-log

Some observations I came up with:

  • (red logarithmic graph) The first thing you notice on this graph is a large peak around year 304. Reason is Diocletian persecution of Christians that happened that year and a large number of people that will later become Christian martyrs died. See for yourself.
  • (red logarithmic graph) Also interesting is a large drop of deaths around year 440 for which I really don’t have an explanation.
  • (red logarithmic graph) As in birth’s graph, here we also see a large rise in deaths between 16th and 17th century (or a large drop of deaths after that?) which  is also puzzling for me.
  • (blue, linear graph) Sudden jump around 1914-1918 is pretty clear. Deaths of millions, greatest tragedy ever, visualized as just a few pixels…
  • (blue, linear graph) Also jump around 1938-1945 shows how many great people died in WWII (and also millions of them unknown, that don’t have their place in Wikipedia…)
  • (red logarithmic graph) In contrast to birth’s graph that drops rapidly after 1985., graph of deaths just continues to grow, logically.

Is there anything else you can add to this observations that I missed? Can you explain better than me slopes in these graphs? Let’s squeeze all the facts we can from these data!

Posted in Analitika, Programiranje, Python | Tagged , , | 1 Comment

Prosečne cene stanova u Beogradu 2. deo (Heat mapa)

Dokaz da imam najbolju ženu na svetu se ne ogleda samo u činjenici da mi je rodila najbolje i najlepše dete na svetu i da je ona moj anđeo čuvar (kako metaforčki, tako i fizički – desilo se par puta da sam mogao da nastradam da nije bilo nje, ali hoće to tako kod rasejanih budala), već i u činjenici da ona može da isprati svaku moju ideju, ma koliko debilna bila:)

Čim sam okačio prethodni post na blogu u vezi prosečnih cena stanova u Beogradu, ona ga je prva pročitala, tražila konekciju na bazu i uzela nešto da čeprka. Vratila se sa heat mapom prosečnih cena stanova u Beograda. Ja sam napisao tamo da bi bilo interesantno to napraviti, a ona je uzela i actually to napravila! Nisam sad baš siguran da li se ovo zove heat mapa ili je ovo nešto drugo, ali ovo je definitivno neka lepa mapa gde su prikazani svi stanovi u ponudi, sa veličinom ponude i prosečnim cenama kvadrata.

Boja označava prosek cena u tom delu grada, a veličina krugova označava broj stanova u ponudi za taj deo grada. Klik na sliku za veću verziju. Uživajte (i zahvalite se njoj što čitate i gledate ovo:)!

 

mapa-v2

 

Tehnički detalji (koga interesuje)

Mapa je rađena u R-u i korišćen je `ggmap` paket u poluautomatskom modu rada (nešto što Google nije mogao da pronađe je moralo ručno). To je ono što ja znam, za sve ostalo morate pitati eksperta (e-mail adresa poznata redakciji:).

Posted in Analitika, Programiranje, SQL | Tagged , , , | 4 Comments

Prosečne cene stanova u Beogradu

Trenutno sam u pripremama početne faze započinjanja razmatranja mogućnosti kupovine stana. Kao što se može primetiti iz prethodne rečenice, imam još da radim oko ovoga, ali nekako mora da se počne.

E, sad, kao svaki pravi mali dobri programer, prvo što mi je palo na pamet da mora da se uradi jeste da se obiđu svi domaći sajtovi za nekretnine i da se sa njih skinu (scrape-uju) svi stanovi za offline detaljnu analizu. Znam, znam, ljudi kupuju stanove i bez da urade matematičku analizu i data mining, ali evo zašto ovo ima svojih prednosti:

  • Mnogo bolje filtriranje – ja otprilike imam predstavu šta tražim, ali kada bih koristio samo veb sajtove agencija za filtriranje, morao bih da pregledavam na hiljade stanova
  • Trenutna detekcija novoponuđenih stanova – kad se skripta ponovo pokrene, tačno znate koji su novi stanovi u ponudi
  • Trenutna detekcija smanjenih cena stanova – kad se skripta pusti da prođe ponovo za sve stanove, vrlo lako može da primeti da li je cena pala ili ne
  • It’s fun:) – verovatno znate onaj vic “zašto pas liže svoja jaja?”. “Zato što može”

Tehnički detalji (koga interesuje)

Skripta je napisana u Python-u, skidani su stanovi sa sajtova mojkvadrat.rs i halooglasi.com, a za svaki posebno je trebalo oko 200 linija koda. Korišćene tehnologije su: SQL Azure, BeautifulSoup, urllib3 i pyodbc. Ceo kod i dump baze se nalazi na: https://github.com/stalker314314/ScrapeStanovi.

TODO lista

  • Uraditi merge-ovanje stanova od različitih source-ova (detekcija duplikata)
  • Dodati još source-ova
  • Detekcija da li je stan u ponudi od strane agenta ili direktno
  • Heat mapa Beograda sa prosečnim cenama stanova (ovo sam probao da nađem na R repozitorijumima, kao i na Google Fusion Table repozitorijumima i nisam, nažalost, našao nikakve postojeće mape Beograda, a ne pravi mi se ovo od nule)

Prosečne cene stanova

E, sad ono zbog čega je ceo ovaj tekst i napisan. Kada je skripta skinula sve stanove, nad njima mogu da se rade razne analize. Jedna jako očigledna, a vrlo interesantna je da se pogleda koje su prosečne cene kvadrata po delovima grada. Kad su podaci već skinuti, ovo je trivijalno, a za vas evo ovde celu liste na pregled, nadam se da će vam biti zanimljivo. Uživajte!

Opština Deo Cena kvadrata [€/m2]
Stari grad Knez Mihailova 2528
Stari grad Trg Republike 2404
Stari grad Francuska 2286
Stari grad Studentski trg 2230
Novi Beograd YUBC 2089
Stari grad Kosancicev venac 2057
Stari grad Toplicin venac 1999
Stari grad Dom omladine 1958
Stari grad Kralja Petra 1948
Novi Beograd Blok 67 (Belvil) 1946
Vracar Hram svetog Save 1941
Vracar Krunska 1938
Stari grad Skupština 1887
Stari grad Terazije 1874
Stari grad Obilicev venac 1865
Vracar Cvetni trg 1861
Palilula Mašinski fakultet 1852
Vracar Kalenic pijaca 1823
Stari grad Kalemegdan 1814
Vracar Karadordev park 1796
Novi Beograd Arena 1792
Stari grad Centar 1786
Vracar Slavija 1763
Voždovac Jove Ilica 1749
Savski venac Kraljice Natalije 1742
Savski venac Dedinje 1736
Stari grad Gundulicev venac 1736
Palilula 27. marta 1731
Palilula Tašmajdan 1721
Stari grad Dunavski kej 1702
Stari grad Atelje 212 1696
Savski venac Nemanjina 1689
Savski venac Svetozara Markovica 1680
Vracar SC Vracar 1673
Stari grad Skadarlija 1669
Stari grad Takovska 1665
Vracar Pravni fakultet 1660
Stari grad Dorcol 1659
Stari grad Trg Nikole Pašica 1648
Savski venac Klinicki centar 1648
Savski venac Resavska 1645
Zvezdara Uciteljsko naselje 1633
Vracar Neimar 1629
Vracar Gradic Pejton 1624
Vracar Cubura 1620
Stari grad Cara Dušana 1619
Stari grad Bajlonijeva pijaca 1618
Voždovac Hotel M 1616
Stari grad Politika 1611
Vracar Bulevar kralja Aleksandra 1605
Palilula Palilulska pijaca 1596
Vracar Crveni krst 1594
Savski venac Centar 1576
Stari grad Kopitareva gradina 1568
Savski venac Senjak 1537
Zvezdara Vukov Spomenik 1531
Savski venac Brankova 1525
Savski venac Kneza Miloša 1523
Zvezdara Ðeram pijaca 1522
Vracar Beogradska 1517
Savski venac Balkanska 1512
Novi Beograd Blok 29 1498
Palilula Centar 1487
Novi Beograd Blok 24 (Super Vero) 1486
Palilula Poštanska štedionica 1484
Vracar Južni bulevar 1479
Zvezdara Lion 1472
Palilula Botanicka bašta 1467
Novi Beograd Sava centar 1465
Voždovac Lekino brdo 1462
Palilula Hadžipopovac 1460
Novi Beograd Blok 30 (B92) 1455
Zvezdara Dimitrija Tucovica 1451
Novi Beograd Blok 22 1444
Stari grad Zeleni venac 1444
Voždovac Centar 1433
Savski venac Ekonomski fakultet 1430
Zemun Retenzija 1426
Voždovac FON, Bilecka 1424
Zemun Kej 1419
Novi Beograd Novi Merkator 1416
Voždovac Bioskop Voždovac 1408
Palilula Profesorska kolonija 1403
Savski venac Palata pravde 1397
Novi Beograd Hotel Jugoslavija 1396
Novi Beograd Blok 21 1394
Stari grad Savamala 1393
Zvezdara Bulbulder 1391
Voždovac Bulevar oslobodenja 1388
Zvezdara Lipov lad 1387
Novi Beograd Blok 34 (Carina – Studentski grad) 1381
Voždovac Vojislava Ilica 1377
Zvezdara Slavujev venac 1374
Novi Beograd Blok 23 1374
Novi Beograd Blok 19a 1373
Zvezdara Denkova bašta 1366
Novi Beograd Blok 3 1364
Zemun Karadordev trg 1354
Novi Beograd Blok 2 1352
Palilula Cvijiceva 1351
Zvezdara Gradska bolnica 1351
Voždovac Autokomanda 1345
Zvezdara Cvetkova pijaca 1333
Novi Beograd Fontana 1333
Cukarica Golf 1331
Novi Beograd Opština 1329
Voždovac Voždovacka crkva 1328
Savski venac Sarajevska 1325
Rakovica Stari Košutnjak 1324
Voždovac Trošarina 1315
Zvezdara Bulevar kralja Aleksandra 1312
Savski venac Humska 1311
Novi Beograd Blok 33 1309
Voždovac Vitanovacka 1285
Novi Beograd Stari Merkator 1282
Voždovac Darvinova pošta 1279
Novi Beograd Blok 4 (Politehnicka akademija) 1276
Voždovac Šumice 1274
Cukarica Košutnjak 1272
Voždovac Vojvode Stepe 1270
Cukarica Banovo brdo 1260
Zvezdara Olimp 1258
Novi Beograd Blok 70a 1246
Palilula Bulevar despota Stefana 1242
Novi Beograd Blok 44 (TC Piramida) 1242
Cukarica Suncana padina 1241
Zvezdara Severni bulevar 1236
Novi Beograd Blok 37a 1236
Novi Beograd Bežanijska kosa 3 1235
Novi Beograd Blok 38 1233
Savski venac Karadordeva 1231
Novi Beograd Blok 28 1225
Voždovac Dušanovac 1220
Novi Beograd Blok 37 1214
Zvezdara Zvezdara 2 1213
Zemun Centar 1205
Novi Beograd Bežanijska kosa 1 1202
Novi Beograd Blok 70 (kineski tržni centar) 1199
Voždovac Saobracajni fakultet 1194
Zvezdara Kluz 1193
Cukarica Filmski grad 1193
Zvezdara Rudo 1186
Novi Beograd Blok 62 1182
Voždovac Ustanicka 1180
Novi Beograd Paviljoni 1177
Novi Beograd Bežanijska kosa 2 1175
Novi Beograd Blok 45 (TC Enjub) 1167
Zemun Donji grad 1164
Voždovac Kumodraška 1163
Novi Beograd Blok 63 1161
Cukarica Cukaricka padina 1151
Novi Beograd Tošin bunar 1147
Novi Beograd Stara Bežanija 1146
Voždovac Konjarnik 1144
Zemun Cara Dušana 1139
Cukarica Cerak vinogradi 1135
Novi Beograd Blok 64 1135
Palilula Bogoslovija 1128
Voždovac Zaplanjska 1124
Novi Beograd Blok 61 1122
Zemun Ugrinovacka 1120
Zemun Save Kovacevica 1118
Zemun Kalvarija 1108
Novi Beograd Dr Ivana Ribara 1099
Voždovac Medakovic 3 1077
Voždovac Banjica 1077
Zemun Meandri 1070
Zvezdara Zvezdarska šuma 1070
Voždovac Farmaceutski fakultet 1066
Zemun Prvomajska 1064
Cukarica Cerak 1063
Zemun Marija Bursac 1062
Cukarica Žarkovo 1045
Zemun Gornji grad 1044
Voždovac Brace Jerkovic 1043
Voždovac Medakovic 2 1038
Zvezdara Cvetanova cuprija 1014
Palilula Višnjicka Banja 1010
Voždovac Medakovic 1 1005
Zvezdara Mirijevo 1001
Rakovica Skojevsko naselje 1000
Zvezdara Zeleno brdo 997
Rakovica Vidikovac 995
Rakovica Kanarevo brdo 995
Palilula Karaburma 993
Palilula Calije 993
Zemun Galenika 983
Zemun Nova Galenika 979
Cukarica Julino brdo 975
Rakovica Miljakovac 972
Zemun Novi grad 964
Zvezdara Veliki Mokri Lug 957
Voždovac Medakovic padina 952
Voždovac Kumodraž 947
Rakovica Novo Skojevsko naselje 940
Rakovica Labudovo brdo 935
Zvezdara Mali Mokri Lug 934
Cukarica Bele vode 922
Rakovica Centar 904
Rakovica Petlovo brdo 903
Rakovica Kneževac 862
Zemun Batajnica 860
Cukarica Železnik 860
Palilula Višnjica 859
Rakovica Vidikovacka padina 839
Novi Beograd Ledine 828
Palilula Borca 810
Voždovac Jajinci 809
Zemun Zemun polje 800
Zemun Altina 785
Zemun Kamendin 761
Palilula Krnjaca 759
Rakovica Resnik 750
Grocka Kaluderica 748
Palilula Kotež 734
Cukarica Sremcica 718
Obrenovac Obrenovac (mesto) 707
Mladenovac Mladenovac (mesto) 624
Palilula Padinska skela 536
Barajevo Barajevo (mesto) 492
Posted in Analitika, Programiranje, Python | Tagged , , | 5 Comments

Menjanje funkcionalnosti dugmeta za gašenje računara

Koliko često koristite dugme za gašenje računara? Јa ga lično nikad ne koristim, a i čak da imam potrebu da gasim ili restartuјem računar, ne bih ga koristio (prosto, toliko se retko koristi da u onom deliću sekunde kada treba ugasiti računar mi nikada ne padne na pamet da ga iskoristim).

Ali, ako, kao i јa, nemate na tastaturi one fensi dugmiće za dodatne funkcionalnosti, zašto ne iskoristiti to dugme za neku dodatnu funkciјu.

Koristiću Ubuntu da podesim ovo, ali, uz male (ili nikakve) izmene, ovo će raditi na bilo koјoј distribuciјi. Prvo treba da uklonimo Gnom ekran za odјavu koјi se poјavljuјe kada se pritisne ovo dugme. Za ovo, treba da izmenimo sledeća dva ključa u gconf-u:

/apps/gnome-power-manager/action_button_power
/apps/gnome-power-manager/buttons/power

na “nothing” (bez navodnika). Ovo će skloniti ekran za odјavu. Sada samo treba izmeniti /etc/acpi/powerbtn.sh da radi ono shto Vi hoćete. Izložiću dva moguća scenariјa, ali stvarno nema ograničenja šta se sve može uraditi.

Uključivanje/isključivanje interneta

Već sam imao dve male skriptice da uključuјem i isključuјem internet nekim korisnicima koјima ga rutiram. Ovo su neke iptables stvari (nebitno ovde, nešto poput `iptables -I FORWARD -p ALL -s 192.168.0.122 -j DROP`) i morao sam da otvaram konzolu, gasim internet, pa posle da ga vraćam. Ovo se može izvesti sa sledećim upisanim u /etc/acpi/powerbtn.sh:

#! /bin/sh
if [ -f /var/tmp/internet_off ]; then
/etc/rc.start_internet
rm /var/tmp/internet_off
else
/etc/rc.stop_internet
touch /var/tmp/internet_off
fi

Glupa skripta koјa proverava da li faјl /var/tmp/internet_off postoјi i na osnovu njega izvršava odgovaraјuću skriptu. Takođe, ako imate nekog dovoljno glupog, možete ga ložiti da nema internet јer јe Vaš računar isključen, a to što vide јe samo slika, ili im prospete priču o virtualnoј (vauuu!) mašini koјa radi i kada јe rachunar isključen. Svi znaјu za VirtualBox, pitanje јe da li ste dovoљno ubedljivi;) Na kraјu kraјeva, uvek možete da pred njima pokažete da kliktanjem na dugme gasite i palite Vaš računar i da oni tad nemaјu interneta.

Pokretaњe firefox-a

Svakodnevno koristim firefox. Ako ima iјedno dugme da bih njemu dodelio pokretanje nekog programa, onda bi to sigurno bio firefox. Ali, da bi startovali GUI program iz skripte koјa se pokreće kao root, moramo malo da budžimo. Moramo da podesimo DISPLAY i XAUTHORITY promenljive.

#! /bin/sh
export DISPLAY=:0
export XAUTHORITY=/home/vaše_korisničko_ime/.Xauthority
sudo -u vaše_korisničko_ime firefox

Ali, ova skripta ima par mana. Ako firefox već radi, ona će pokrenuti totalno novi prozor, a vidimo i da se “vaše_korisničko_ime” provlači svuda. Evo bolje verziјe:

#! /bin/sh
USERNAME=vaše_korisničko_ime
export DISPLAY=:0
export XAUTHORITY=/home/$USERNAME/.Xauthority

if ps -U $USERNAME -u $USERNAME|grep firefox; then
sudo -u $USERNAME firefox -new-tab about:blank
else
sudo -u $USERNAME firefox
fi

Ako firefox radi, samo će se otvoriti novi prazan јezičak, u suprotnom će ga pokrenuti normalno. A i “vaše_korisničko_ime” јe izvučeno na početak skripta, pa tako samo treba promeniti drugu liniјu i skripta će proraditi. Uživaјte!

Dalje ideјe

Samo јedna funkciјa za dugme јe ništa. Možda da podelimo dve različite funkcionalnosti definisanjem običnog i double click-a. Na primer, kreiranjem faјla na prvi klik, a proveravanjem na drugi da li јe faјl stariјi od npr. 2 sekunde (da ne ulazim u detalje ovde). Takođe, ovo dugme može da otvara CD, što da ne:) Kao i sve u Linux-u, Vaša kreativnost јe Vaša јedina granica. Ako i Vi imate јoš ideјa šta i kako sa ovim dugmetom, јavite. Šta biste Vi stavili u /etc/acpi/powerbtn.sh?

 

Posted in Linux | Tagged , , | Leave a comment