Kompilacja i sprawdzanie poprawności zadań

Jak kompilujemy i uruchamiamy zadania

Najważniejszym elementem platformy apki.org będą interaktywne kursy, w których użytkownik dostanie do dyspozycji edytor kodu i możliwość jego uruchomienia oraz zobaczenia po chwili wyniku.

O ile od strony użytkownika brzmi to prowizorycznie (wpisujemy kod i go wykonujemy) to dla nas jest to bardzo duże wyzwanie. Kompilacja dużej ilości języków (każdy ma swoją specyfikę, środowisko wykonywalne, sposoby przekazywania wyników, błędów, danych wejściowych) musi być elastyczna, szybka i bezawaryjna.

Serwery które muszą podołać takiemu zadaniu to niesamowicie potężne maszyny, których kupno i utrzymanie to niesamowicie kosztowne przedsięwzięcie, na które nie mogliśmy sobie pozwolić zarówno ze względów finansowych jak i na nakład pracy potrzebny na stworzenie takiej usługi.

Z w/w problemów musieliśmy skorzystać z zewnętrznej usługi kompilacji, którą udostępnił nam portal HackerEarth (który przy okazji został naszym partnerem strategicznym). Udostępnia nam on bardzo proste api do kompilacji szerokiego spektrum języków, zwracając w przejrzysty sposób wyniki kompilacji, wykonania czy ewentualnych błędów.

Jako że każda kompilacja zajmuje sporą ilość czasu zdecydowaliśmy się wyodrębnić wywołania HackerEarth do osobnej usługi. Jest nią bardzo prosta aplikacja napisana w frameworku Slim (język PHP). Kod tej usługi można zobaczyć na GitHubie. Pośredniczy ona jako pomost między portalem apki.org i usługą kompilacji HackerEarth załatwiając wszystkie problemy z kodowaniem, obsługą różnych miejsc wyników kompilacji i wykonań programów. W tej sposób po wywołaniu tej usługi apki.org mają bardzo prosty wynikowy json zawierający: wyjście (stdout), stan kompilacji (ok lub błąd), pole błędu (jeżeli takowy wystąpił). Jedyne co apki.org muszą zapewnić to kod do kompilacji oraz język w jakim ma ona nastąpić.

Jak sprawdzamy zadania

Ok, mamy już wynik działania kodu użytkownika. Teraz jednak stajemy przed kolejnym problemem. Jak sprawdzić czy zadanie jest poprawne? Stworzyliśmy 3 różne sposoby na kontrolę zadań:

  • Proste sprawdzanie wyniku - nie ma tutaj żadnej filozofii. Jeżeli użytkownik miał za zadanie wyświetlić ciąg witaj to sprawdzamy tylko czy wynik uruchomienia kodu to ten ciąg
  • Wyrażenie regularne - możemy sprawdzić czy kod lub wynik wywołania tego kodu pasuje do stworzonego przez nas wzorca. Kod za to odpowiadający jest dość prosty i zawiera przekazanie 2 zmiennych, input i output do wzorca. Wyrażenia regularne najlepsze są do wyszukiwania wzorców tekstowych, jeżeli prosimy użytkownika o wykonanie jakichś operacji na ciągach znaków.
  • Prosty język skryptowy Dentaku - gem Dentaku pozwala nam na wykonywanie prostych skryptów. Tak samo jak w przypadku wyrażeń regularnych przekazujemy tutaj parametry input i output. Dentaku jednak będzie mieć zastosowanie w przypadku sprawdzania operacji matematycznych. Oba parametry rzutujemy bezpośrednio na typ integer, dlatego jeżeli wynik wykonania kodu lub dane wejściowe nie będą liczbowe to zadanie zostanie oznaczone automatycznie jako nieprawidłowe.

Dzięki tym trzem metodom dajemy twórcy kursu bardzo szerokie spektrum zadań do wymyślenia i sprawdzenia ich poprawności.

Podsumowując - platforma odpowiedzialna za wykonanie i kompilację kodu jest zewnętrzną usługą którą wywołujemy przez pośrednią (bardzo prostą) usługę, dzięki czemu uzyskujemy bardzo dobrą wydajność i bezpieczeństwo działania systemu. Użytkownik może wykonywać dowolny kod bez żadnej wiedzy o środowiskach wykonywalnych, różnicach językowych na konkretny system operacyjny czy niuansach instalacji takich języków. Nie musi także korzystać z żadnego dodatkowego narzędzia w postaci edytora kodu.

Dla dociekliwych - cały kod odpowiedzialny za kontrolę zadań można znaleźć tutaj.

Nekromancer

Programista z zawodu i zamiłowania. W fundacji zajmuje się głównie rozwiązaniami backendowymi oraz aplikacjami mobilnymi. Współtwórca portalu apki.org oraz mentor na forum

Jastrzębie-Zdrój http://ownvision.pl/