Project 2: Climate Simulator

Design Checks: October 9th – October 16th
Design Check due: October 18th 9:00 PM ET
Implementation: October 22th 9:00 PM ET

Note: This project is to be completed with a partner. You are encouraged to work with different partners for each project. You will be assigned a partner by October 11th. Both partners must be present at the Design Check meeting.

This project aims to build a simplified climate simulator for Earth to predict potential climate changes based on various factors. While our simulation is somewhat simplified compared to real models, it’s designed to balance realism with the programming skills you’ve learned so far in the course. We recommend you read through the entire project description before starting to get a sense of the scope and requirements!

Background

Environmental scientists have determined a near-linear relationship between tonnes of carbon dioxide (CO2) and global surface temperature increases. In other words, the more CO2 we produce, the hotter our globe will be. Based on the most recent work from the Intergovernmental Panel on Climate Change (IPCC), if global temperatures increase 3.0°C from pre-industrial levels, global catastrophes like droughts, peak biodiversity losses, and extreme temperature changes will continue to unravel and exacerbate all across the world. To read more about the adverse impacts of rising global temperature levels, see the report.

By building a graphical simulator, we can see how much various countries contribute to global warming over time. We will also be implementing various policies that will impact how much CO2 a country emits.

The simulator will primarly be based on these two figures from the IPCC:

Global Temperature and Carbon Emissions

This first image represents the linear relationship between carbon emitted over time and global surface temperature increases.

Impact of 1.5 and 2.0 degree temperature increases

This second image demonstrates that the climbing global temperatures will carry disproportionate impacts on local regions across the globe.

Setup

The project includes several components: the simulator (which you will write), the country policies (which you will write), and the display (which is provided to you).

Project Roadmap

As you work through this project, you will need to complete the following tasks:

  1. Read through this document in its entirety.
  2. Setup: Download the project’s stencil code from the link above.
  3. Design Check: Complete the Design Check questions due by October 18th at 10:00 PM ET.
  4. Implement the country policies.
  5. Implement the simulator.
  6. Write tests for your simulator and policies.

Note: Refer to the course design recipe and apply it to your functions.

Project Component Details

Part 1: The Display

The display is implemented for you in display.py. It has one button: the step button, which calls advance_year once. The rest of the interface displays the countries and temperatures reported by the simulator, as well as the current year.

You can run the display by running python3 main.py in your VSCode terminal. If that doesn’t work, try using python main.py instead. This initializes the display, the simulator, and two policies that have been hardcoded (you will need to change this as part of the assignment!).

As you’re working with all these different modules, keep in mind the way they depend on each other:

Part 2: The Simulator

The simulator is implemented as a class Simulator in the simulator.py file. The simulator tracks the amount of cumulative carbon emissions (in gigatonnes, or, GtCO2) in the atmosphere and the average temperature of each country. The Display calls the Simulator’s advance_year function to simulate the passing of one year in time. The Display also calls the Simulator’s report function to generate a report of the countries on Earth and their current temperatures.

The Simulator class has some attributes that you will need to use in your implementation:

The simulator has three methods:

Task 1: Navigate to the simulator.py file and understand the Simulator class and its methods. No need to make any changes yet, just familiarize yourself with the code.

Part 3: The Policies

The policies we want you to create are defined as stencil classes in policies.py. An informal description of each policy is:

Task 2: Navigate to the policies.py file and understand the policy classes. No need to make any changes yet, just familiarize yourself with the code.

Section 5: Design Check

For the design check, you should submit a README.txt file with blocked out comments answering the following questions:

  1. Suppose United States has adopted the TaxEmissions policy (where emissions are reduced by 5% each year by what they were the previous year). The baseline (year0) CO2 emissions for the U.S. is 6.5Gt and the cumulative CO2 emissions for year0 is 2300Gt. The baseline (year0) temperature for the U.S. is 10.0 degrees Celsius. Round your answers to three decimal places.
    • A) Provide the year1 and year2 U.S. C02 emissions.
    • B) Provide the year1 and year2 cumulative CO2 emissions, provided that other countries in the world have emitted 54Gt in year1 and 62Gt in year2. Take into account the amount of carbon absorbed by the atmosphere, which is 6Gt each year.
    • C) Provide the year1 and year2 global surface temperature increases from baseline.
    • D) Provide the year1 and year2 United States temperatures (see equations for advance_year). Note that y in the equation will give you the temperature increase from baseline.
  2. What states will the simulator need to track? Be specific about the data structures you will use to track each piece of state. For example, how would you keep track of the temperatures for all countries?
  3. What parameters should the emit methods take? Why does each policy’s emit method need to take in the same arguments?
  4. What arguments should the emit methods take (there may be multiple correct answers)? Write at least one emit method/function.
  5. Think about the implementation of the simulator’s advance_year method, and write some helper functions in pseudocode that can assist with the computations you are making.

Section 6: Implementation

Part 1: The Policies

Task 3: Implement the policies in the policies.py file.

