Team Project: Cell Society
The chess-board is the world; the pieces are the phenomena of the universe; the rules of the game are what we call the laws of Nature. — T. H. Huxley
Submitting Your Work
Use GIT to push your team's implementation to the master
branch of the provided, shared, cellsociety_teamNN
repository hosted in the course's Gitlab group.
As your submission for this project, use GIT to add
, commit
, and push
the following
doc
folder: all design documentation and any supporting images
src/main/java
folder: all project code
src/main/resources
folder: any images or program resource files
data
folder: all example simulation files
- top-level (no separate folder): project README, and otherwise no other files created by you
Your code is expected to follow the course coding conventions and follow Javadoc conventions.
Your team's project GIT repository must show many, purposeful, commits from all team members rather than just one or two large "kitchen sink" commits and marathon merging or redesign sessions. Specifically, we will be looking for deliberate attempts to regularly:
- integrate each other's work
- refactor code to improve its design
- test your functionality
We strongly suggest using the course's suggested GIT workflow for teams to manage this process.
Specification
In teams, write a Java program from scratch using straight OpenJFX (without FXML), that allows users to simulate Cellular Automata (CA) models, such as those described in the following CompSci 101 level assignments:
Generally, your program should make it easy to animate a variety of CA simulations as a 2D grid (with a number of rows and columns) of cells (with an initial state such as on and off). A simulation's rules (such as whether a cell changes state, is created, or moves to another position in the grid) are applied on each cell "simultaneously" (i.e., based on their current state and that of their neighbors) and then cell states are updated in a second pass (so a cell is affected only by information from their immediate neighbors). The grid's edges represent closed bounds, i.e., cells on the grid's edges should have smaller, partial, neighborhoods than those in the middle, with full neighborhoods (i.e., 8 neighbors).
Simulation rules will be written in Java code but the kind of simulation, its starting configuration, as well as any initial parameter settings will be read from an eXtensible Markup Language, XML, formatted file (the exact tags of this configuration file should be decided by your team):
- simulation type it represents (e.g., Game of Life, Fire, etc.)
- title for this configuration (e.g., the kind of simulation, or the name of a specific structure (such as glider, blinker, or pulsar), or what this configuration is showing or testing)
- author of this configuration (e.g., team member, someone from the Internet from whom you borrowed the example, or the original discoverer (such as glider was discovered by Richard Guy in 1970))
- description of this simulation (e.g., brief sentence or two about what you expect to see or why you think it is an interesting example)
- width and height of the grid (two numbers representing the grid's number of rows and columns of cells)
- initial configuration of the states for the cells in the grid (whose values represent the different states a cell can be in (e.g.,
0 = DEAD
and 1 = ALIVE
))
- parameter values specific to the simulation (e.g.,
probCatch
, the probability of a tree in a cell catching fire, but Game of Life has no parameters)
While the exact User Interface for setting up and animating a simulation is up to your team to decide, it should allow the user to:
- see the simulation's descriptive information (or make it easily accessible, like in a dialog box created by pressing an "About" button), such as its type, name, author, description, state colors, and parameter values (if any)
- animate a simulation from its initial state indefinitely until they choose to stop it, displaying the current states of the cells in the grid with different colors
- pause and resume the simulation, as well as step forward through it
- speed up or slow down the simulation's animation rate
- load a new configuration file, which stops the current simulation and starts the new one
NOTE, the app's size should not change based on the size of the grid to be displayed (i.e., the display size of an individual cell should be calculated to fit within the app's fixed screen size)
- save the current state of the simulation as an XML configuration file that can be loaded in as a simulation starting configuration (i.e., in the same format as is read in)
NOTE, this requires prompting the user with fields for entering or changing
information such as the title, author, and description
Any text displayed to the user or styles (colors, font, borders, etc.) must be set using configuration files instead of using hard-coded values within your Java code (and these settings should be different from the simulation configuration files).
Deliverables
This project will be submitted in stages:
- Plan: plan your design for the project
- Basic: build the "core" features of the project
- Change: extend the project by adding new features
It is strongly encouraged that you to start simply in order to verify your understanding of the project's core features. Then refactor your code to help it serve as a foundation for the more diverse functionality expected.
Design Specifications
The functionality features emphasize design goals, so your focus should be implementing them in such a way as to promote creating abstractions that generalize your core code, not simply as special cases added without a clear plan. Ideally, a well-designed program will make implementing new features easier so, when choosing a new feature to implement, look for something that fits into your design or refactor your code first to accommodate it. Specifically, your design should be thoughtful and intentional: clearly avoiding duplicate code structures and making it easy to add more simulations without changing the existing code.
Adding functionality not related to an abstraction or resulting in poor code that diminishes your overall design efforts will not be rewarded. Specifically, the credit you receive for a functionality feature will be in proportion to how clearly it shows that your core classes are closed to modification while open to extension using abstractions to remove dependencies on concrete classes. Thus, a program with fewer features, but plenty of clear paths to easy expansion, is worth more than a program with many features but lacking clean code and good abstractions.
In addition to following the course Code Design Habits Checklist, your project design should clearly show the your progress learning the topics we have discussed so far in the course:
- Model-View Separation.
Create a GUI that is separate from the model; this requires clear articulation about what information (including errors) needs to be communicated between each part
- Open/Closed Principle. Structure the main parts of your project around abstractions (built using inheritance and polymorphism) rather than directly on concrete classes
- Abstractions. Create inheritance hierarchies to define common methods that can be implemented in multiple ways in separate concrete classes
- Encapsulation. Key implementation details must be hidden such that they can be changed without impacting any other classes:
- the grid data structure (such as between a
List
of List
s, a 2D array, or a Map
)
- the configuration file format (such as using different key names, one file instead of two, or a JSON format instead of XML)
- the panel component used to display the grid (such as a
Canvas
, a GridPane
, or a Group
)
- Clean code. Write your code primarily for communication: to avoid duplication, to support your team mates, and so that it can be easily understood by others
- Avoid hardcoded values. Move all "magic" values into files, rather than compiled into your program, using resources, properties, and styles
- Exceptions. Communicate errors in a thoughtful, intentional, manner rather than returning
null
or other error prone values, possibly using Java's Optional
- Immutability. Be intentional about what data you expect to be modified by explicitly restricting what other classes can change, perhaps by using Enumerated types or Records
CompSci Context
This project highlights the following interesting and foundational Computer Science concepts. You are not expected to write a general or complete version of any of these concepts, but learning about them may help provide a context to begin thinking about some design issues or connect your work in this course to the broader computing community.
- Real-world connection: Programming has become essential to scientific research, allowing scientists to analyze data, perform simulations, and create visualizations that would be otherwise infeasible or impractical to do by hand. Scientists use programming to simulate complex systems such as the behavior of molecules, the spread of diseases, or the dynamics of the climate in order to test hypotheses, make predictions, and gain a deeper understanding of the underlying processes.
- Cellular Automata are simulations based on a model that consists of a regular grid of cells, each in one of a finite number of states that are each updated based on a set of fixed rules described in terms of the cell's current state and the states of its immediate neighbors. Though this model is simply described, it can be used to simulate a wide variety of complex phenomena, such as ant foraging to modeling fur patterns to natural patterns to economic theory to city growth to image processing to generative music to terrain generation in video games! In fact, after 20 years of study, Stephen Wolfram declared CA were a universal mechanism for moving scientific study forward in his 1280 page book A New Kind of Science that contains hundreds of example models and others argue it could explain the universe scientifically and philosophically.
- Computational Modeling is the process of defining an algorithmic model of a physical system that is difficult or impossible to observe or control, much less experiment with. Such models can help better understand a complex system by allowing people to perform many experiments and explore the effect of even subtle changes. This helps especially for systems that involve events that are not precisely predictable even though the relative frequencies of event results may be known, e.g., a flipped coin's particular result cannot be known certainly.
However, a model's accuracy can lead to ethical questions).
- The Model, View, and Controller (MVC) architecture has proven so successful that it is the de facto standard for designing desktop, web, and mobile applications — with many popular frameworks actually requiring it. This is done to separate internal representations of information from the ways information is presented to and accepted from the user, decoupling these components and allowing for effective code reuse and more opportunities to develop and test separately and in parallel (often by people with very different skill sets). As programs become more complex, a Controller (middleware) is introduced between the Model (backend) and the View (frontend) to act as a mediator to process their interactions and provide specific application logic (we will not worry about the Controller until the next project).
- Configuration, or config, files are a standard way to customize how you interact with an application or how an application interacts with the rest of your system. There are thousands of config files on your computer, hidden by starting with a period or in system folders like
/etc
. It is also thanks to config files that any time you launch an application, it has "memories" of how you like to use it (or how GIT remembers your name and which repository to send your code to). There are many standard formats but Java prefers .properties and XML files. XML is an open, industry standard, flexible format, supported by most companies (including rivals Google, Facebook, Microsoft, and Apple) as well as many web protocols and Linux programs. It is supported in all modern programming languages and, while it may be viewed as "overly-verbose", it is generally easy to read and generate algorithmically.
Individual Responsibilities when Working as a Team
This project requires steady, consistent, work — only by putting in consistent time each week will you see measurable progress and not have to pull "heroic" all-nighters.
Although this is a team project, everyone has individual responsibilities to the team that can be summed up as follows:
- actively participating in all team meetings
- regularly contributing clean code to the shared repository in reasonably sized chunks
- solving and coding at least one significant design problem
- helping teammates at least once by going above and beyond
Unfortunately conflicts are likely to occur, so please let the Teaching Team know as soon as possible — even if it has happened just once or twice since it is better to deal with the situation early rather than having a disaster at the end when little can be done to get back on track.
Resources
Experiment online with the Game of Life simulator or NetLogo Fire Simulation.