#4Developers i powrót do RL

Ahh. Już w domu, szkoda. 
Emocje opadły, wiedza jeszcze się indexuje xD ale Wartało!

Cała ścieżka .Net przepleciona z małym odskokiem follow by @konradkokosa

No ale po kolei:

Pierwsze Before PARTY YEaah. Jadąc z Jasła, byliśmy pewni że wpadniemy do klubu i nie będzie już gdzie siąść. Ale udało się wbić na free browar dla pierwszej setki, 43 byłem zeskanowany :). Jakoś w dziwnych okolicznościach mykły 4 browce i cała impreza praktycznie przeniosła się na zewnątrz. Oprócz przechadzającego się gandalfa, najważniejszy był wodzirej @j_palka, który nawoływał do wspólnej integracji wymownymi cytatami "Pijemy, Pijemy, Pijemy!" :) Funn na maxa.

F# -> C#  @bartsokol

Trzeba przyznać się, że głowa z rana jeszcze pulsowała, ale za to Bartek przygotował dosłownie prezentacje w sam raz na rozgrzewkę. I w brew pozorom nie był to jakiś low level. Gość pokazał jak za pomocą 2 klas szablonowych(Result<T> i Optional<T>) i 2 komend(Map, Bind) zbliżyć składnię F# do C# i POSPRZĄTAĆ!.
Coś pięknego. Zamiast skakanie po blokach if-ów i kolejnych zagnieżdźeniach, można bardzo przejżyście i zrozumiale Biznesowo utrzymać kod przynajmniej w głównej akcji.

Przykład jak wyglądała by taka zmiana niku przeze mnie:

public Response ChangeNick(ChangeNickModel model)
    {
        try
        {
            string error = UsersManager.ValidModel(model);
            if(string.IsNullOrWhiteSpace(error))
                return new { Error = "Istnieje inny user z takim nickiem", Succes = false };
            using (var db = new DbContext())
            {
                var user = UsersManager.GetUserModel(model.nick,db);
                if (user != null)
                {
                    if (UsersManager.CheckNickIsFree(model))
                    {
                        if (UsersManager.ValidPassword(user.nick, user.pw))
                        {
                            UsersManager.SetNewNick(user.nick, user.newNick);
                            EmailManager.SendNewNick(user);
                            var newUserToStore =  UsersManager.GetUser(user.newNick);
                            return new {Succes = true, NewUserToStore = newUserToStore};
                        }
                        else
                        {
                            return new { Error = "Błędne hasło", Succes = false };
                        }
                    }
                    else
                    {
                        return new { Error = "Istnieje inny user z takim nickiem", Succes = false };
                    }

                }
                else
                {
                    return new { Error = "Błędy user", Succes = false };
                }
            }
        }
        catch (Exception)
        {
            return new { Error = "Z przyczyn bliżej nam nie znanych nie możemy ci pomuc", Succes = false };
        }
    }

W sumie operacja nie jest skomplikowana ale trochę zajmuje.

Kod by Bartek byłby *Uwaga mogę coś pokiklać ale mam : 

public Response ChangeNick(ChangeNickModel model)
    {
        return model.Map(UsersManager.CreateChangeNickContext)
            .Map(UsersManager.ValidModel)
            .Bind(UsersManager.GetUser)
            .Bind(UsersManager.CheckNickIsFree)
            .Bind(UsersManager.ValidPassword)
            .Bind(UsersManager.SetNewNick)
            .Bind(EmailManager.SendNewNick)
            .Map(context => new { Succes = true,NewUserToStore = context.User});
    }

