💾 How The Rock-Paper-Scissors Example Saves Your Data

Goal: Understand exactly how this Step 4 demo uses localStorage to collect and save data right in your browser.

← Back to Step 4

What is Browser Storage (localStorage)?

Imagine your web browser has a small, private filing cabinet for each website you visit. localStorage is the name for this filing cabinet. It lets our experiment save information directly on your computer. This is great because the data stays on your machine, it's private, and it persists even if you refresh the page or close the browser.

This is different from saving to a server, which involves sending your data over the internet to a remote computer. For this tutorial, we are keeping everything local and simple.

🛠️ How Our Code Saves Data: A Step-by-Step Breakdown

Step 1: Create an Empty "List" to Hold Data

First, our code creates an empty container to hold all the data we collect. In JavaScript, this is called an array, which is just a fancy word for a list. We give it a descriptive name, `experimentData`.

// Global state: Create an empty list to store all our trial data let experimentData = []; let trialCount = 0; // Also create a counter to keep track of trials

Step 2: Define What Data to Save on Each Click

Next, inside the `logChoice` function, we define exactly what information to capture every time you click a button (Rock, Paper, or Scissors). We create a small data "packet" (called an object in JavaScript) that includes the trial number, a timestamp, and your choice.

function logChoice(choice) { trialCount++; // Increment the trial counter // Create a "packet" of data for this specific trial const trialData = { trial: trialCount, timestamp: new Date().toISOString(), // Record the exact time playerChoice: choice, step: 4, // Note which step this data is from status: 'localStorage_collection' // Note the data collection method }; // Add this new data packet to our main list experimentData.push(trialData); // Immediately save the entire updated list to the browser's storage saveData(); // Update the status message on the screen updateStatus(choice); }

Step 3: Save the Data into the Browser's "Filing Cabinet"

The `saveData` function takes our `experimentData` list, converts it into a special text format called JSON, and saves it to `localStorage` with a unique key, `rpsExperimentData`.

function saveData() { // The browser can only store text, so we convert our data list to a string // JSON.stringify is the standard way to do this localStorage.setItem('rpsExperimentData', JSON.stringify(experimentData)); }

Step 4: Load Existing Data When the Page Opens

When you first open or refresh the page, the `loadData` function checks the browser's "filing cabinet" to see if any data already exists from a previous session. If it does, it loads it back into our `experimentData` list.

function loadData() { // Look for our data in the browser's storage const savedData = localStorage.getItem('rpsExperimentData'); // If we found something... if (savedData) { // ...convert it from a text string back into a usable JavaScript list experimentData = JSON.parse(savedData); // And update our trial counter to match trialCount = experimentData.length; } }

Step 5: Putting It All Together at Page Load

To make all this happen automatically, we use a special event listener that runs code as soon as the page has finished loading. This single block of code kicks everything off in the right order.

// When the HTML document is fully loaded and ready... document.addEventListener('DOMContentLoaded', () => { // 1. Check for and load any data from previous sessions loadData(); // 2. Update the status message based on what was (or wasn't) loaded updateStatus(); // 3. Log helpful messages to the developer console console.log('🚀 Step 4: Data collection experiment loaded'); if (experimentData.length > 0) { console.log(`📁 Found ${experimentData.length} existing trials`); } else { console.log('📝 No existing data - ready for new session'); } });

Step 6: Create Download Buttons to Export Your Data

Once you've collected data, you need a way to get it out of the browser. The process involves converting your data list into text and creating a temporary download link.

// Function to download data as a JSON file (great for code) function downloadJSON() { // First, convert your data list into a nicely formatted text string const dataStr = JSON.stringify(experimentData, null, 2); // Create a 'Blob', which is a file-like object for the browser const dataBlob = new Blob([dataStr], {type: "application/json"}); // Create a temporary, invisible URL that points to our data blob const url = URL.createObjectURL(dataBlob); // Create an invisible link element const link = document.createElement('a'); link.href = url; link.download = "rps-data.json"; // Set the desired filename // Programmatically click the link to trigger the browser's download dialog link.click(); } // Function to download data as a CSV file (great for spreadsheets) function downloadCSV() { // Define the column headers for your file const headers = "trial,timestamp,playerChoice,step,status"; // Convert each data object in your list into a single line of text const rows = experimentData.map(d => `${d.trial},${d.timestamp},${d.playerChoice},${d.step},${d.status}`); // Join the headers and all the rows into one big string const csvContent = [headers, ...rows].join("\n"); const dataBlob = new Blob([csvContent], {type: "text/csv"}); const url = URL.createObjectURL(dataBlob); const link = document.createElement('a'); link.href = url; link.download = "rps-data.csv"; link.click(); }

Want to see the full code?

You can see all of these functions working together in the step4-experiment.js file in your code editor. Reading the actual file is a great way to understand how all the pieces connect.

Next Level: Managing Experiment Settings

In this step, we used localStorage to collect data. In Step 5, we'll take this a step further and use the same browser storage to manage complex experiment configurations. You'll see how to save and load different settings for your AI opponents, which is a powerful way to design more advanced studies.

See Advanced Configuration in Step 5 →