Each policy should have an __init__ method that takes in the baseline parameter, which represents the initial emissions rate. Each policy should also have an emit method that returns the number of emitted gigatonnes of carbon. You will need to track past emissions as part of some policy objects’ state. Think about how you can use principles of polymorphism to make the emit function take in the same arguments, while making sure each policy instance has access to the information it needs to compute the country’s emissions.

To understand how to implement the policies, you should refer to the informal descriptions of each policy in the Background section. You should also refer to the Simulator class in the simulator.py file to understand how the policies will be used.

Task 4: Write tests for the policies in test_policies.py.

Part 2: The Simulator

Task 5: Fill in the constant attributes in the Simulator class in simulator.py.

You will need to fill in the following attributes in the Simulator class:

Task 6: Implement advance_year in simulator.py. Try to break down the problem into smaller parts and write helper functions to assist with the computations you are making.

In the advance_year method, you will need to:

Task 7: Write tests for the advance_year method in test_simulator.py.

Your tests should be unit tests that test the advance_year method in the Simulator class. You should test the following:

Can you think of any edge cases that you should test for?

Task 8: Implement report in simulator.py. Write tests for this method in test_simulator.py.

Section 7: Testing

Until now, and in CS0111, you have been doing one kind of testing: unit testing of functions. Unit tests are a type of software testing that checks individual components, or units, of a program in isolation. For example, calling a single, specific method, such as advance_year, and testing its results, such as checking that simulator.time has been updated, would be deemed a unit test.

Part 1: Integration Testing and UI Testing

But what about the user interface (UI), the interactive component of the code, in the form of the simulator’s display? UIs are front-facing; when using a website or app, you interact with its UI. Compared to testing a function, testing UIs can be time-consuming because rather than just passing in an input and then examining the output, the tester must perform some UI manipulation (like clicking a button or moving the mouse) and then check that the expected effect has happened in the UI. If this is all done manually, it can be an enormous investment of time since every time you want to “run your tests,” you need to spend time using the application yourself. Instead, to save time, you can use automated testing, rather like what you’ve already done for testing functions.

A close connection to UI testing is integration testing. Integration testing focuses on combining multiple units of a program to validate that they work in collaboration–that their interactions are performed correctly.

Consider a scenario where all your unit tests for the policies, advance_year, report, etc., pass, but nothing happens when you run main and click on the step button. This indicates an integration problem - the components work individually but not together. Is the step button not triggering an advance_year call, or is the implementation of the display not responding even if advance_year is called, or something else entirely? Automated UI testing could discover this predicament.

Part 2: Mocking

When all you’re testing is functions in combination, this is often straightforward because you can just call the functions in succession and look at the final output. But in the UI testing scenario, we need a way to automate the interaction. To do that, we’ll use a technique called “mocking.” Mocking is a controlled way to emulate either data or the behavior of objects.

Check the test_mocking.py file to understand the mocking implementation.

Task 9: Correct the mock_event function in test_display.py to correctly change the environment. What should be the trigger for the step button? Use this list of possible interactions: [KEYDOWN, KEYUP, MOUSEBUTTONUP, MOUSEBUTTONDOWN, MOUSEMOTION, QUIT]

Now, we have a way to interact with the display in a controlled way. What this funtion does is basically “press” the step button, which should trigger the advance_year method in the simulator.

Task 10: Write at least three tests to check that the mock_event correctly changes the environment. What should change when the step button is pressed? Write a comment above each test explaining how your tests check aspects of the UI and the program’s integration.

Part 3: Reflection on Testing Approaches

The simulator display was programmed using the Python library Pygame. In the mocked tests, we are simulating Pygame events or interactions. For instance, when you mock the Pygame event KEYDOWN, it only affects the Pygame window.

You don’t need Pygame to do this sort of scripted interaction, however. There are many testing libraries that let you take control of an application (later on in the semester, you’ll use software that effectively lets you automate actions in a web browser!) And you could even go further. For example, you could write a program that automatically controls your mouse and keyboard, allowing it to interact with any clickable buttons, applications, and more on your entire desktop—not just within Pygame!

In your README, address the following:

Remember, when building software that other people will use, it’s crucial to consider potential unintended consequences and how to mitigate risks.

Section 8: Readme

Imagine augmenting your simulator to be a higher-accuracy, more realistic simulation for the actual climate and atmosphere on Earth. Detail the full process you’d take to create a more accurate model and the advantages/disadvantages of your design choices. Feel free to draw inspiration from similar simulations that exist. Address the following points in your README:

Emphasize the differences between a realistic simulation for Earth and the basic one that you implemented for this project. What ethical considerations must you take into account given the real impact that a widely-used simulation might have?

Section 9: Submission

Please follow the design and clarity guide–part of your grade will be for code style and clarity. Additionally, you should be adhering to the course design recipe. After completing the homework, you will submit:

Only one of your partners should submit the project on Gradescope. Make sure to add your partner as a Group Member on your Gradescope submission so that you both can see the submission. Please DO NOT write your partner’s name in the README when listing other collaborators’ cslogins.

If you are using late days, make sure to make a note of that in your README. Remember, you may only use a maximum of 3 late days per assignment, and both you and your partner must have late days to use them. If the assignment is late (and you do NOT have anymore late days) no credit will be given.