Troche bardziej czytelnie niee ? :D Fakt faktem, że do tego potrzebne są te klasy i metody, które miał Bartek na prezentacji. Więc jak je udostępni to podrzucę je tutaj.(EDIT JEST !: https://speakerdeck.com/bartsokol/functional-developer-in-object-oriented-world)
Oczywiście, ktoś powie, że więcej kodu pewnie się napisze bo np zrobimy klasę kontekstu zmiany niku, ale jednak jak wróci się do tego kodu po 9 miesiącach to odrazu wiadomo co jest wykonywane. A dodam ze haczykiem tych klas szablonowych jest to. że jeśli wystąpi błąd na np 2 kroku to jego propagacja zostanie- przeleci przez pozostałe metody lecz bez ich wywoływania. ILE MIE IFÓW   Óffff.

Flow wątków w TPL by @maklipsa

Kiedyś myślałem że korzystam z TPL, ale to co pokazał Szymon jest kozackie. Drugi raz jestem na prelekcji Szymona i gość gasi moje pragnienie na content. Boje się iść na 3 prezentację xD.  Ale do content-u, to że Taski są jednym z debeściackich rzeczy w .Net i to że bardzo łatwo się ich używa to nie wiedziałem, że za pomocą TPL można połączyć te wszystkie Taski w uporządkowane flow z bloków, a cała kwintesencja jest w tym iż każdy z bloków może posiadać swoją kolejkę do wykonania, w ilu Taskach będzie ją realizować, Ile wiadomości per Task, i co najważniejsze ile wiadomości w jednym czasie, czyli po mega rozgałęzieniu można zejść do 1 taska gdzie będzie obsługa czegoś mega nie Thread Safty jak SQL tak jak to ma miejsce u Szymona.

Polecam mega przestudiować jego prezentacje na ten temat i oczywiście Dać Stara github.com/maklipsa/donetconfpl_tpldataflow

ETW  & Memento Memori by master of Memory @konradkokosa

Konrada to bym mógł słuchać godzinami. Dwie prelekcje, pierwsza o narzędziu ETW, które jest jest od dawna a nie wyparło logowania do pliku :), pomimo iż nadaje 0 narzut na produkcje i załączenie/wyłączenie logów nie wymusza jakiegokolwiek wstrzymania Serwisu/Witryny/Programu/Serwera. Natomiast ma ono tyle możliwości być toolem zarówno do monitorowania performance naszej apki jak i jej zdarzeń. Wychodzi na to że żadne memory profilery nie są potrzebne a z ETW korzystamy na co dzień w EventLog(Rejestr zdarzeń) i Monitor zasobów. 

Natomiast druga prezentacja to kwintesencja starej dobrej zasady, "Dopuki nie wiesz jak to działą, to nie wiesz co się dzieje". Trzeba znać choć podstawową wiedzę aby posługiwać się sprawnie narzędziami. I tak na podstawie ciekawych przykładów Konrad pokazał jak np. cache L3 zrobi nam psikusa.  Zgłębianie tematów wydajności to coś za czym można podążać za Konradem na jego blogach : tooslowexception.com  i blog.kokosa.net

Try use Serverless in @gutek live 

Nie wiem czy to tradycja u gutka, ale również w tamtym roku, przygotował podczas prezentacji przerywnik typeof(Exception). Zapowiedział że tak będzie, więc żadnej wtopy nie było. Za to bardzo fajnie porównał rozwiązanie Azure i Amazon. Jedno wiem na pewno, tym trzeba się pobawić i cieszy fakt że jest to za free do po testowania azure.microsoft.com/en-us/services/functions/  a na prd jest limit 10 000 req/m  ? Coś takiego.

The only thing that matters @Scooletz

Pierwszy raz na prezentacji Szymona, i jednak muszę powtórzyć temat na rzemioslo.it gdzie będzie ta prezencja. Swoją drogą zapraszam do RZESZOWA :D 

 

Natomiast pozostałe 3 prezentacje jeszcze się procesują w mojej głowie. Jednego jestem pewien, POLECAM jak najbardziej 4developers. A jeszcze bardziej polecam do śledzenia tych prelegentów, bo ich wiedza na festiwalu to strzał w głowę nową energią, a żeby zgłębić ich wiedzę zachęcam do ich blogów :)

 

A teraz powrót do realu :D 

Znajdź najkrótszą ścieżkę i do domu

Znajdź najkrótszą ścieżkę i do domu

Magiczna komenda jaką daje nam silnik i pozamiatane. Nie no co wy, zwróci nam najkrótszą drogę ale po ilości relacji.

MATCH (s:Point),(e:Point),
p = shortestpath((s)-[*]-(e))
WHERE s.name = 'JASŁO' AND e.name = 'RZESZÓW'
return p

No ale nam chodzi o odległość, a posiadamy strukturę punktów osadzonych na kawałkach drogi, a poruszamy się między punktami, droga to tylko medium. Więc w głowie pojawia się pomysł bezpośredniego połączenia punktów.

MATCH (s:Point)-[r:Stay]-(t:Segment)
where  r.lineNo = t.lineNo
with distinct s,r.km as km, t.lineNo as  lineNo
order by km 
with collect({s:s,km:km,lineNo:lineNo}) as one , collect({s:s,km:km,lineNo:lineNo}) as two
UNWIND one as ss 
with  ss  , filter(next IN two WHERE ss.lineNo = next.lineNo and next.km >= ss.km and NOT next.s.name = ss.s.name)[0] as nss
with  ss.s as fi,  nss.km-ss.km as distance , ss.lineNo as lineNo, nss.s as se
where se is not null
merge (fi)-[:Connect{distance: distance ,lineNo: lineNo}]-(se)

Przy tym skrypcie się już trochę rozpoznałem Cypher'a, ale jeśli ktoś ma inny pomysł na połączenie tego to proszę bardzo :).

