HTTPS SSH
### WireWorld - Java + Swing ### **Dawid Sowa** *24 czerwca 2016* Program WireWorld ma za zadanie umozliwic uzytkownikowi symulacje automatu komórkowego działajacego na zasadach WireWorld Briana Silvermana. Uzytkownik ustawia poczatkowa generacje a nastepnie za pomoca graficznego interfejsu sledzi jej przebieg. ## Funkcjonalnosc ## Cała obsługa programu odbywa sie z menu głównego. Wprowadzamy tutaj dane dotyczace wymiaru planszy oraz planowanej liczby generacji. Liczba generacji zmienia sie dynamicznie w czasie działania programu. Mozemy wczytac generacje z pliku (zarówno zapisanego przez program jak i stworzonego przez uzytkownika) oraz zapisac aktualny stan generacji. ## 2.2 Okno wizualizacji ## Za pomoca lewego przycisku myszki przenosimy komórke do kolejnego stanu. Prawym przyciskiem uruchamiamy FileChooser który pozwala wzytac plik bezposrednio na plansze. 3 3 Implementacja 3.1 Diagram klas 3.2 Plansza komórek - klasa Field Obiekt klasy Field reprezentuje pojedyncza generacje mapy. Tworzenie nowej generacji odbywa sie w zaleznosci od parametrów przekazanych do konstruktora. Mozemy stworzyc nowy obiekt na podstawie 1. wymiarów (int x, int y) 4 2. starego obiektu (Field f) 3. dwuwymiarowej tablicy komórek (Cell[][] c) 3.2.1 Reprezentacja - klasa FieldWindow Reprezentacja naszej planszy jest GridLayout wypełniony obiektami klasy JLabel. Obiektom tym ustawiamy rózne kolory tła w zaleznosci od tego jaka komórke reprezentuja. Obiekt iklasy FieldWindow Inicjalizuje sie on na podstawie przekazanego obiektu klasy Field. 3.3 Pojedyncza komórka - klasa Cell i dziedziczace Reprezentacja pojedynczej komórki jest obiekt klasy Cell. Oprócz tego mamy klasy dziedziczace po Cell odpowiedzialne za reprezentacje róznych innych rodzajów komórek. Jak wynika z diagramu klas, klasa Cell dziedziczy po JLabel. Pozwala to na przypisywanie tych samych obiektów zarówno w klasie Field jak i FieldWindow, z czego wynika lepsza przejrzystosc kodu. 3.4 Format zapisu - klasa Stream Klasa Stream jest odpowiedzialna za odczyt danych z pliku do programu oraz zapis danych przetwarzanych w programie do pliku. Dopuszcza ona dwa formaty danych, które rozpoznawane sa za pomoca rozszerzenia pliku. 3.4.1 Format danych programu (*.map) Przetwarzane mapy komórek program jest w stanie zapisac jako zserializowane obiekty klasy Field. Jest to bardzo wygodne rozwiazanie w którym nie musimy zagłebiac sie w strukture pliku. 3.4.2 Format danych uzytkownika (*.ww) Uzytkownicy oprócz interfejsu graficznego moga wprowadzac dane za pomoca odpowiednio sformatowanych plików tekstowych. Przykładowy plik: 3 3 E C E H E C E C E W pierwszej linii okreslamy wymiary planszy (najpierw liczba wierszy, potem liczba kolumn). Nastepnie podajemy ciag znaków który definiuje ułozenie komórek na planszy. Plansza wypełniana jest po kolei, od lewej do prawej od góry do dołu. Mozliwe podanie jest koloru, numeru lub literki dla kazdej odpowiadajacej komórki 1. 0 - H - Color.RED = Głowa elektronu 2. 1 - T - Color.YELLOW = Ogon elektronu 3. 2 - C - Color.BLACK = Przewodnik 4. 3 - E - Color.WHITE = Pusta komórka 5 4 Testy 4.1 CellTest @Test public void getState() throws Exception { Cell cell = new Cell(); Integer i = cell.getState(); assertEquals(new Integer(-1),i); } Powyzszy test mozna przeprowadzic dla kazdej klasy z pakietu cell. Daje nam to pewnosc ze odpowiednie rodzaje komórek maja przypisane odpowiednie numery. Oczywiscie testy nalezałoby zmienic jezeli zmienialibysmy koncepcje programu, np. poprzez wprowadzenie nowego podziału komórek. 4.2 FieldTest @Test public void getXdim() throws Exception { for (int i=0;i<100;i++) { a = r.nextInt(200); b = r.nextInt(200); Field f = new Field(a,b); assertEquals(new Integer(f.getXdim()), a); } } @Test public void getYdim() throws Exception { for (int i=0;i<100;i++) { a = r.nextInt(200); b = r.nextInt(200); Field f = new Field(a,b); assertEquals(new Integer(f.getYdim()), b); } } Dla dowolnych (pseudolosowych) wymiarów planszy sprawdzamy poprawnosc metod zwracajacych jej wymiar. 4.3 StreamTest @Test public void readingBadExtension() { File folder = new File("C:\\Windows"); Stream stream = new Stream(); Field field; 6 for (final File f : folder.listFiles()) { if (!f.isDirectory()) { String ext = f.getName().substring(f.getName().lastIndexOf("."), f.getName().length()); if (!ext.equals(".map") && !ext.equals(".ww")) { field = stream.read(f); assertEquals(field, null); } } } } @Test(expected = IOException.class) public void readFromUserDefinition() throws IOException { File folder = new File("C:\\WireWorld\\testfiles"); Stream stream = new Stream(); Field field; for (final File f : folder.listFiles()) { if (!f.isDirectory()) { String ext = f.getName().substring(f.getName().lastIndexOf("."), f.getName().length()); if (ext.equals(".ww")) { try { System.out.println(f.getName()); stream.readFromUserDefinition(f); fail("Should thrown an exception if file is invalid"); } catch (IOException e) { assertEquals(e.getMessage(), "Bledny format pliku"); throw e; } } } } } Testy polegały na sprawdzeniu czy walidacja danych wprowadzanych przez pliki do programu jest wystarczajaca. Wszystkie testy przeszły pomyslnie. Niestety z jakichs powodów nie udało mi sie przeniesc wszystkich testów do jednego folderu. Kompilator nie widział testowanych klas z poziomu folderu nizej. Jest to sprawa organizacji plików, która z pewnoscia w przyszłosci powinna byc rozwiazana. 7 4.4 Komunikaty Program informuje uzytkownika jezeli dane które wprowadził sa niezgodne z przewidzianym formatem. Program analizuje zarówno pliki wczytywane przez uzytkownika jak i dane tekstowe wprowadzone przez niego. 5 Podsumowanie Program umozliwia budowanie w dosyc szybki sposób map WireWorld. Mozemy dowolnie definiowac struktury, zapisywac je, wczytywac na wieksze mapy. 8 Jest zgodny z załozeniami specyfikacyjnymi. Klasa odpowiedzialna za przetrzymywanie reguł zycia komórek jest łatwo modyfikowalna co daje duze mozliwosci rozwoju programu. Najbardziej nefralgiczne metody programu zostały przetestowane. Dla zbioru danych testowych spełniaja swoje zadania. 6 Zródła 1. https://bitbucket.org/owlcode/wireworld 2. https://github.com/owlcode/WireWorld 9