Mając na połączone punkty no to tylko sumować odległości dzieki reduce i dawaj najkrótszą. 

START  startNode=node:node_auto_index(name="Start"),
             endNode=node:node_auto_index(name="Finish")
MATCH  p=(startNode)-[:NAVIGATE_TO*]->(endNode)
RETURN p AS shortestPath,
                reduce(distance=0, r in relationships(p) :  distance+r.distance) AS totalDistance
                ORDER BY totalDistance ASC
                LIMIT 1;

I lepiej tego nie puszczać jeśli się ma więcej niż 100 nodów. XD Gdy rozpoczeła się walka z brakiem RAM i mając już 5 min zastanawiania się dlaczego to tak długo, zrozumiałem że gość tak naprawdę robi iloczyn kartezjański i wszystko próbuje obliczyć... Porażka, Jak takie zajefajne grafy i na 25k Pointów i 60k odcinów się wysypuje. 

No ale 90% problemu to brak zrozumienia jak to działa. I oczywiście każdy miał na studiach algorytmy i było o takim na D, co tak szybko szuka. 

Daleko szukać i głowić się nie trzeba, jest już zaimplementowany jako plugin do neo, neo4j-apoc-procedures

MATCH (s:Point{name:'JASŁO'}),(e:Point{name:'RZESZÓW'})
CALL apoc.algo.dijkstra(s, e, 'Connect', 'distance') YIELD path, weight
RETURN path, weight

No i to już jest faktyczna prawdziwa najkrótsza ścieżka.

Teraz temat co jeśli nie możemy jechać przez np Czudec.  Na szybko mam tylko taki pomysł żeby skopiować relacje które są dostępne czyli bez Czudca, a następnie wyszukać połączenie, i oczywiście pamiętać żeby to chwilowe powiązanie usunąć.

MATCH (s:Point)-[c:Connect]-(t:Point)
where s.name <> 'Czudec' and t.name <> 'Czudec' 
merge (s)-[:Connect_tempWOCzud{distance: c.distance ,lineNo: c.lineNo}]-(t)

Jak sprawdziłem skopiowanie 2k relacji bez 2 bo akurat tyle miał Czudec to 450ms, więc jeszcze nie tak źle. Gorsza jest trasa bez przejazdu przez Czudec gdzie okazuje się że muszę nadgonić 100km aby go ominąć. Taką mamy mapę :)

MATCH (s:Point{name:'JASŁO'}),(e:Point{name:'RZESZÓW'})
CALL apoc.algo.dijkstra(s, e, 'Connect_tempWOCzud', 'distance') YIELD path, weight
RETURN path, weight

 

Próbując wytyczyć alternatywne ścieżki okazało się że dane są nie dokładne a najlepszy błąd to stworzenie punktu Granica Państwa gdzie z odległością 0 można się teleportować z Zgorzelca do Cieszyna :) 

Tyle eksperymentów z czystym Neo, następny krok to kawałek, który będzie miał za zadanie obsługę obsługę całej transakcji bez wyłączonych odcinków itd.

I DO DOMU :D 

 

WebRTC-skype? a może coś więcej

Może kolejny komunikator wideo to nie najlepszy pomysł ale wykorzystanie WebRTC może zaspokoić potrzeby biznesu i Helpdesków. :) 

https://www.youtube.com/watch?v=ocg5HN0nt-k

 Kod

https://github.com/sakrut/webrtc-and

https://github.com/sakrut/webrtc-api

 Lepsze strony

https://github.com/GleasonK/android-webrtc-tutorial

https://webrtc.org/start/ 

https://webrtc.github.io/samples/

https://www.html5rocks.com/en/tutorials/webrtc/basics/

 

Daj się poznać 2017

dajsiepoznac.pl

Oto i cały inicjator prowadzenia bloga.

No nic założenia są proste.
Pomysł na Opena to coś, co pomoże złączyć .Neta z Grafami na tyle aby można było wykorzystać to do rozwiązywania problemu komiwojażera.

UUU student ktoś powie. Nic podobnego. Wiem ze w czasach wyznaczania trasy przez Google czy Janosika takie problemy są 300* rzędne, lecz w świecie jakim żyje mój produkt problem ten nadal istnieje i nie znalazłem** narzędzi do jego rozwiązania.

Nie mam ustalonego planu projektu czy też technologi jakich ostatecznie otrzymam. Wiem tylko że będę chciał to w końcowej fazie doprowadzić otrzymać w WinFORMSACH. TAAAAA :D - A czemu nie.

 

Mam nadzieje że przynajmniej moje próby wypocenia się zostaną odebrane pozytywnie.

 

ps. *Nie lekceważ 300 :D  
     ** No sory czasami Ctrl-F i google zawodzi.

 

 

: