# Introduction

Easy Multiplayer Interactive Experiments in the Browser

{% hint style="success" %}
This documentation is for Empirica v1. If you want to see the documentation for Empirica v2 head over to [https://docs.empirica.ly](https://docs.empirica.ly/).
{% endhint %}

Empirica is an open-source JavaScript framework for running multiplayer interactive experiments and games in the browser. It was created to make it easy to develop and iterate on sophisticated designs in a statistically sound manner, and offers a unique combination of power, flexibility, and speed. Empirica is a powerful framework that facilitates the management of your games and experiments, and is useful even for singleplayer research.&#x20;

Empirica is built on a combination of [Meteor](https://www.meteor.com/) for the backend (managing your games and data) and [React.js](https://reactjs.org/) for the frontend (what the players see and interact with). Empirica provides a helpful structure to how your Games, Players, Rounds, and Stages interact. Furthermore, Empirica provides you with an Admin Panel that makes organising and running your Games for data collection extremely easy and intuitive.

Empirica is the one method that provides enough flexibility to build any type of experiment whilst still being accessible and helpful to the researcher.&#x20;

### I want to use Empirica, where do I start?

Visit the [Getting Started](/getting-started/setup) part of this documentation to get you started.&#x20;

Follow our [first experiment tutorial](/guides/tutorial-your-first-experiment/your-first-experiment).

To learn more about the parts of an Empirica app (e.g., what are Games, Rounds, and Players?) visit the [Concepts ](/overview/concepts)page.

### What skills do I need to use Empirica?

Empirica helps you build online apps for online research. As with many online tools, basic notions of HTML, CSS, and JavaScript will be helpful. As Empirica is built with Meteor and React.js, knowing a bit about those can also be helpful, although you do not need to be an expert. There are many tutorials online that teach the basics of all the technologies mentioned here.

### Why should I use Empirica instead of just Meteor and React.js together?

Whilst Meteor and React.js are powerful tools, and you could build sophisticated experiments with them, but Empirica makes the process of building and managing your experiments much easier.&#x20;

Notably, Empirica provides an Admin Panel that allows you to manage the conditions of your experiments (Treatments and Factors) and which Games are running, collecting data, or waiting for players.

Empirica does the heavy lifting in terms of managing games, player connections, game life cycles, and more...

### YouTube tutorial

{% embed url="<https://www.youtube.com/playlist?list=PLPQelvUwyVgiawBDk3Sp74QMfL8RPgORW>" %}


# Setup

1. Install Node.js via <https://nodejs.org/en/> (download and install the LTS bundle on the left)
2. Install Meteor with instructions at <https://www.meteor.com/install>

That's it, you're done! Proceed to creating your experiment:

{% content-ref url="/pages/-M-DU6peo0\_R4jW1X\_mJ" %}
[Creating your experiment](/getting-started/quick-start)
{% endcontent-ref %}

### **A note about Windows 10 Setup**

Empirica is build on industry-standard open-source web technologies which run best in Unix-like operating systems such as Linux and MacOS. \*\*\*\*

Running Meteor apps on Windows can be unreliable, as apps struggle to install and launch. Whilst stopping and trying again multiple times (as well as making sure there are no processes that slow down the installation of the Meteor files) might work, it is not recommended.

In order to run Empirica reliably in Windows, you will need to enable developer settings within advanced Windows settings and download/install the new version of Windows Subsystem for Linux (WLS2).

*If you are a Windows user and get stuck at any point in the development process, please contact <joshua.becker@ucl.ac.uk> or join the Slack channel for community-based technical support on a wide range of topics.*

{% content-ref url="/pages/-MQFm\_OhGD0ymKg\_sz4z" %}
[Windows WSL Instructions](/getting-started/setup/windows-instructions)
{% endcontent-ref %}

### **A note about macOS Monterey (Apple M1 Chip) Setup**

When using apple's new M1 chip, the minimum Meteor version that you can install is version 2.5.1. This causes an issue with Empirica which uses a specific version of Meteor (1.10.2) as shown below.

```
This project uses Meteor 1.10.2, which isn't available on this platform. To work with this app on all supported platforms, use meteor update --release METEOR@2.7.3 to pin this app to the newest compatible release.
```

**Do not run the recommended command to update meteor as that would also cause issues.**

To resolve this issue, you need to switch from macOS Monterey to macOS Rosetta by running the following command:

```
arch -x86_64 zsh
```

Once entered, run the following command to change the meteor version to 1.10.2.

```
meteor update --release 1.10.2
```


# Windows WSL Instructions

## Step 1.  Install WSL 2 and Ubuntu 20.04

1. Follow either the written instructions or video tutorial below to install WSL2. &#x20;
2. During this process, select "Ubuntu 20.04" as your Linux version.
3. See our overview below for a summary with screenshots.

**Written Instructions:**\
<https://docs.microsoft.com/en-us/windows/wsl/install-win10>

**Video Tutorial:**\
<https://www.youtube.com/watch?v=D7Em1wjMiak> (commands in the description)

#### Our Summary of these Instructions:

1. Enable the Windows Subsystem for Linux
2. Ensure you meet the requirements for WSL2
3. Enable the Virtual Machine feature in Windows (see screenshot below)
4. Download the WSL2 update package
5. Set WSL2 as your default Linux system
6. Open Microsoft store, search for Ubuntu 20.04, and install it&#x20;
7. Launch the terminal and follow the prompt to create a new username/password (see screenshot below).

#### Screenshot: Enabling Virtual Machine feature in Windows:&#x20;

![](https://1898430204-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M-Cqf0McgfJZYwXisux%2F-MJ7PeQxzYXgij99DAjc%2F-MJ7XEtznp94AWHI2D4o%2F1.png?alt=media\&token=deff7404-e6a1-40b5-9ca2-5d0b87cd9fe5)

#### Screenshot: Running Ubuntu 20.04 in Windows for the first time:&#x20;

![](https://1898430204-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M-Cqf0McgfJZYwXisux%2F-MJ7PeQxzYXgij99DAjc%2F-MJ7XK7FFSB-TRlxfqrg%2F3.png?alt=media\&token=be743771-b06a-4d18-9a66-fd5c55fca2a9)

## Step 2.  Install NVM

*Note: Copy these commands and then paste into WSL2 by right-clicking on the terminal.*

Enter the following commands into your Ubuntu terminal:

```
curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash  # Download and install
source ~/.profile  # Reload system environment
nvm install lts/erbium
```

## Step 3.  Editing Files in WSL2

In order to access your WSL2 file directory, run the following command in WSL2:

```
explorer.exe .
```

This will allow you to browse WSL2 as if it were another computer on a local network.

{% hint style="info" %}
If you are using the WSL, you files for your experiment must be in the WSL, you can't use the WSL to run an experiment stored on the rest of your computer.
{% endhint %}

### Using code editors

Different [code editors](/tips-and-tricks/code-editors) (such as VSCode) will have commands that you can run to open them in the current directory (e.g., `code .`). This helps make for a better coding experience in the WSL.


# Creating your experiment

Once you have finished setting up Node and Meteor, [as per our setup guide](/getting-started/setup), you can use `create-empirica-app` to create your experiment.

Then you can simply run the following command, where `my-experiment` is your customized experiment name (no spaces or uppercase letters):

```bash
npx create-empirica-app my-experiment
```

It will create a directory called `my-experiment` inside the current folder.\
Inside that directory, it will generate the initial [structure ](/overview/structure)and install the transitive dependencies.

Once the installation is done, open your project folder:

```bash
cd my-experiment
```

You can now read more about the running your experiment, the structure of an Empirica experiment, and you can try our tutorial:

{% content-ref url="/pages/-MTtiX7H8rZS8QB\_1vq\_" %}
[Running your experiment](/getting-started/quick-test)
{% endcontent-ref %}

{% content-ref url="/pages/-M\_5avIBNy9-Me5fqN8n" %}
[Structure](/overview/structure)
{% endcontent-ref %}

{% content-ref url="/pages/-MabnF5l3kFtd8vlnFQS" %}
[Tutorial: Your First Experiment](/guides/tutorial-your-first-experiment)
{% endcontent-ref %}


# Running your experiment

Once you have created an experiment using either create-empirica-app or a git clone.

## Installing the node modules

Whenever you *first* pull or clone an app from a repository, you need to run this command to install all the Node packages:

```
meteor npm install
```

## Running the app locally

Run the app on your local machine with one command:

```
meteor
```

This can take a few minutes.

This will start the app that you can access as a participant: <https:/localhost:3000/>

You can access the `admin panel` here: <https:/localhost:3000/admin>

Log in with the *username* and *password* provided in the command line.

## Loading the factors and treatments

Treatments and factors can also be entered manually via the admin panel.

Empirica also enables "experiment as code" by which experimental treatments and factors can stored in a `.yaml` file (e.g., `factors.yaml`).&#x20;

To load factors and treatments from a `.yaml` file , go in the **admin panel** and:

* click on the **Configuration** button
* click on **import**
* select the `.yaml` file you want to import the factors and treatments from
* wait a few seconds for the factors and treatments to be imported

## Testing the app

To run a game, create a new `batch` with the games of treatments you want to use and click start on the batch.

Open a player tab by going to <https:/localhost:3000/> or clicking on **open app**.

The player that you open with <https:/localhost:3000/> is cached on your browser. Whenever you start a game with this player, your local app will keep that information. To play again there are multiple things you can do:

* Click on the **Reset current session** button in the top right to reset this player, and create a new game for this player to join.
* Click on the **New Player** button in the top right to open a new tab with a different player (you will see tab with an id).
* Go to the **Players** tab in the admin panel and retire players that have finished or cancelled.

**The app will automatically ("hot") reload when save changes to the code.**


# Updating your experiment

## Check your Empirica Core version

If you are unsure as to which version of Empirica you have, you can run this line in your app to show you all the meteor packages in the app, including Empirica Core:

```bash
meteor list
```

## Updating the Empirica Core

As new versions of Empirica become available, you might want to update the version you are using in your app. To do so, simply run:

```bash
meteor update empirica:core
```

*Note: you might not want to update your empirica:core in the middle of a project unless it solves an important problem.*


# Tutorial: Your First Experiment

This is the tutorial to get started with Empirica. You will discover Empirica's potential and run a simple experiment.&#x20;

If you want to compare your work to a finished version of the tutorial, you can find it [on GitHub](https://github.com/empiricaly/your-first-experiment/).

Each part builds on the previous one:

{% content-ref url="/pages/-M-DUC1e\_KCv-S73IpC9" %}
[Part 1: Getting Started](/guides/tutorial-your-first-experiment/your-first-experiment)
{% endcontent-ref %}

{% content-ref url="/pages/-McV0\_4v1OCn3pGOGPEj" %}
[Part 2: Configuring the Experiment](/guides/tutorial-your-first-experiment/part-2-configuring-the-experiment)
{% endcontent-ref %}

{% content-ref url="/pages/-McV5gD6\_HFX9tqbTfVB" %}
[Part 3: Adding Social Information and New Factors](/guides/tutorial-your-first-experiment/part-3-adding-social-information-and-new-factors)
{% endcontent-ref %}

{% content-ref url="/pages/-Mabo5c2EhjcjqtPCmiw" %}
[Part 4: Adding Chats](/guides/tutorial-your-first-experiment/part-2-adding-chats)
{% endcontent-ref %}

{% content-ref url="/pages/-MaboDG8h\_yYuRCYLU9Z" %}
[Part 5: Adding Bots](/guides/tutorial-your-first-experiment/part-3-adding-bots)
{% endcontent-ref %}


# Part 1: Getting Started

## Getting Started With Empirica

Although it won't do too much, Empirica works straight out of the box. The first step to customizing your Empirica app is to launch a test game so you can see your edits in action.

1. Follow the [setup](/getting-started/setup) guide and [create your experiment](/getting-started/quick-start)
2. Start your app by running the command `meteor`
3. Then, visit your admin panel <http://localhost:3000/admin>
4. Log in using the password generated in the command line by step 2

### Configuring your app

1. Click `configuration` in the upper right corner to access app settings. This is where you'll define all your experimental conditions.
2. Click `factors` in the menu bar at the top. This is where you set the most

   basic parameters for your experiment. The only default parameter is

   playerCount. Add a new factor by clicking the `+` button. Set the name to

   `one` and the value to `1`, then click `Create Factor Value`.
3. Click `treatments`. This is where you combine factors to create an

   experimental condition. Create a new treatment using the factor you just

   created and name whatever you want.
4. Click `Lobby Configurations` and create a new lobby configuration using the default settings.

### Creating an experiment session

1. Click `monitoring` in the upper right corner to toggle your admin panel from configuration to monitoring. This is where you'll interact with all the

   Empirica features that have to do with actually running experiments.
2. Click `New Batch` in the batches panel, select the treatment you just

   created, and click `Create Batch`.
3. Press the `► Start`  to start the batch.

### Testing the experiment as a participant

1. Navigate to <http://localhost:3000/> (or click the `► Open App` button on the top right) .
2. Follow through the consent, identification (this would be, e.g., an MTurk/Prolific ID, but you can enter whatever you want right now), instruction pages, and attention check (you have to answer correctly).
3. You're running an experiment! This is the default app, just a slider with 10

   rounds of input. We're going to edit that.

{% hint style="info" %}
For more information about testing the experiment locally, see our [guide on running your experiment](/getting-started/quick-test).
{% endhint %}

## Creating the experiment title

The `client/main.html` is the html point of entry for the React code that determines what a participant sees when they are in your experiment. **You should NOT change anything in this file** **except** for the text in between the `<title></title>` tags. There you can put the title you want to appear at the top of the tab when people are using your experiment (e.g., "My First Experiment").

## Cleaning up the styling

The styling of an Empirica experiment is set in `.client/main.less`. **Less** is very similar to CSS.&#x20;

The default styling of the experiment is a bit complicated to understand, and to make our experiment look good we want to tweak a few things. Let's start by replacing the code in `main.less` with this code:

```css
/* ----------------
- default styling -
---------------- */

.title {
  text-align: center;
}

input[type="text"],
input[type="number"] {
  padding: 0.3rem 0.5rem;
  border-radius: 0.3rem;
  border: 1px solid lightgray;
}

input[type="radio"] {
  margin-right: 0.5rem;
}

.content {
  display: flex;
  flex-wrap: wrap;
}

.content > * {
  padding: 0.5rem;
  box-sizing: border-box;
}

.player-profile {
  display: flex;
  flex-direction: column;
  width: 20%;
  align-items: center;

  .profile-avatar {
    width: 8rem;
    height: 8rem;
    margin: 3rem 0;
  }

  .profile-score {
    text-align: center;
    span {
      font-size: 3rem;
      font-weight: bold;
    }
  }

  .timer {
    margin-top: 2rem;
    text-align: center;

    .seconds {
      font-size: 3rem;
      // Helvetica has tabular numbers (fixed width), which looks better
      // for a timer, doesn't jump all over the place.
      font-family: Helvetica, Arial, sans-serif;
      color: green;
    }
    &.lessThan10 {
      .seconds {
        color: orange;
      }
    }
    &.lessThan5 {
      .seconds {
        color: red;
      }
    }
  }
}

.task {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 50%;

  .task-image {
    text-align: center;
    margin-bottom: 1rem;
  }

  .task-question {
    width: 100%;
    text-align: center;
  }

  .task-response {
    width: 100%;

    form {
      display: flex;
      justify-content: center;
      margin-top: 1.5rem;
    }

    .response-submitted {
      margin-top: 1.5rem;
      background-color: #e8e8e8;
      padding: 2rem;
      border-radius: 0.4rem;

      h5 {
        margin: 0 0 0.5rem;
        font-size: inherit;
      }
    }
  }
}

.social-exposure {
  width: 30%;

  .alter {
    display: flex;
    justify-content: center;
    align-items: center;
    margin-bottom: 1rem;

    img {
      width: 6rem;
      height: 6rem;
      margin-right: 3rem;
    }

    .range {
      display: flex;
      align-items: center;
      justify-content: center;
    }
  }
}

button {
  padding: 0.8rem 1.2rem;
  border-radius: 0.3rem;
  border: 1px solid lightgray;
  background-color: #eee;
  cursor: pointer;

  &:hover {
    background-color: #ddd;
  }
}

.instructions,
.quiz,
.exit-survey {
  button {
    margin: 2rem 1rem 0 0;
  }

  label {
    display: block;
    margin: 2rem 0 1rem;
  }

  textarea {
    padding: 0.3rem 0.5rem;
    border-radius: 0.3rem;
    border: 1px solid lightgray;
  }
}

.exit-survey {
  .form-line {
    display: flex;

    & > div {
      margin-right: 30px;

      textarea {
        min-height: 90px;
        width: 100%;
      }
    }

    &.thirds {
      & > div {
        flex-grow: 0;
        flex-shrink: 0;
        flex-basis: 30%;

        label {
          min-height: 36px;
        }
      }
    }
  }
}

.finished {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
```

## Understanding an Empirica Experiment

As you go about your first experiment, it might help to try and get a global understanding of what an Empirica Experiment is.

### The Empirica Framework

The Empirica framework provides powerful tools to create singleplayer and multiplayer games.&#x20;

You have the frontend in the `/client` folder. This is where you determine what the users will see when they come to your experiment: which components you build your game with and what they look like.&#x20;

The backend in the `/server` folder. This is where you determine the structure of your game.

You have an `admin panel` in the browser that allows you to create factors and treatments as well as monitor the games you are running. For now, everything is running locally for your to test out, but the admin panel will look similar once deployed to recruit participants online.

{% hint style="info" %}
The best ways to learn about the structure of an Empirica experiment and testing it locally is to give the **Readme.md** file a read or consult our other sections in this documentation.
{% endhint %}

### The Technologies used by Empirica

Empirica is a framework that builds on top of a Meteor.js and React.js app. Meteor does the backend and generally building of the app whilst React is used for the front end.&#x20;

You can find some tutorial online for both technologies. However, you do not need any knowledge of these technologies for this tutorial.

{% hint style="info" %}
Our [brief explanation on what React components are](/faq/the-processes-and-elements-of-an-empirica-experiment#what-is-a-react-js-component) might help.
{% endhint %}


# Part 2: Configuring the Experiment

## Configuring the task page

The main file that determines what is displayed to the participant (i.e., the user-side) during a game is located at `/client/game/Round.jsx`.

By default, this is divided into two main components, `Task` and `SocialExposure`. The `Task` itself is composed of `TaskStimulus` which contains the stimulus (e.g., a survey question — or in this example, an estimation task) and `TaskResponse` which contains the input for users to response to the stimulus.

Let's start by adding a title to the `/client/game/Task.jx`  so that the component looks like this:

```jsx
import React from "react";

import TaskResponse from "./TaskResponse";
import TaskStimulus from "./TaskStimulus";

export default class Task extends React.Component {
  render() {
    return (
      <div className="task">
        <h3 className="title">Task</h3>
        <TaskStimulus {...this.props} />
        <TaskResponse {...this.props} />
      </div>
    );
  }
}

```

### Adding content to the task stimulus

{% hint style="info" %}
React components have a `this.props`  object which contains elements passed into it. These props can be extracted with destructuring (the `const {} = this.props` part). Notice that the props here include `round`, `stage`, and `player`. These are your interface with Empirica, and allow you to both read and set data for the state of the experiment.
{% endhint %}

All we're doing here is adding an image and question to the `client/game/TaskStimulus.jsx` so that it looks like this:

```jsx
import React from "react";

export default class TaskStimulus extends React.Component {
  render() {
    const { round, stage, player } = this.props;

    const imagePath = "/experiment/images/candies.jpg";
    const questionText = "How many candies are in the jar?";
    return (
      <div className="task-stimulus">
        <div className="task-image">
          <img src={imagePath} height={"300px"} />
        </div>
        <div className="task-question">
          <b>Please answer the following question:</b>
          <br />
          {questionText}
        </div>
      </div>
    );
  }
}
```

### Adding the candy jar image

You can download the candy jar image we use [here](https://raw.githubusercontent.com/empiricaly/your-first-experiment/master/public/experiment/images/candies.jpg).

Then, in the `public` directory, create the following directories: `/experiment/images/` and add the candy jar image there so that it matches the path we just set: `"/experiment/images/candies.jpg"` .

{% hint style="info" %}
The `public` directory allows you to store static assets, such as images, that can then be accessed on the client side.
{% endhint %}

### Customizing the input field

In this section, we are going to change the input type from a slider to a numeric input box.  To do so, go to the `client/game/TaskResponse.jsx` file.&#x20;

You can see that there are some "handle" functions (they don't need to be named this way, but clear names are helpful) that will execute on certain events.&#x20;

There are also different "render" functions that will be called further down in the main `render` based on different conditions (e.g., if the player has already submitted for this stage).

Change the `renderSlider` function. First let's change it's name to `renderInput` . Then, replace the slider with a numeric input box. Because we're asking people to estimate the number of candies in a jar, we'll set the minimum value to one.&#x20;

```jsx
renderInput() {
  const { player } = this.props;
  const value = player.round.get("value");
  return (
    <input
      type={"number"}
      min={1}
      onChange={this.handleChange}
      value={value}
      required
    />
  );
}
```

{% hint style="info" %}
We recommend adding additional form verification methods beyond the default to ensure a smooth user experience. Note that if you do choose to use a slider input, we strongly recommend using the Empirica slider, which is made with experimenters in mind — no default values that might create anchoring effects.
{% endhint %}

Notice that this method uses the `player` data to control the form input. This player data is created with `player.round.set()` in the `handleChange` method which is called every time the input is updated. This method will save this data to the database on the server, automagically.

The sliders and inputs don't send exactly the same data format, so we have to change the `handleChange` function to look like this:

```jsx
handleChange = event => {
  const value = Number(event.currentTarget.value);
  const { player } = this.props;
  player.round.set("value", value);
};
```

Because we changed the name of the "render" function to `renderInput` we need to change this in the main `render` ; instead of calling `this.renderSlider()` it should be called `this.renderInput()`.

```jsx
  render() {
    const { player } = this.props;

    // If the player already submitted, don't show the slider or submit button
    if (player.stage.submitted) {
      return this.renderSubmitted();
    }

    return (
      <div className="task-response">
        <form className="task-response-form" onSubmit={this.handleSubmit}>
          {this.renderInput()}

          <button type="submit">Submit</button>
        </form>
      </div>
    );
  }
```

{% hint style="info" %}
**Careful with the brackets!**

You might notice that a react component, like `TaskResponse.jsx` has a few import lines at the top of the file and then starts with this type of line and opening of curly brackets {}

```jsx
export default class TaskResponse extends React.Component { 
```

This curly bracket will close on the last line of the file.

You will also notice that the main render of a component also opens curly brackets {} which close before those of the overall component.

So when you are changing the render of a component, **careful not to delete the final bracket that closes the component**, otherwise you will get an error such as `'}' expected`.
{% endhint %}

Overall, `TaskResponse.jsx` should look like this:

```jsx
import React from "react";

export default class TaskResponse extends React.Component {
  handleChange = event => {
    const value = Number(event.currentTarget.value);
    const { player } = this.props;
    player.round.set("value", value);
  };

  handleSubmit = event => {
    event.preventDefault();
    this.props.player.stage.submit();
  };

  renderSubmitted() {
    return (
      <div className="task-response">
        <div className="response-submitted">
          <h5>Waiting on other players...</h5>
          Please wait until all players are ready
        </div>
      </div>
    );
  }

  renderInput() {
    const { player } = this.props;
    const value = player.round.get("value");
    return (
      <input
        type={"number"}
        min={1}
        onChange={this.handleChange}
        value={value}
        required
      />
    );
  }

  render() {
    const { player } = this.props;

    // If the player already submitted, don't show the slider or submit button
    if (player.stage.submitted) {
      return this.renderSubmitted();
    }

    return (
      <div className="task-response">
        <form className="task-response-form" onSubmit={this.handleSubmit}>
          {this.renderInput()}

          <button type="submit">Submit</button>
        </form>
      </div>
    );
  }
}

```

## Configuring stimulus content

The next step is to allow the experimenter to modify the stimulus without having to update the experiment code directly. We'll accomplish this by adding a JavaScript object to a `constants.js` file (the name of the file in itself is not important, as long as you are consistent), that will contain all the stimulus information, and then use that in the experiment via the `Empirica.gameInit` method.

This all happens server-side, so you need to create this file in your `server/` directory instead of your `client/` directory. Create a file `server/constants.js`, and add the following code to it.

```javascript
export const taskData = {
  candies: {
    path: "/experiment/images/candies.jpg",
    questionText:
      "The jar in this image contains nothing but standard M&M's.  How many M&M's are in the jar?",
    correctAnswer: 797
  },
  survey: {
    questionText:
      "A 2014 survey asked Americans whether science and technology make our lives better (easier, healthier, more comfortable).  What percentage of respondents agreed that science and technology are making our lives better?",
    correctAnswer: 80.5
  }
};
```

{% hint style="info" %}
The **export** keyword allows us to access this JavaScript object in another `.js` or `.jsx` file.
{% endhint %}

### Using data from `constants.js`

Next, we need to use this data in the `Empirica.gameInit` callback in `/server/main.js`. This is an important event that sets up the rounds and stages of a game.&#x20;

{% hint style="info" %}
For more about the life cycle of an Empirica app and its callback, consult [our guide](/overview/lifecycle).
{% endhint %}

You can see that this file has a few imports and then most of the code is within `Empirica.gameInit`. In gameInit, you can see that it is going through each player and assigns them some data such as a score and an avatar. Then it is doing something 10 times (using `_times()` from [underscore.js](http://underscorejs.org); a library of convenient JavaScript tools): It is creating 10 rounds, each with one stage.

First, we import the `constants.js` data with `import { taskData } from "./constants";` added to at the top of `server/main.js`.

We are going to create a network of players. We prepared a node for each player based on their position, and then we assign each player a set of "neighbors": Every possible node except a player's own node. This means this is a full network. Of course, you could create a different type of network if you wanted to. The neighbours will see each other's responses in a social stage we are going to create.

Replace the code in your `server/main.js` with the following code:

```javascript
import Empirica from "meteor/empirica:core";

import "./callbacks.js";
import "./bots.js";

import { taskData } from "./constants";

// gameInit is where the structure of a game is defined.
// Just before every game starts, once all the players needed are ready, this
// function is called with the treatment and the list of players.
// You must then add rounds and stages to the game, depending on the treatment
// and the players. You can also get/set initial values on your game, players,
// rounds and stages (with get/set methods), that will be able to use later in
// the game.
Empirica.gameInit(game => {
  // Establish node list
  const nodes = [];
  for (let i = 0; i <= game.players.length; i++) {
    nodes.push(i);
  }

  game.players.forEach((player, i) => {
    player.set("avatar", `/avatars/jdenticon/${player._id}`);
    player.set("score", 0);

    // Give each player a nodeId based on their position
    player.set("nodeId", i);

    // Assign each node as a neighbor
    const networkNeighbors = nodes.filter(node => node !== i);
    player.set("neighbors", networkNeighbors);
  });

  Object.keys(taskData).forEach(taskName => {
    const task = taskData[taskName];
    const round = game.addRound({
      data: {
        taskName: taskName,
        questionText: task.questionText,
        imagePath: task.path,
        correctAnswer: task.correctAnswer
      }
    });

    round.addStage({
      name: "response",
      displayName: "Response",
      durationInSeconds: 120
    });
  })

});

```

An important part of what is being done is here is adding a `data` object to the rounds. Any value in this object can then be access with `round.get()` .

### Incorporating dynamic round data in TaskStimulus.jsx

Finally, we're ready to incorporate our new configurable task data into `TaskStimulus.jsx`

All we do is change the value of the constants to pull dynamically with `round.get()` instead of setting them manually. Replace the lines that declare the imagePath and the questionText with these:

```javascript
const imagePath = round.get("imagePath");
const questionText = round.get("questionText");
```

We also add logic so that we only display an image if a path is given:

```jsx
<div className="task-image">
  {imagePath && <img src={imagePath} height={"300px"} />}
</div>
```

Overall, it should look like this:

```jsx
import React from "react";

export default class TaskStimulus extends React.Component {
  render() {
    const { round, stage, player } = this.props;

    const imagePath = round.get("imagePath");
    const questionText = round.get("questionText");
    return (
      <div className="task-stimulus">
        <div className="task-image">
          {imagePath && <img src={imagePath} height={"300px"} />}
        </div>
        <div className="task-question">
          <b>Please answer the following question:</b>
          <br />
          {questionText}
        </div>
      </div>
    );
  }
}
```

## Calculating player score with callbacks

Empirica provides a set of methods that will run at the start and end of each round and stage. These can be found in `server/callbacks.js`.

{% hint style="info" %}
To learn more about callbacks, see [our guide on the life cycle of an Empirica experiment](/overview/lifecycle).
{% endhint %}

By default, the score is equal to the total sum of responses, but this is not very informative. We'll modify this to show percentage of error subtracted from 1. Replace the `Empirica.onRoundEnd` code in `server/callbacks.js`  with this:

```javascript
// onRoundEnd is triggered after each round.
// It receives the same options as onGameEnd, and the round that just ended.
Empirica.onRoundEnd((game, round) => {
  game.players.forEach(player => {
    let value = player.round.get("value") || 0;
    const prevScore = player.get("score") || 0;
    let newScore = 1 - value / round.get("correctAnswer");
    if (newScore < 0) newScore = 0;
    player.set("score", prevScore + newScore);
  });
});
```

These scores are compared to the `correctAnswer` from our `constants.js` file.


# Part 3: Adding Social Information and New Factors

## Adding social information

Social information is included in the default Empirica template via `SocialExposure.jsx`. However, nothing will show if we don't have any other players!

In this example we're going to modify the default behavior so that (a) the social information only shows after participants have entered their initial response, and (b) social information shows only for a participant's network neighbors.

### In the admin panel

Return to your `admin panel` and to the `configuration` section.

First, create a multi-player game by adding a new factor value to `playerCount` (following the same procedure as before) with more than one player, then creating a new treatment and a new batch.&#x20;

You can then launch the Empirica app multiple times in the same web browser by clicking `New Player` in the header tab. The game will start once the required number of players have entered the lobby.

### On the server side

Let's go back to `server/main.js`&#x20;

Within each `round` are multiple `stages`. We can add more stages by returning to the `Empirica.gameInit` method and adding the following after the other `roud.addStage` part.

```javascript
round.addStage({
  name: "social",
  displayName: "Social Information",
  durationInSeconds: 120
});
```

So that your `server/main.js` file looks like this:

```javascript
import Empirica from "meteor/empirica:core";

import "./callbacks.js";
import "./bots.js";

import { taskData } from "./constants";

// gameInit is where the structure of a game is defined.
// Just before every game starts, once all the players needed are ready, this
// function is called with the treatment and the list of players.
// You must then add rounds and stages to the game, depending on the treatment
// and the players. You can also get/set initial values on your game, players,
// rounds and stages (with get/set methods), that will be able to use later in
// the game.
Empirica.gameInit(game => {
  // Establish node list
  const nodes = [];
  for (let i = 0; i <= game.players.length; i++) {
    nodes.push(i);
  }

  game.players.forEach((player, i) => {
    player.set("avatar", `/avatars/jdenticon/${player._id}`);
    player.set("score", 0);

    // Give each player a nodeId based on their position
    player.set("nodeId", i);

    // Assign each node as a neighbor
    const networkNeighbors = nodes.filter(node => node !== i);
    player.set("neighbors", networkNeighbors);
  });

  Object.keys(taskData).forEach(taskName => {
    const task = taskData[taskName];
    const round = game.addRound({
      data: {
        taskName: taskName,
        questionText: task.questionText,
        imagePath: task.path,
        correctAnswer: task.correctAnswer
      }
    });

    round.addStage({
      name: "response",
      displayName: "Response",
      durationInSeconds: 120
    });

    round.addStage({
      name: "social",
      displayName: "Social Information",
      durationInSeconds: 120
    });

  })

});

```

### In Round.jsx

We can access the stage information (including the name) within the app, so we're going to modify `Round.jsx` to display the `SocialExposure` component only when `stage.name === "social"`.&#x20;

Modify the `<SocialExposure {...this.props} />` part with this code:

```jsx
{
  stage.name === "social" && (
    <SocialExposure {...this.props} />
  )
}
```

So that your `Round.jsx` file looks like this:

```jsx
import React from "react";

import PlayerProfile from "./PlayerProfile.jsx";
import SocialExposure from "./SocialExposure.jsx";
import Task from "./Task.jsx";

export default class Round extends React.Component {
  render() {
    const { round, stage, player, game } = this.props;

    return (
      <div className="round">
        <div className="content">
          <PlayerProfile player={player} stage={stage} game={game} />
          <Task game={game} round={round} stage={stage} player={player} />
          {
            stage.name === "social" && (
              <SocialExposure {...this.props} />
            )
          }
        </div>
      </div>
    );
  }
}

```

### In SocialExplosure.jsx

Finally, we'll modify `SocialExposure.jsx` .

We're going to remove the slider element, since we are not using that in this example, and just show the number:

```jsx
  renderSocialInteraction(otherPlayer) {
    // Get the value or return NA if no value was entered
    const value = otherPlayer.round.get("value") ?? "NA";
    return (
      <div className="alter" key={otherPlayer._id}>
        <img src={otherPlayer.get("avatar")} className="profile-avatar" />
        Guess: {value}
      </div>
    );
  }
```

{% hint style="info" %}
This simple feature shows just how powerful Empirica can be. Just by virtue of storing user information with `player.set()` and displaying that information in the `SocialExposure` component, the participant's interface is automatically updated. This is due to the way React.js works with Meteor: any time a piece of information passed as one of the props is updated, then the display re-renders to show the new information.
{% endhint %}

We also only want to show information for players listed in `player.get("neighbors")` . Let's do this by replacing the declaration for `const otherPlayers` with:

```javascript
const otherPlayers = game.players.filter(p =>
  player.get("neighbors").includes(p.get("nodeId"))
);
```

*This sets the `otherPlayers` to players that are not the current player and players that are in the current player's neighbors (their node is in their list of neighbors).*

Now, let's add a title to make this component match the other two. And let's make a condition to determine whether the phrase, "There are X other players:", should be plural or not. This paragraph will show different text depending on whether there is only one or more other players.

```jsx
return (
      <div className="social-exposure">
        <h3 className="title">Social Information</h3>
        <p className="title">
          {
            otherPlayers.length > 1
              ? <strong>There are {otherPlayers.length} other players:</strong>
              : <strong>There is one other player:</strong>
          }
        </p>
        {otherPlayers.map(p => this.renderSocialInteraction(p))}
      </div>
    );
```

In the end, your `SocialExposure.jsx` component should look like this:

```jsx
import React from "react";

export default class SocialExposure extends React.Component {
  renderSocialInteraction(otherPlayer) {
    // Get the value or return NA if no value was entered
    const value = otherPlayer.round.get("value") ?? "NA";
    return (
      <div className="alter" key={otherPlayer._id}>
        <img src={otherPlayer.get("avatar")} className="profile-avatar" />
        Guess: {value}
      </div>
    );
  }

  render() {
    const { game, player } = this.props;

    const otherPlayers = game.players.filter(p =>
      player.get("neighbors").includes(p.get("nodeId"))
    );

    if (otherPlayers.length === 0) {
      return null;
    }

    return (
      <div className="social-exposure">
        <h3 className="title">Social Information</h3>
        <p className="title">
          {
            otherPlayers.length > 1
              ? <strong>There are {otherPlayers.length} other players:</strong>
              : <strong>There is one other player:</strong>
          }
        </p>
        {otherPlayers.map(p => this.renderSocialInteraction(p))}
      </div>
    );
  }
}

```

## Adding treatments and factors

One of the key features of Empirica is that you can think like a scientist and control your app with experimental conditions. To show how this works we'll add a factor, allowing us to modify the stage length without changing the code.

First, we add the new factor through the `admin panel` by navigating to the factors interface and clicking "New Factor".&#x20;

We will create a `stageLength` factor of type `Integer`.  You need to add a little description, but you do not need to specify a minimum or maximum.

{% hint style="info" %}
Because we are replacing timing of the stages with this factor, you should make this factor `Required` so that it has to be entered when creating treatment. Otherwise, if you forget to set a `stageLength`, the experiment will break.

You can also archive your previous treatments that do not have a `stageLength`, to avoid being tempted to use them and declutter your interface. You'll always be able to unarchive these if necessary.
{% endhint %}

Now, add a new value to the factor you have created (such as `60`, for 60 seconds).

**Now create a new treatment where you use the stage length.** You can now use this new treatment when you create new batches.&#x20;

We use this treatment information in the `Empirica.gameInit` callback. In  `server/main.js` , go to the part where stages are added to the round, and change the `durationInSeconds: 120`to  `durationInSeconds: game.treatment.stageLength` for both stages.

```javascript
		round.addStage({
			name: "response",
			displayName: "Response",
			durationInSeconds: game.treatment.stageLength
		});

		round.addStage({
			name: "social",
			displayName: "Social Information",
			durationInSeconds: game.treatment.stageLength
		});
```

{% hint style="info" %}
If you are trying to edit elements (e.g., change the styling) you might want the stage length to be longer so you have time to work on your changes without creating new games over and over again. Consider creating a `stageLength` factor that is longer and make a 'test' or 'dev' treatment with this factor that's just for you when you want to do some long edits.
{% endhint %}

## Exporting the Treatments and Factors

The Treatments and Factors that you have created are all saved on your local database. This means that you will no longer have access to them if you share this someone through GitHub, if you reset your app, or if you deploy your app.

**You should export these Treatments and Factors so that they can be imported back in if need be.**

Go to `Configuration` on the admin panel (where you create Treatments and Factors) and click the `Export` button. This will allow you to download a `.yaml` file of your Treatments and Factors. Add it to the root of your Empirica experiment folder (or somewhere else where it is handy to access). It can be good to rename it to something like `factors.yaml`.

Now, if you need to recreate your Treatments and Factors, you can just go `Configuration` on the admin panel, click `Import` and select your `.yaml` file.


# Part 4: Adding Chats

## Installing the Empirica Chat

First, you should stop running your experiment (e.g., press **cntrl+c** in the command line) to [install the package for the Empirica chat](https://www.npmjs.com/package/@empirica/chat).

Install it by running this in the command line:

```
meteor npm install --save @empirica/chat
```

## Adding a chat to the social stage

To add a chat to a component, you have to import it at the top of the `client/game/SocialExposure.jsx` component:

```jsx
import { Chat } from "@empirica/chat";
```

Then, still in the `client/game/SocialExposure.jsx` component, we add a chat component by replacing the return of the main render with this code:

```jsx
    return (
      <div className="social-exposure">
        <h3 className="title">Social Information</h3>
        <p className="title">
          {
            otherPlayers.length > 1
              ? <strong>There are {otherPlayers.length} other players:</strong>
              : <strong>There is one other player:</strong>
          }
        </p>
        {otherPlayers.map(p => this.renderSocialInteraction(p))}
        <div>
          <p className="chat-title"><strong>Chat</strong></p>
          <Chat player={player} scope={round} />
        </div>
      </div>
    );
```

Note that we need to assign this `player` as a property of the chat. We also need to define a `scope`, which determines in which element of Empirica the chat is created (the game, every round, every stage, etc.). Here, we want one chat per round, so we set the scope to the `round`.

This also means we need to call out the round from the props of this component. Replace this line in the main render:

```jsx
const { game, player } = this.props;
```

With this one:

```jsx
const { game, player, round } = this.props;
```

Overall, your `SocialExposure.jsx` component shoud look like this:

```jsx
import React from "react";
import { Chat } from "@empirica/chat";

export default class SocialExposure extends React.Component {
  renderSocialInteraction(otherPlayer) {
    // Get the value or return NA if no value was entered
    const value = otherPlayer.round.get("value") ?? "NA";
    return (
      <div className="alter" key={otherPlayer._id}>
        <img src={otherPlayer.get("avatar")} className="profile-avatar" />
        Guess: {value}
      </div>
    );
  }

  render() {
    const { game, player, round } = this.props;

    const otherPlayers = game.players.filter(p =>
      player.get("neighbors").includes(p.get("nodeId"))
    );

    if (otherPlayers.length === 0) {
      return null;
    }

    return (
      <div className="social-exposure">
        <h3 className="title">Social Information</h3>
        <p className="title">
          {
            otherPlayers.length > 1
              ? <strong>There are {otherPlayers.length} other players:</strong>
              : <strong>There is one other player:</strong>
          }
        </p>
        {otherPlayers.map(p => this.renderSocialInteraction(p))}
        <div>
          <p className="chat-title"><strong>Chat</strong></p>
          <Chat player={player} scope={round} />
        </div>
      </div>
    );
  }
}

```

## Styling the chat

You can now see the chat in the social stage. However, it does not look very pretty. We could use a `customClassName` on the chat component to style all the elements of the chat. However, it is easier for us to just style a few of the chat's elements.

Add this bit of styling at the end of the `client/main.less` :

```css
/* -----------------
- Styling the chat -
----------------- */

.chat-title {
  text-align: center;

  color: white;
  background-color: #394b59;

  border: 1px solid hsl(0, 0%, 75%);

  margin: 1rem 0 0 0;
}

.empirica-chat-container {
  width: 100%;

  .chat {
    form {
      padding: 0;
    }
  }
}

.empirica-chat-container .chat form {
  padding: 0;
}

.chat-button-send, .chat-input {
  min-height: 50px;
}

.empirica-chat-container .chat form .chat-footer .chat-input {
  border-radius: 0%;
}

.empirica-chat-container .chat form .chat-footer .chat-button-send {
  border-radius: 0%;
}

.messages {
  border: 1px solid hsl(0, 0%, 75%);
  max-height: 300px;
}

.empirica-chat-container .chat .messages .message {
  margin: 2rem 0.5rem;
}
```

## Using factors to create conditions with and without chats:

You might want to create condition where there are chats and a condition without chats. We can do that with new Treatments and Factors.&#x20;

Go back to the Admin Panel and create a new `chat` factor as a `boolean` factor so it will be `true` or `false`.  Now  create a treatment with `chat` set to `true` and a treatment with `chat` set to `false`.

Now let's use this information render the chat only if the `chat` factor is set to `true` . Change the return of the main render of the  `SocialExposure.jsx` component with this code:

```jsx
    return (
      <div className="social-exposure">
        <h3 className="title">Social Information</h3>
        <p className="title">
          {
            otherPlayers.length > 1
              ? <strong>There are {otherPlayers.length} other players:</strong>
              : <strong>There is one other player:</strong>
          }
        </p>
        {otherPlayers.map(p => this.renderSocialInteraction(p))}
        {game.treatment.chat &&
          <div>
            <p className="chat-title"><strong>Chat</strong></p>
            <Chat player={player} scope={round} />
          </div>
        }
      </div>
    );
```


# Part 5: Adding Bots

## Adding bots in the factors and treatments

To add bots you need to go to the admin panel and create `botsCount` (the name is important this time!) factor as an integer and set it up with the number of bots you want in your study. Then create treatments that use this factor.

{% hint style="info" %}
Bots will replace one of the player slots. So if you want two human players and one bot, you need to create a game with a `playerCount` of  3.
{% endhint %}

## Programming a bot

In the `server/bots.js` you can create bots to be used based on the number of set in the `botsCount` factor.

Bots will be added to the `game.players` in the game. They have some special characteristics such as a `bot` name.

### **Submitting the stages**

Let's program `bob` to submit every stage if they haven't already. We do so by modifying the `onStageTick` method:

```jsx
// Called during each stage at tick interval (~1s at the moment)
onStageTick(bot, game, round, stage, secondsRemaining) {
    // Have the bot always submit their stage
    if (!bot.stage.submitted) {
      bot.stage.submit()
    }
}
```

### **Getting a value**

In the social stage, we want the bot to get a value and maybe chat. Let's create a conditional to tell the bot what to do when it is the social stage. If the both does not have a value for this round yet, let's set one for them as the mean of the values of the other players.

```jsx
// Called during each stage at tick interval (~1s at the moment)
onStageTick(bot, game, round, stage, secondsRemaining) {

  // Have the bot always submit their stage
  if (!bot.stage.submitted) {
    bot.stage.submit()
  }

  // if this is a social stage... 
  if (stage.name === "social") {
    // get the mean of the values of the other players and set it to the bot
    if (!bot.round.get("value")) {
      const nonBotPlayers = game.players.filter(p => p.bot === undefined)
      const sumValues = nonBotPlayers
        .map(p => Number(p.round.get("value")))
        .reduce((total, item) => (total += item), 0)

      const mean = Math.round(sumValues / nonBotPlayers.length)

      bot.round.set("value", mean)
    }
  }
}
```

### Bots and chats

If there is a chat, we want the bot to send a random message every 20 seconds.

To select a random message from an array we need to create a function to make a random choice. Let's add this function to a separate `.js` file on the server side: `server/randomFunctions.js` :

```javascript
//Function to randomly choose an element from an array:
export const choice = (array) => {
    var randomIndex = Math.floor(Math.random() * array.length);
    var randomElement = array[randomIndex];
    return randomElement;
}

```

Now, let's import this function at the top of the `server/bots.js` file:

```jsx
import { choice } from "./randomFunctions";
```

Now lets also add a list of messages to randomly chose from at the top of the `server/bots.js` file (but below the import statements):

```jsx
const botLanguage = [
  "Hi",
  "That's a good question!",
  "What do you think the correct answer is?",
  "This experiment is fun",
  "I also do human things"
]
```

*Feel free to add your own messages!*

Now, still in the conditional that it is the social round, add a conditional that will send a message if there is a chat in this game and if the remaining seconds are divisible by 20 (to send a message every 20s):

```jsx
// send a random message every 20s
if (game.treatment.chat && secondsRemaining % 20 === 0) {
  const chat = round.get("chat") ?? []

  chat.push({
    text: choice(botLanguage),
    player: {
      _id: bot._id,
      avatar: bot.get("avatar"),
      name: bot.bot
    }
  })

  round.set("chat", chat)
}
```

Notice that we get the `"chat"` from the `round`, this is because we set the `scope` of the chat to the `round`.&#x20;

If the chat is empty, we prepare an empty array, otherwise we take the messages in the chat as they are, and we push a new message from this bot with a random choice of text. We set these new messages to the round.

## Next steps and future work

In this tutorial, we have created a simple experiment that prompts participants to complete numeric estimation tasks and allows them to revise their answers while observing the responses of other participants. We have also added chats and bots.

Right now, this app ONLY works for social conditions ; if you don't have any neighbors, things will look a bit weird because the stage name is called "Social Information".&#x20;

Here are some examples of how we can use Empirica features to expand the functionality of this experiment:

* Add instructions for the different stages of the game.
* Add logic to use different stage names for social and non-social conditions
* Add configurable task instructions to the constants.js that say things like

  "Please answer the question, you will have a chance to revise your answer" and

  "Please revise your answer"
* Add a factor "questionSet" that takes a comma-separated list of question

  identifiers, and uses only those questions. This allows different treatments

  to use different conditions, based on the same constants.js file.
* If you want to use more complex network structures, you could store those in a

  json/js format and import them in main.js

There are also several very basic features from the Intro and Outro we haven't touched yet that you'll need to update:

* The Consent form
* The Instructions pages
* The attention check
* The Exit Survey and Thank You page


# The Settings File

Emprica is configured with **settings** stored as `json` data.

You will need to create a **settings file** to set up your app. This will be a `.json` file, which is often named`settings.json` (or `local.json` or `deploy.json`).

**The settings file contains information that you do not want to share with the public**, such as your admin password and database security credentials. Hence you should keep it private. If you put your code on an online version-control repository (e.g., GitHub), we suggest you ***add the name of your settings file to the\*\*\*\* ****`.gitignore`**** \*\*\*\*file of your project.***

The settings file contains a JSON object `{}` in which there are other objects separated by `,`

```javascript
{
    "galaxy.meteor.com": {
        
    },
    "admins": [
        {
            "username": "myusername",
            "password": "mypassword"
        }
    ],
    "public": {  
    }
}
```

To run your app locally with your settings as set in the settings file, use:

```
meteor --settings settings.json
```

## Uses

The settings file is useful for:

{% content-ref url="/pages/-McUuO\_zLytU0OSDCkMc" %}
[Specifying Login Details](/guides/the-settings-file/specifying-login-details)
{% endcontent-ref %}

{% content-ref url="/pages/-MeYmiTudC\_682iD2eOa" %}
[Setting player ids via URL queries](/guides/the-settings-file/id-url-queries)
{% endcontent-ref %}

{% content-ref url="/pages/-MeYmsRwl-Htl9bLpyZw" %}
[Connecting Locally to MongoDB](/guides/the-settings-file/connecting-locally-to-mongodb)
{% endcontent-ref %}


# Specifying Login Details

If you go to the settings file, you can elements to set the username and the password of the admin account for your Empirica Admin Panel.

For example:

```
{
  "admins": [
    {
      "username": "admin",
      "password": "p5yycpd2yrg"
    }
  ]
}
```

You can set the information you want here. Now you can run your app with:

```
meteor --settings <name of settings file>
```

This will allow you to open the admin panel with your own login details instead of the one automatically generated.


# Setting player ids via URL queries

You can have the player's id set automatically based on a URL query (e.g., `MID` or `PROLIFIC_PID`). This will skip the section at the start of the game where players put in their id.

In the `public` section of your settings file, add this sort of code:

```
"public": { 
    "playerIdParam": "playerIdKey",
    "playerIdParamExclusive": false 
}
```

Where `"playerIdParam"` sets the name of the URL query parameter after which you set the player's id.  For example,  a fake app with these settings, I could set the player id directly in the URL `https://myfakeapp.meteorapp.com/?playerIdKey=3333`.

If `"playerIdParamExclusive"` is set to `true` , then players can only ever participate if their id is set by the `"playerIdParam"` (i.e., they cannot set their id in the NewPlayer page), but if it is set to `false`, then players can join both by setting their id at the NewPlayer page (if there is no query in their URL) and by having their id in the URL query set by the `"playerIdParam"`.


# Connecting Locally to MongoDB

You can run your Empirica experiment locally, whilst still connecting it to a cloud MongoDB database.

To do so, you need to [create the database and obtain the URI](/guides/deploying-my-experiment/database).

## Via the settings file

As explained in the [guide for deploying to MongoDB](/guides/deploying-my-experiment/database#how-do-i-connect-my-app-to-mongodb-atlas), you will need to add these elements to your settings file:

```
    "galaxy.meteor.com": {
        "env": {
            "MONGO_URL": "mongodb+srv://<read&write username>:<read&write password>@<connection>/<database name>?retryWrites=true&w=majority",
            "MONGO_OPLOG_URL": "mongodb+srv://<oplog username>:<oplog password>@<connection>/local"
        }
    },
```

Fill in the <> parts with the appropriate elements.

Now you can run your app with:

```
meteor --settings <name of settings file>
```

{% hint style="info" %}
This might not always work for connecting locally to your MongoDB. The method below is more reliable.
{% endhint %}

## Via the command line

According to your OS, follow the instructions below to connect to your MongoDB via the command line.

{% tabs %}
{% tab title="Mac, Linux, Windows with WSL" %}
Run this command with the URI you have obtained but without the `?retryWrites=true&w=majority`

```
MONGO_URL=<MongoDB URI> meteor
```

{% endtab %}

{% tab title="Windows without WSL" %}
Create a `.bat` file (e.g., `start.bat`). **These files allow you to run multiple commands on Windows. Do not run commands you are not comfortable with or not convinced they are secure.**

Make sure that you have `*.bat` in your `.gitignore` because this file will contain sensitive information (your access to the database) and you don't want it to be sent to your repository.\
\
Add the following commands to the file with the URI you have obtained but without the `?retryWrites=true&w=majority`:

```
SET MONGO_URL=<MongoDB URI>
meteor
```

Run the file in the command line (e.g., `.\start.bat` ).
{% endtab %}
{% endtabs %}


# The Admin Panel

## Structure

The Admin Panel, that you can access at `<url>/admin` is made of two parts:

* The **monitoring** tab
* The **configuration** tab

### The Monitoring Tab

Here you can create and run batches of game, monitor player statuses, and export the data.

### The Configuring Tab

Here you can create factors, to then make treatments, to then be used with lobby configurations when creating batches.

## Deleting Game and Player data but keeping Treatments, Factors, and Lobby Configurations

In the **Monitoring tab**, you can click on **Reset** and then `Reset Games` to clean the data from previous instances/tests. It will remove the current *batches*, *games*, *players* but it will keep the *treatments*, *factors*, and *lobby configurations*.

## Deleting all the data and settings of an experiment

In the **Admin Panel**, in the **Monitoring tab**, you can click on **Reset** and then `Reset Entire App` to clean the whole database. It will remove all of the data in the database.

## Retiring Players: How players can play again, even if they got gameFull, LobbyTimedOut, etc.

Players can only play once. If there was a problem (e.g., the lobby timed out or the game was full), or if you want players to play again, you can *retire* them which allows them to play again.

In the **monitoring tab**, in the **players tab**, you can see the status of every Player. At the bottom of the page, you can select a type of **exit status** and retire every player with that status.

Once *retired*, players can refresh their page/return to the link of your game and they will be randomly allocated to a game with the same treatment as before. They are allocated to a game with the same treatment so that they don't discover a game with different conditions or instructions.

### I tried to retire a player but got this error: Failed to return players: Error: ID cannot exceed 256 characters in players update \[400], what should I do?

This means that the player id of the player was too long. If you go to your data base you can find that player and modify their player id so that it is not as long.

## Lobby Configuration

In the **Configuration tab**, in **Lobby Configurations**, you can set important aspects of the Lobby such as:

* The `Timeout Type` (whole lobby or individual)
* The `Timeout Duration in Seconds`
* The `Timeout Strategy` (fail, ignore)
* The `Extend Count`

### What happens when the Lobby times-out?

When players start a Game, they go through Intro Steps, and when they have finished the Intro Steps they arrive at a Lobby where they are set as **ready** and they wait for other players to join until there are as many ready players as the number set in the `playerCount` factor.

However, it is possible that there won't be enough players and you don't want players to wait indefinitely in the Lobby for others to join. Hence, you can set a time after which the Lobby times-out.

This is set in the **Configuration tab**, in **Lobby Configurations**. What happens when the Lobby times-out depends on these settings.

If `Timeout Type` is set to *Lobby* then the countdown to the timeout starts as soon as the first player reaches the Lobby. Here the `Timeout Stragety` determines what happens when the Lobby times-out:

* If set to *Fail*, the Game will fail (it will be terminated) and the current players waiting in the Lobby [will be sent to the Exit Steps set for them](/faq/faq#how-can-i-show-a-different-exit-step-to-players-depending-on-whether-they-have-finished-the-game-or-if-the-game-was-cancelled-had-a-problem) with their Exit Status set to *gameLobbyTimedOut*.
* If set to *Ignore*, it will start the Game anyway, even if there aren't enough players.

If `Timeout Type` is set to *Individual* then a different countdown starts for each player when they reach the Lobby. If the Lobby times-out, the player[ will be sent to the Exit Steps set for them](/faq/faq#how-can-i-show-a-different-exit-step-to-players-depending-on-whether-they-have-finished-the-game-or-if-the-game-was-cancelled-had-a-problem) with their Exit Status set to *playerLobbyTimedOut*, but the Game will not fail (i.e., players can still join the game). With `Extend Count` you can set the number of times the player needs to timeout before they are sent to the Exit Steps. If `Extend Count` is set to 0, then after one timeout the player is sent to the Exit Steps, if it is set to 1, then after two timeouts the player is sent to the Exit Steps.

## Importing and exporting my treatments, factors, and lobby settings

In the **configuration** tab there are **Import** and **Export** buttons.&#x20;

The **Export** button will produce a `.yaml` file of your treatments and factors.

The **Import** button will allow you to select a `.yaml` file to set the treatments and factors.

If you want to share your app with someone, it is important to provide this `.yaml` so that they can use the same treatments and factors as you.


# Special Empirica Elements (and how to modify them)

## Centered

The **Centered component** is a custom element from Empirica that you can use to surround other elements of your components. This will make them centered on the page.

Import the element with:

```
import { Centered } from "meteor/empirica:core";
```

And use it like this:

```jsx
<Centered>        
    <div> Other elements </div>    
</Centered>
```

## Timer

There is a `Timer.jsx` component that represents the stage timer and shows players how much time is left at that stage.&#x20;

For the Timer to work, the `stage` has to be passed down to it as a prop. For example, in the `PlayerProfile.jsx` of [your first Empirica experiment](/guides/tutorial-your-first-experiment/your-first-experiment):

```jsx
return (
      <aside className="player-profile">
        {this.renderProfile()}
        {this.renderScore()}
        <Timer stage={stage} />
      </aside>
    );
```

Inside the `Timer.jsx` component, what makes the timer is that it extracts the `remainingSeconds` from the `stage`, and that it imports the `StageTimeWrapper` to export the Timer with `export default (Timer = StageTimeWrapper(timer));`.&#x20;

Here is the code for a basic Timer component:

```jsx
import { StageTimeWrapper } from "meteor/empirica:core";
import React from "react";

class timer extends React.Component {
  render() {
    const { remainingSeconds } = this.props;

    const classes = ["timer"];
    if (remainingSeconds <= 5) {
      classes.push("lessThan5");
    } else if (remainingSeconds <= 10) {
      classes.push("lessThan10");
    }

    return (
      <div className={classes.join(" ")}>
        <h4>Timer</h4>
        <span className="seconds">{remainingSeconds}</span>
      </div>
    );
  }
}

export default (Timer = StageTimeWrapper(timer));
```

## About Section

The **About section** is a small window that will upon when players click the top right corner button `About`. For example:

![](https://1898430204-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M-Cqf0McgfJZYwXisux%2F-MRQbSG8am4AC8PUONx0%2F-MRQdzXo7v4WknaO99Wi%2FCapture.PNG?alt=media\&token=f3d1026d-5d8a-477e-beba-490ccdab4047)

In `client/main.js` you can set your custom component for the About section.&#x20;

Import the component to the `client/main.js` with:

```
import <component name> from <path>;
```

And then set it with:

```
Empirica.about(<component name>);
```

However, setting an About section is completely optional, you can get rid of it by not writing the `Empirica.about` line in `client/main.js` or deleting it if it is already written.

## Header

The **Header** is the blue rectangle at the top of the page in an Empirica app.&#x20;

See more about the structure of the Header component [here](/overview/api#empirica-header-component).

Import the component to the `client/main.js` with:

```
import <component name> from <path>;
```

And then set it with:

```
Empirica.header(<component name>);
```

Or you can get rid of the Header with:

```
Empirica.header(() => null);
```

## Special Dev Wrap Header

If you don't want the blue header to show, especially not when you deploy your experiment, but you still want to access the `Reset Player` and `New Player` buttons during development, you can surround each of your important components (e.g., Round.jsx, Intro steps, etc.) with this special component:

```jsx
import React from 'react'

export default function DevWrapper({
    children,
    showOpenAltPlayer,
    onOpenAltPlayer,
    showReset,
    onReset, }) {

    const isDev = showReset || showOpenAltPlayer

    return (
        <div>
            {isDev &&
                <div style={{
                    display: "flex"
                    , justifyContent: "flex-end"
                    , alignItems: "center"
                    , margin: "5px"
                }}>
                    <p style={{
                        fontSize: "1rem"
                        , color: "grey"
                        , margin: "0"
                    }}>Dev buttons:</p>
                    {showReset &&
                        <button style={devButtons} onClick={onReset}>Reset Player</button>
                    }
                    {showOpenAltPlayer &&
                        <button style={devButtons} onClick={onOpenAltPlayer}>New Player</button>
                    }

                </div>
            }

            { children}
        </div >
    )
}

// Styling
const devButtons = {
    backgroundColor: "transparent"
    , fontSize: "1rem"
    , color: "grey"
    , margin: "0 2.5px"
    , cursor: "pointer"
}
```

For example, to have it show in each round, import it into the round component and use it this way:

```jsx
export default class Round extends Component {
	render() {
		const { round, stage, player, game } = this.props

		return (
			<DevWrapper {...this.props}>
				<div>
					The Rounds
				</div>
			</DevWrapper>
		)
	}
}
```

## Breadcrumb

The **Breadcrumb** is the track at the top of a Round that shows the player which Stage of the Round they are currently at.

See more about the structure of the Breadcrumb component [here](/overview/api#empirica-breadcrumb-component).

![](https://1898430204-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M-Cqf0McgfJZYwXisux%2F-MRVlAzEfY9JHItIv7rg%2F-MRVltn81PUTOcL7sVSI%2Fexample_breadcrumb.PNG?alt=media\&token=b50be9db-5a09-4cbf-9722-1a1dfda3c4a7)

In `client/main.js` you can set your custom component for the Breadcrumb.&#x20;

Import the component to the `client/main.js` with:

```
import <component name> from <path>;
```

And then set it with:

```
Empirica.breadcrumb(<component name>);
```

Or you can get rid of the Breadcrumb with:

```
Empirica.breadcrumb(() => null);
```

## NewPlayer (where players set their id)

Players have to set their id at a **NewPlayer page** just after the consent page. This could be a name, an MTurk/Prolific id, a student id, an email, etc.&#x20;

You might want to change its design, format, or instructions. For example, if you want participants to provide a student id but no other personal information, you would want to make your own clear instructions.

The default NewPlayer.jsx page looks like this:

```jsx
import React, { Component } from 'react'
import { Centered } from "meteor/empirica:core";

export default class NewPlayer extends Component {
  state = { id: "" };

  handleUpdate = event => {
    const { value, name } = event.currentTarget;
    this.setState({ [name]: value });
  };

  handleSubmit = event => {
    event.preventDefault();

    const { handleNewPlayer } = this.props;
    const { id } = this.state;
    handleNewPlayer(id);
  };

  render() {
    const { id } = this.state;

    return (
      <Centered>
        <div >
          <form onSubmit={this.handleSubmit}>
            <h1>Identification</h1>

            <p>
              Please enter your id:
                        </p>

            <input
              dir="auto"
              type="text"
              name="id"
              id="id"
              value={id}
              onChange={this.handleUpdate}
              required
              autoComplete="off"
            />

            <br />

            <p>
              <button type="submit">Submit</button>
            </p>

          </form>
        </div>
      </Centered>
    )
  }
}
```

The important parts of your component is to have methods to handle when the player is changing the id they write (`handleUpdate`) and when the player clicks the submit button (`handleSubmit`) so that in the end it is using the `handleNewPlayer()` method that will set the player's id as the string submitted and moves the player to the first Intro Step.

You can either modify the `NewPlayer.jsx` file, or create a new one and set it in the `client/main.js`.

**If you want to create a new file:**

Import the component to the `client/main.js` with:

```
import <component name> from <path>;
```

And then set it with:

```
Empirica.newPlayer(<component name>);
```

## Lobby

In the **Admin Panel**, in the **Configuration tab**, in **Lobby Configurations**, you can set important aspects of the Lobby such as:

* The `Timeout Type` (whole lobby or individual)
* The `Timeout Duration in Seconds`
* The `Timeout Strategy` (fail, ignore)
* The `Extend Count`

But you might want to customise your Lobby even further (e.g., change what it looks like or what is written). To do so, you can create a **custom Lobby component**. It will receive two props, the `player` and the `gameLobby`. The `gameLobby` can be used to extract the following properties in the customising of your Lobby:

* `gameLobby.treatment.playerCount` will give you how many players the Game expects
* `gameLobby.queuedCount` will give you the total number of players queued for this game, including ready players and players currently going through the intro steps.&#x20;
* `gameLobby.readyCount` will give you the number of players ready to play. They have completed the intro steps, and they are on the lobby page.

For a better idea of what you can do and customise, see the default version of the Lobby [here](https://github.com/empiricaly/meteor-empirica-core/blob/master/ui/components/GameLobby.jsx).

Once you have created your custom Lobby component, you can import the component to the `client/main.js` with:

```
import <component name> from <path>;
```

And then set it with:

```
Empirica.lobby(<component name>);
```

### Can I add a chat to the Lobby?

To add a chat to the Lobby you need to install the **Empirica Chat** with:

```
meteor npm install --save @empirica/chat
```

Then you can use the default Lobby with chat. Do so by importing the  `LobbyChat` component of this package in your experiment's `client/main.js` file, like this:

```
import { LobbyChat } from "@empirica/chat";
```

And setting it to the lobby like this:

```
Empirica.lobby(LobbyChat);
```

Or you can manually add a chat to your customised Lobby.

## Empirica Chat

To add a chat  in Empirica, you can use our simple solution by using the **Empirica Chat**. For detailed information about Empirica Chat, see [here](https://github.com/empiricaly/chat).

### Installing

First, install Empirica Chat with:

```
meteor npm install --save @empirica/chat
```

### Import and Usage

In the components you want to use the chat, import this:

```
import { Chat } from "@empirica/chat";
```

Then you can create the chat component with:

```jsx
<Chat player={player} scope={game} />
```

`chat` expects 2 required props:

* `player`: the current player
* `scope`: object that the chat will be attached to, can be game, round, or stage objects.

### Scoping

The scope is important because it determines where the chat data (the messages) will be stored. You can access them again afterwards based on the scope. For example, if the scope is set to the Round:

```javascript
const chat = round.get("chat") ?? []
```

### Multiple chat instances within the same scope

You can pass an optional `customKey` string prop to differentiate different chats within the same scope. This changes which get/set key on the given scope the chat will be recorded.

```jsx
<Chat player={player} scope={game} customKey="casual_chat" />
```

### Display names

`Chat` also displays a name for each participant, which you need to set in the experiment independently of the `playerId`: `player.set('name', "myPseudonym")`

### Adding timestamp to chat message

You can pass an optional `timeStamp` date prop to add the timestamp attribute on each message sent.&#x20;

Run this command to add mizzao timesync:

```
meteor add mizzao:timesync
```

You can pass an optional timeStamp date prop to add the timestamp attribute on each message sent:

```jsx
// reactive time value only updates at 1000 ms
const timeStamp = new Date(TimeSync.serverTime(null, 1000));

<Chat player={player} scope={game} timeStamp={timeStamp} />
```

### Other functionalities

There are many other functionalities with Empirica chat that you can see [here](https://github.com/empiricaly/chat).


# Deploying Your Experiment

How to connect your experiment to a database and deploy it online so that others can participate

This tutorial describes how to connect to [`MongoDB Atlas`](https://www.mongodb.com/cloud/atlas) for your database service and [`Meteor Galaxy`](https://www.meteor.com/cloud)(a service directly provided by Meteor) for your app hosting service.  Other services are also available, and we find these particularly easy with Empirica.

*To understand the role of database and hosting, see documentation on the* [*general structure of an Empirica experiment*](/overview/structure)*.*

{% content-ref url="/pages/-M\_4x7jPx4wI6HK-Tww6" %}
[Database](/guides/deploying-my-experiment/database)
{% endcontent-ref %}

{% content-ref url="/pages/-M\_4x6zvFZWTUjvu4Mwk" %}
[Hosting](/guides/deploying-my-experiment/hosting)
{% endcontent-ref %}


# Database

How to connect your experiment to a MongoDB Atlas database where data to run your experiment as well as participant data will be held.

## How do I connect my app to MongoDB Atlas?

First, create an account on [MongoDB Atlas](https://www.mongodb.com/cloud/atlas).&#x20;

Then you should set up a **project**. A project can contain multiple **clusters**, which can contain multiple **databases**, which can contain multiple **collections**. You can share access to your project with collaborators if you wish.&#x20;

### Clusters

In your project, got to *clusters* and click on *Create a New Cluster*. You can select the provider, region, and tier of your cluster. It takes a few minutes for the cluster to become operational.

{% hint style="info" %}
The **sandbox** tier allows you to test out a free cluster with a limited storage space. This is perfect for development. However, you want to have more power, space, and guaranties when you deploy your app and start collecting data. Unless you plan on collecting a lot of data, an **M10 tier** is a good place to start. **Please take note of the fees involved in cluster tiers other than sandbox.**
{% endhint %}

### Users

In *Database Access*, click *add new database user*. You want to  create a Read\&Write user by creating a user an that has a username, a password, and *Read and write to any database* privileges.

It is also useful to create an OPLOG user. You can create one the same way as the Read\&Write user, with a username and a password, but for the privileges select *Grant specific privileges* and have the specific privileges be `read @ local` (leave the Collection blank).

### Network Access

In *Network Access*, click *add ip addresses* to set the IP addresses that are allowed to access your databases. Technically, someone using your app 'needs to access your databases' (through your app, not directly), so if you want any player to be able to play your game, you should set the IP address to any IP address (whitelist): 0.0.0.0/0

### Databases

In your cluster, click *collections* and then *create database* where you will set the name of your database and its first collection. The name of the collection isn't very important, because most of the collections of interest will be generated by your Empirica app once it is connected to the database.&#x20;

### Connecting to your app

In your cluster, click *connect*, then click *connect your application*. It will open a window where you should select *Node.js* as the driver. It also presents a **URI** that you will need to copy to connect your app to your database.

You need the `?retryWrites=true&w=majority` part for the [resilience of your app](https://docs.atlas.mongodb.com/resilient-application/).

The important part that this URI provides you is the part between the `@` and the `<dbname>`, it is the **connection**.

In your [settings file](/guides/the-settings-file), you will have to add this JSON object:

```
    "galaxy.meteor.com": {
        "env": {
            "MONGO_URL": "mongodb+srv://<read&write username>:<read&write password>@<connection>/<database name>?retryWrites=true&w=majority",
            "MONGO_OPLOG_URL": "mongodb+srv://<oplog username>:<oplog password>@<connection>/local"
        }
    },
```

Fill in the <> parts with the appropriate elements from when you created the users and the database. The connection is mentioned above.

Now, when you [deploy your app with the settings file](/guides/deploying-my-experiment/hosting#deploying) or when you [launch it locally with the settings file](/guides/the-settings-file/connecting-locally-to-mongodb), you will be connected to the database. Once you start using your app connected to the database, your should be able to verify that everything worked by refreshing your page on your cluster's database: You will see all the collections relevant to an Empirica app appear (games, players, treatments, etc.).

### MongoDB Atlas sent me an email about Query Targeting, should I be worried?

If you regularly receive emails about `Query Targeting: Scanned Objects / Returned has gone above 1000`, and you haven't been making custom queries to the database, then it is likely NOT a problem. Verify that your data is complete as it should. If it is, then this is probably because the long running query to the oplog does end up reading over 1000 records, but that’s normal, and Atlas does not know it’s a normal behavior that does not impact performance. It should be safe to [disable this notification in the Atlas admin](https://docs.atlas.mongodb.com/configure-alerts/#disable-an-alert).


# Hosting

Hosting your experiment on Meteor Galaxy so that people can access it and participate in it.

## How do I deploy my app to Galaxy?

[Galaxy](https://www.meteor.com/cloud) (also called Meteor Cloud) is a hosting service provided by Meteor. For a full guide on deploying to Galaxy, see [here](https://galaxy-guide.meteor.com/deploy-guide.html).

### Registering and logging in

The first step is to register an account with Meteor Galaxy. **Please take note of the fees involved in hosting with Galaxy.**

Then, in your app's command line, you should log into your Meteor Galaxy account with:

```
meteor login
```

It will then prompt you for your username and password.

To see which account is currently logged into your app you can type:

```
meteor whoami
```

### Hostname

A **hostname** is the name that the public will use to access your app.&#x20;

Part of the hostname is the **domain name**. You can use a custom domain name if you own one, or use one of those offered by Galaxy.&#x20;

If you are using the offered domain, use:

* &#x20;`.meteorapp.com` for apps deployed to the US East region
* &#x20;`.eu.meteorapp.com` for apps deployed to the EU West region
* &#x20;`.au.meteorapp.com` for apps deployed to the Asia-Pacific region

For example, a complete hostname with a Galaxy offered domain could be: `my-game-study-example.meteorapp.com`

This, combined with *https\://* is the link you will send players for them to access your app.

### DEPLOY\_HOSTNAME

You will need to enter a deploy\_hostname variable depending on your location:

* To deploy to US East: `DEPLOY_HOSTNAME=galaxy.meteor.com`
* To deploy to EU West: `DEPLOY_HOSTNAME=eu-west-1.galaxy.meteor.com`
* To deploy to Asia-Pacific: `DEPLOY_HOSTNAME=ap-southeast-2.galaxy.meteor.com`

### Deploying

Once you have selected a hostname and a deploy\_hostname variable, you need to type the following commands to deploy your app to Galaxy with your [settings file](/faq/faq#what-is-the-settings-json).

{% tabs %}
{% tab title="Linux, Mac, Windows with WSL" %}

```
[deploy_hostname] meteor deploy [hostname] --settings settings.json
```

{% endtab %}

{% tab title="Windows without WSL" %}

```
SET [deploy_hostname]
meteor deploy [hostname] --settings settings.json
```

{% endtab %}
{% endtabs %}

For example, you might run this:

```
DEPLOY_HOSTNAME=galaxy.meteor.com meteor deploy my-game-study-example.meteorapp.com --settings settings.json
```

Note that deploying an app **takes a few minutes!**

Once it is done, you can go to <https://galaxy.meteor.com/> to check on your apps. You can inspect their **logs** and modify their **settings**.&#x20;

If you run the commands to deploy the app again, it will redeploy the app with any changes you have made since your last deployment.

### What should the scale of my hosting service be?

The size of the Galaxy hosting is determined by **containers** of different size. You can have multiple containers of the same size. This will determine how many players and games can co-occur on your deployed app. **Please take note of the fees involved in hosting with Galaxy.**

**You may be able to get a single Tiny container for a free plan (check your Meteor Cloud/Galaxy account).** However, the Tiny containers will be insufficient for collecting data. You will want bigger containers. The exact size depends on how many players will be using your app concurrently an how demanding your app is. The most basic way of finding out the right size for you is to test your deployed app with different containers whilst monitoring the CPU usage.&#x20;


# Managing the Data

## Recording the data

There are multiple places where you can record data in an Empirica experiment.

### To the player

One way of recording the data of players' responses is to set them to the `player` prop itself. You can do so with this command:

```
player.set("name of property", value)
```

You can retrieve what you have set as a specific property/answer for the player with:

```
player.get("name of property")
```

This will be accessible in the `player` collection of your database.

### To the player.stage

One way of recording the data of players' responses is to set them to the `player.stage` prop to identify a particular data/response of a particular player to a particular stage. You can do so with this command:

```
player.stage.set("name of property", value)
```

You can retrieve what you have set as a specific property/answer with:

```
player.stage.get("name of property")
```

This will be accessible in the `player-stages` collection of your database.

### To the player.round

One way of recording the data of players' responses is to set them to the `player.round` prop to identify a particular data/response of a particular player to a particular round. You can do so with this command:

```
player.round.set("name of property", value)
```

You can retrieve what you have set as a specific property/answer with:

```
player.round.get("name of property")
```

This will be accessible in the `player-rounds` collection of your database.

### To the round

If you want to save general data (not specific to one player), you can save it to the `round` with:

```
round.set("name of property", value)
```

You can retrieve what you have set as a specific property/answer with:

```
round.get("name of property")
```

This will be accessible in the `round` collection of your database.

### To the game

If you want to save general data (not specific to one player), you can save it to the `game` with:

```
game.set("name of property", value)
```

You can retrieve what you have set as a specific property/answer with:

```
game.get("name of property")
```

This will be accessible in the `game` collection of your database.

## Data structure

The data is stored in your database across multiple different collections (e.g., batches, games, players, etc.).

The collections you are the most interested in are:

* batches
* games
* player-inputs
* players

Because that is where most of the data is. You can then wrangle these together according to game, player, batch, and other `_ids`.

## Manually downloading data

In the **Admin Panel**, in the **configuration tab**, you can click on **Export** to download a zip file with CSVs or JSONs for each of these collections. The advantage of downloading from the panel is that all the data objects will have been unnested to some extent. For example, every attribute of a Player will be a column in players.csv and every Player will be a row.

## Collect or avoid collecting the players' id, IP address, and user agent

Empirica allows you to collect the user agents and the IP addresses of players, but this has to be activated to avoid running into privacy issues unknowingly.

To do so, in the `"public"` part of the settings file you need to add:

```
"collectPII": true
```

When you download files from the control panel, you need to tick a specific box if you want to download the `player id` (the id they enter themselves or that is set as a URL parameter), the user agents, and the IP addresses of players (if you have decided to collect them): `Add Personal Identity Information (includes the player ID, URL parameters, and IP addresses)`

This allows you to download a version of the data without any identifying information.

## How long players took to submit in a stage

Once you have the data, in the `player_stages` part of the data, you can see each `playerId` and `stageId` combination, when it is was started (`createdAt`) and when the player submitted (`submittedAt`). Compare the two and that will give you the time it took the player to submit that stage.

## How long the game lasted

Once you have the data, in the `game` part of the data, you can see for each game, when it is was created  (`createdAt`) and when it finished (`finishedAt`). Compare the two and that will give you how long that game lasted.

**Note: this does not count the intro and exit steps, only the game part**.

## Wrangling the data with R

Instead of manually downloading the data, you can directly access the data in your database with the R programing language (similar things can be done with Python and other languages).

### Preparation

You will need the `mongolite` library and the `tidyverse` (or at least `dplyr`) library.

You will need [this great function to unnest the data](https://raw.githubusercontent.com/joshua-a-becker/RTools/master/df_unnest.R). The top of your script should look like this:

```r
# preparations
library(mongolite)
library(tidyverse)
source("https://raw.githubusercontent.com/joshua-a-becker/RTools/master/df_unnest.R")
```

Then you need to save your [MongoDB URI](/guides/deploying-my-experiment/database) to a variable (without the `?retryWrites=true&w=majority`):

```r
# The URI to the mongoDB database
uri <- "<your uri>"
```

### Getting collections

To get data from collection that is then unnest, use the `mongo` and `find` functions from the `mongolite` packaged, the pipe from `dplyr` and the special unnesting function:

```r
players <- mongo("players", url = uri)$find(
  fields='{}'
) %>% 
  df_unnest()
```

The first argument of the `mongo` function is the string of the collection you want to download. You can do this for players, player-stage, player-rounds, rounds, stages, games, batches, factors, treatments.

The fields argument of the `find` function ca be tricky. If you set it to `'{}'` it means it will grab every field in the database. However, you might do that and find that there is an issue with your dataframes because of a mismatch between the names of dataframe and the actual names available. This is usually because Empirica creates potential a `data` field - the field where all the data that you `.set()` goes to (see above on recording the data). So if you haven't set any data to this part of the experiment, and you are getting errors when trying to view the dataframes, set it to `'{"data":false}'` instead.

### Tips for Renaming and Joining

Once you have accessed all the collections you need, you can use merger/join functions to bring everything together into one dataframe.

The games, the players, the rounds, etc. will have certain variables with the same names that you might want to rename: `_id` (the unique id from the database), `index`, `createdAt`.&#x20;

The id variable of from dataframe might be referred to in another, so you can use this to join dataframes together. For example, `players` has  `_id` which corresponds to `playerId` in `player_stages`.


# Using Custom Collections

Empirica allows you to store data in different places for each game (e.g., game, round, stage, player, etc.). But you might want to store and use data in a special structure or have certain data accessible across all games (e.g., global configs, data from all participants). To do so, you need to create and use custom collections in your database. Thankfully, Empirica uses Meteor, which makes this process easy (see [their collections API docs](https://docs.meteor.com/api/collections.html)).

*Note: you can use custom collections during development without* [*connecting your experiment to MongoDB*](/guides/the-settings-file/connecting-locally-to-mongodb)*. However, it is easier to see what is happening if you are connected to a cloud database that you can monitor.*

### Using custom collections just on the server side

You need to create a file to connect to your custom collection. I usually put these in an `api` folder. Create a `.js` file for the collection of interest. For example, `playerScores.js`.

The contents should look something like this:

```javascript
import { Mongo } from 'meteor/mongo';

export const PlayersScores = new Mongo.Collection('players-scores');
```

The string you pass to the `new Mongo.Collection` is the name of the collection.

Then you can access this collection in your other server side file with an import statement, for example:

```javascript
import { PlayersScores } from "./api/playerScores"
```

Then you can use this collection by updating it, or setting it to elements that are easy to access on the client side (e.g., game, round, stage).

To get elements from the collection (example):

```javascript
PlayersScores.find({}).fetch()
```

To insert a new element to the collection (example):

```
PlayersScores.insert({ playerId: player._id, score: player.get("score") })
```

### Using custom collections on the client side

If you want to use the custom collection directly on the client side, you should set the files in a `shared` folder in the root of your experiment files so that it can be access both on the client and server side. **Set the file for the collection as explained above.**

In `server/main.js` , import the collection and publish it.\
*For example with a 'admin-global-configs' custom collection.*

```javascript
import { Configs } from "../shared/api/collectionAdminGlobalConfigs.js";

Meteor.publish('admin-global-configs', function publishTasks() {
  return Configs.find({})
})
```

On the client side you need to use a special tracker from Meteor to follow when the collection is available and when it has been changed. To use it, you want to create three parts to your component:

* One part to hold the other parts,
* one part to connect to the collection and send the information as props to
* the last part where the information will be displayed

For example we create a waiting consent component where we want participants to wait until a certain time before they can join the experiment.

Create the `WaitingConsent.jsx` component (don't  forget it to set it in the `client/main.js`).&#x20;

Import the important elements:

```javascript
import { withTracker } from "meteor/react-meteor-data"
import { Configs } from '../../../shared/api/collectionAdminGlobalConfigs'
```

Then create the first part in which you call the second part.

```jsx
export default class WaitingConsent extends Component {
    render() {

        return (
            <div>
                {/* Load the db data which loads the page contents */}
                <WaitingConsentPageContents {...this.props} />
            </div>
        )
    }
}
```

Create the third and second part (in this order):

```jsx
class WaitingConsentPage extends Component {

    render() {
        const { loading, now, timeToStart } = this.props

        if (loading) {
            return (
                <div>Loading...</div>
            )
        }

        let difference = +timeToStart - +now

        // If waiting for the time, show the countdown and instructions
        if (difference > 1) {
            return (
                <div>
                    <h3>Countdown</h3>
                    ...
                    </div>
                </div>

            )
        }

        // otherwise return consent page
        return (
            <div>
               <h3>Consent</h3>
                ...
            </div>
        )
    }
}

WaitingConsentPageContents = withTracker(rest => {

    // Suscribe to collection information, and return nothing as long as it is loading
    const loading = !Meteor.subscribe("admin-global-configs").ready()
    if (loading) {
        return {
            loading
        }
    }

    // Get the globalConfigs collection
    const globalConfigs = Configs.find({}).fetch()[0] ?? {}
    const timeToStart = new Date(globalConfigs.timeToStart)

    // Get time now (makes sur the whole process is synced)
    const now = new Date(TimeSync.serverTime(null, 1000))

    return {
        loading,
        timeToStart,
        now,
    };

})(WaitingConsentPage)
```

You can see how in the last component we are subscribing to the collection, waiting for it to load, and then sending this information to the other component.


# Structure

## General Structure

Empirica allows you to build powerful apps for multiplayer and singleplayer research. It is made of these important components:

* Your **code**.
  * The backend (managing your games and data) with Meteor
  * The frontend (what the players see and interact with) with React.js
* An **Admin Panel** that allows you manage the conditions, games, and players in your experiment.
* A connection to a **database**, such as MongoDB Atlas, to store your data that can be accessed and modified live by your experiment.
* The app is deployed to a **hosting service**, such as Meteor Galaxy, so that your experiment is online and you can send a **link** for players to connect to it.

![](https://1898430204-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M-Cqf0McgfJZYwXisux%2F-MRZ91D5enNaGw_j9UOm%2F-MRZAKH7AtyEoVbf3ANQ%2FPicture1.png?alt=media\&token=428689e8-4a09-471d-beed-83927f2c1a91)

## File Structure

This is what a starting Empirica experiment file structure looks like:

```
my-experiment
├── .meteor
├── README.md
├── node_modules
├── package.json
├── package-lock.json
├── .gitignore
├── public
├── client
│   ├── main.html
│   ├── main.js
│   ├── main.css
│   ├── game
│   │   └── ...
│   ├── intro
│   │   └── ...
│   └── exit
│       └── ...
└── server
    ├── main.js
    ├── callbacks.js
    └── bots.js
```

**It contains:**

* `.meteor` with the meteor files. You do not need to touch those.
* `node_modules` the files for the node modules in your app. You do not need to touch those. This directory should be in the `.gitignore` file.
* `public` where you store static assets (e.g., images).
* `client` where you set what the players can see in the experiment.
* `server` where you manage the flow and resources of the experiment.

### Client

All code in the `/client` directory will be ran on the client. The entry point for your app on the client can be found in `/client/main.js`. In there you will find more details about how to customize how a game *Round* should be rendered, what *Consent* message and which *Intro Steps* you want to present the players with, etc.

The HTML root of you app in `/client/main.html` shouldn't generally be changed much, other than to update the app's HTML `<head>`, which contains the app's title, and possibly 3rd party JS and CSS imports.

All styling starts in `/client/main.less`, and is written in [LESS](http://lesscss.org/), a simple superset of CSS. You can also add a plain CSS files in `/client`.

The `/client/game`, `/client/intro`, `/client/exit` directories all contain [React](https://reactjs.org/) components, which compose the UI of your app. If you are new to React, we recommend you try out the official [React Tutorial](https://reactjs.org/tutorial/tutorial.html).

### Server

Server-side code all starts in the `/server/main.js` file. In that file, we set an important Empirica integration point, the `Empirica.gameInit`, which allows to configure each game as they are initiated by Empirica.

From there we import 2 other files. First the `/server/callback.js` file, which contains all the possible callbacks used in the lifecycle of a game. These callbacks, such as `onRoundEnd`, offer powerful ways to add logic to a game in a central point (the server), which is often preferable to adding all the logic on the client.

&#x20;Finally, the `/server/bots.js` file is where you can add bot definitions to your app.

### Public

The `/public` is here to host any static assets you might need in the game, such as images. For example, if you add an image at `/public/my-logo.jpeg`, it will be available in the app at `http://localhost:3000/my-logo.jpeg`.


# Game Life Cycle

*Elements on this page refer to the f*[*ile structure*](/overview/structure)*,* [*concepts*](/overview/concepts)*, and* [*API* ](/overview/api)*of an Empirica experiment.*

Empirica experiments are event driven. The image below summarizes the lifecycle from the beginning of a game through exit steps.

![](https://1898430204-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M-Cqf0McgfJZYwXisux%2F-M_5ri7COWVb0gPSVr41%2F-M_5u7cgy5ZsdnOmkqgX%2FPicture3.png?alt=media\&token=2ecb38ae-4a04-4b3b-aa64-acd94b0c9169)

### Beginning and intro steps

In the admin panel, you would create a Batch of games for players to join. Players enter the game where they go through a consent form (optional), they provide an identifier (which can be set via URL queries), and they do the intro steps (the instructions and other components you have set in the intro steps. All of these are set by you in the `./client` . During these steps, players are **asynchronous**; namely, they complete these steps at their own pace until they have finished them, independent from the pace of other players.

### gameInit

Once players finish the intro steps they are sent to a lobby where they wait until every player has joined. When every player has joined, the Game object is created based on what is set in `./server/main.js` in the  `Empirica.gameInit()` . This is where certain parameters are set, and where the Rounds and their Stages are created.

In the `./server/callbacks.js`, `Empirica.onGameStart()` is also triggered at the same time as `Empirica.gameInit()`. Any pre-game preparations can be done in either `gameInit` or `onGameStart` interchangeably. It might make sense to the Game designer to split the overall **mandatory** Game configuration (Rounds and Stages) in `gameInit`, from data initialization (using `set` on Game, Players, Rounds and Stages objects) in `onGameStart`, but it is not required.

### Rounds and Stages

Then players go through each Stage of each Round. Once a Stage is finished, they move on to the next. If this was the last Stage of a Round, they move on to the next Round. If this was the last Round, they move on to the Exit Steps.&#x20;

During these steps, players are **synchronous**; namely, every player has to finish each stage before they can all move on to the next.

In the `./server/callbacks.js`,  a series of callbacks are triggered during this process:&#x20;

* Before a round starts, [`onRoundStart`](http://localhost:3000/docs/api#empiricaonroundstartcallback) is called.
* Before a stages starts, [`onStageStart`](http://localhost:3000/docs/api#empiricaonstagestartcallback)is called.&#x20;
* When a Stage ends, [`onStageEnd`](http://localhost:3000/docs/api#empiricaonstageendcallback) is called.&#x20;
* When a Round ends, [`onRoundEnd`](http://localhost:3000/docs/api#empiricaonroundendcallback)is called.

See our guide on customising when player submit a stage:

{% content-ref url="/pages/-MeZTEmahAt8YzPgoM3K" %}
[Customising when players submit stages](/overview/lifecycle/customising-when-players-submit-stages)
{% endcontent-ref %}

### Game end and exit steps

Finally, when the last Round ends, after the end of Stage and Round callbacks are triggered, the [`onGameEnd`](http://localhost:3000/docs/api#empiricaongameendcallback) callback is called in the `./server/callbacks.js`.

After which, the players goes through the exit steps. During these steps, players are **asynchronous**; namely, they complete these steps at their own pace until they have finished them, independent from the pace of other players.

### List of callbacks

The list of callbacks goes as follows in order:

* `gameInit` Required
* `onGameStart`
* `onRoundStart` Repeated for each Round
* `onStageStart` Repeated for each Stage
* `onStageEnd` Repeated for each Stage
* `onRoundEnd` Repeated for each Round
* `onGameEnd`


# Customising when players submit stages

## When players submit (end) a stage

Instead of having players wait until the end of the stage, you can have them submit their answer. This will set the Stage as submitted for them. If all the other players have also submitted the Stage, then the players move on to the next Stage or Round.

To set the stage to submitted you need to run this method from the `player` prop:

```
player.stage.submit()
```

This will change this property, that you can use to see if the stage has been submitted (it is a Boolean, true or false):

```
player.stage.submitted
```

For example, you could create a button, that has a handle method for `onClick` that will do the necessary with the player's answer and call `player.stage.submit()`.

## What players see when they have submitted a stage

Once a player submits for the stage, you might want to show something different on the screen. For example, instead of showing the stage's question/task (and avoiding players submitting multiple responses), you could show a message thanking the player for submitting the stage and telling them that they will have to wait for all players to submit the stage before they can move on to the next one.

You can do this by setting a **conditional** that renders different elements depending on what `player.stage.submitted` returns.

For example:

```jsx
{
player.stage.submitted
    ? <div> Thank you for your answer. The next stage will start when all the other 
    players have submitted their answer. </div>
    : <div><Question player={player} /></div>
}
```


# Concepts

*Elements on this page might refer to the f*[*ile structure*](/overview/structure)*, the* [*life cycle*](/overview/lifecycle)*, or the* [*API* ](/overview/api)*of an Empirica experiment.*

## Game

A Game is a single run of the experiment. It is also used to describe the experiment that was developed. One or more *Players* participate in a Game. A Game is divided in three main parts: Intro steps, Game, and Exit Steps.&#x20;

The *Intro Steps* are when Players arrive in the game. They can read instructions, answer quizzes, etc. before arriving to the *Lobby*. The Intro Steps are asynchronous (each player completes these steps at their own pace). Once all the Players have reached the Lobby stage, the *Game* initialises. The Game part of the Game is composed of *Rounds*, which are themselves divided into *Stages*. Players must complete every stage of a Round before moving on to the next Round. The Game is synchronous (every player has to finish a stage before the can all move on to the next stage). Once every Round is complete, the Players will reach the *Exit Steps* where they can read a debrief, answer questionnaires, etc. The Exit Steps are asynchronous.&#x20;

## Player

Players are users participating in a Game. A game must have a least 1 Player. Each Player entry in the database will contain information such as their last login, their unique ID, the ID of the Game they are participating in, which steps they have accomplished, and any other data you additionally assign to Players (e.g., an avatar to represent the Player).&#x20;

## Batch

A Batch is a set of 1 or more Games that run in parallel. Batches allow to create different assignment methods for player distribution: simple and complete. Batches are ran one at a time, in order of creation time. If you start multiple batches at once in the admin, only the first will accept players. Once full the next batch will automatically start receiving players.

## Round

A Game is made up of 1 or more ordered Rounds. A round contains 1 or more stages. Rounds are usually composed of the same stages and repeats over the course of the game.

E.g. For the guess the correlation experiment, on each round, we ask the player to guess the correlation between a graph and a numerical value. In the first stage of each round, it's the guess, the second stage the reveal of the result, and in the third stage we show what other players have guessed; all in the same round; and in the next round, we repeat those stages.

It is not required for all Round to contain the same stages or even the same number of stages.

Rounds do not have a name, they have an order number (1, 2, 3...).

## Stage

A Round may contain 1 or more stages. A stage has a duration, a name and a display name.

The `name` is the programmatic reference that can later be used in the UI code to differentiate stages. The `displayName` on the other hand is used in the UI, and it a clean human readable name. For example, a stage name might be "*guess*", while the display name might be "*Guess A Number*".

The `durationInSeconds` is set in seconds, with a minimum of 5 seconds, and no maximum. You can also allow Players to *submit* a stage, which marks it as done for the given player. When all players have submitted, the stage is considered done. If the stage timer runs out the stage is also considered done, whichever happens first.

If you do not want to have a timer and want to wait until players submit, you can set the timer to an unreasonable value (e.g. 30000000 \~= a year), and hide the timer in the UI.

The Rounds and Stages are **synchronous** (every player has to finish a stage before the can all move on to the next stage). The timer allows you to avoid one Player not responding and stopping the other Players from continuing because a new stage starts when the timer ends.

## Factors

Factors are essentially variables that will affect how a game will play. One *Factor Type* is mandatory for any Empirica game, the `playerCount` number.

Factors are assembled into Treatments, which are themselves assigned to Games.

To create *Factor Values*, you must first create Factor Types. A *Factor Type* describes the Factor. A \_Factor Type) has a `name`, a `description`, a `type` and a `required` marker.

* The `name` must be a code-friendly name, such a `playerCount`, which does not

  contain spaces or odd characters and is written in

  [camelCase](https://en.wikipedia.org/wiki/Camel_case).
* The `description` is a human readable description used in the admin UI to help

  other admins understand what this factor does.
* Finally, the `type` is a computing type (integer, string, ...) to limit what

  \_Factor Values *can be created for this \_Factor Type*.
* Factor Types can also be marked as `required`, meaning they are required in

  all treatments.

The Factors can then be accessed as a property of the Game. This can be used to represent different conditions. For example, say you want some Games to show information from the other Players' answers to each other and some Games not to. You can have a "socialInformation" factor set to "yes" and "no", and only show the information from other Players if `game.socialInformation == "yes"` .

## Treatment

A Treatment is a named *set of Factors*. Each Factor can appear at most once in a treatment and required Factors must be present. The set of Factors in a treatment must be unique, no two treatment with the exact same set of factors can be created.

## Game Lobby

A Game Lobby is where the players wait for other players to arrive, and until the game starts.

### Lobby Config

The Game Lobby is configured by lobby configs for common scenarios. It contains a timer duration for the lobby, and handles the behavior of the app in case of timeouts. Such as whether it should try again or cancel the game once the timer runs out.

## Intro Steps

The Intro Steps are pages shows to the user after registering and before the game or game lobby. These steps can be configured by the game designer to contain whatever is needed: instructions, a quiz, forms, etc.

The set of steps can be altered depending on the treatment assigned to the current player or the treatments.

The Intro Steps are **asynchronous** (each player completes these steps at their own pace).

## Exit Steps

The Exit Steps are pages shown to the user after the game. They are configured by the experiment designer and may contain: results, reward instructions, quiz, thank you note...

The steps shown may be altered depending on any parameter of the player or the game (treatment, results, etc.).

The Exit Steps are **asynchronous** (each player completes these steps at their own pace).


# Randomization & Batches

## Creating batches

In the `Admin panel` you can create a batch of games. Select the games of the different treatments you want and create the batch.&#x20;

To start the games in the batch click the `► Start`  button.&#x20;

Now players can join the games in that batch.&#x20;

If all the games from that batch are full, they will be allocated to games in other open batches that have the same treatments. If there are no such games available, the players will receive a `gameFull` and told that there are no games available.

## What do the assignment methods 'simple' and 'complete' do?

These are different methods for randomly allocating players to different Games.

When you create a Batch, you can create multiple games within it, and these games can have different treatments. With experiments, one usually wants to randomly allocate players across the different games (Treatments).

**Simple** will randomly allocate players to either of the games. Imagine rolling a die for each player to determine which game they are sent to. This might lead to situations where more than the maximum number of players of a game are allocated to a game. In that case, the first players to reach the lobby will be those who get the play the game and the others will be unable to join and their status will be set to `gameFull`.

**Complete** will randomly allocate players to either of the games except those who already have the maximum number of players. This avoids the potential gameFull issue of the simple allocation method.

## What's the difference between N batches of 1 game each or 1 batch of N games?

The assignment of players to games is done in batches sequentially and within each batch players will be randomly assigned to one game. Therefore, when you have 1 batch with multiple games, players will be assigned randomly to each of the X games according to the assignment method. This means it's possible that none of the games fill up even though enough players join for at least one game to proceed past the lobby as the players are distributed across various games. This would not happen if each batch has only one game: the first game will fill up with the first players who move past the lobby and the remaining players will transition to the game in the second batch.

If you want to ensure the maximum possible number of players get assigned to a game, a good strategy would be to start batches each with 1 game per each treatment condition. For example, if you have two treatment conditions of 8 players each, your batches should contain 1 game of each treatment. This way you can be sure if 16 players join, all 16 will be randomized between only 2 games and you don't lose any of your players in games that never fill up. **This approach however has a drawback as it does not randomize between players with different arrival time or completion time of instructions.**


# API

*Elements on this page refer to the f*[*ile structure*](/overview/structure)*,* [*concepts*](/overview/concepts)*, and* [*life cycle*](/overview/lifecycle) *of an Empirica experiment.*

This document describes Empirica's [server](/overview/api#server), [client](/overview/api#client) and [shared ](/overview/api#shared)APIs.

## Server

### `Empirica.gameInit(callback)`

The `gameInit` callback is called just before a game starts, when all players are ready, and it must create rounds and stages for the game.

One (and one only) gameInit callback is required for Empirica to work.

The callback receives one argument, the [`game` object](/overview/api#game-object), which gives access to the `players` and the treatment for this game.

It also offers the `addRound()` method, which allows to add a round to the `game`. The returned Round object will implement the `addStage(stageArgs)` method, which allows to add a Stage to the Round. The `stageArgs` object to be passed to the stage creation method must contain:

* `name`: the name used to identify this stage in the UI code
* `displayName`: which will be showed to the UI to players
* `durationInSeconds`: the stage duration, in seconds

Note that the Game has not yet been created when the callback is called, and you do not have access to the other properties of the Game which will be created subsequently.

#### Example

```javascript
Empirica.gameInit(game => {
  game.players.forEach((player, i) => {
    player.set("avatar", `/avatars/jdenticon/${player._id}`);
    player.set("score", 0);
  });

  _.times(10, i => {
    const round = game.addRound();
    round.addStage({
      name: "response",
      displayName: "Response",
      durationInSeconds: 120
    });

    if (game.treatment.playerCount > 1) {
      round.addStage({
        name: "response",
        displayName: "Response",
        durationInSeconds: 120
      });
    }
  });
});
```

### **Game Callbacks**

Game hooks are optional methods attached to various events throughout the game life cycle to update data on the server-side.

Contrary to client side data updates, sever-side updates are synchronous, there is no risk of conflicting updates, and important calculations can be taken at precise points along the game.

### `Empirica.onGameStart(callback)`

`onGameStart` is triggered once per game, before the game starts, and before the first [`onRoundStart`](broken://pages/-M-DTNZemLa_RUod2OLW#empiricaonroundstartcallback). It receives the [`game` object](/overview/api#game-object). Contrary to [`gameInit`](broken://pages/-M-DTNZemLa_RUod2OLW#empiricagameinitcallback), the Game has been created at this point.

#### Example

```javascript
Empirica.onGameStart(game => {
  if (game.treatment.myFactor === "fourtytwo") {
    game.set("maxScore", 100);
  } else {
    game.set("maxScore", 0);
  }
});
```

### `Empirica.onRoundStart(callback)`

`onRoundStart` is triggered before each round starts, and before [`onStageStart`](broken://pages/-M-DTNZemLa_RUod2OLW#empiricaonstagestartcallback). It receives the same options as [`onGameStart`](https://app.gitbook.com/s/-M-Cqf0McgfJZYwXisux/overview/empiricaongamestartcallback), and the [round](/overview/api#round-object) that is starting.

#### Example

```javascript
Empirica.onRoundStart((game, round) => {
  round.set("scoreToReach", game.get("maxScore"));
});
```

### `Empirica.onStageStart(callback)`

`onRoundStart` is triggered before each stage starts. It receives the same options as [`onRoundStart`](https://app.gitbook.com/s/-M-Cqf0McgfJZYwXisux/overview/empiricaonroundstartcallback), and the [stage](/overview/api#stage-object) that is starting.

#### Example

```javascript
Empirica.onStageStart((game, round, stage) => {
  stage.set("randomColor", myRandomColorGenerator());
});
```

### `Empirica.onStageEnd(callback)`

`onStageEnd` is triggered after each stage. It receives the current [game](/overview/api#game-object), the current [round](/overview/api#round-object), and [stage](/overview/api#stage-object) that just ended.

#### Example

```javascript
Empirica.onStageEnd((game, round, stage) => {
  stage.set("scoreGroup", stage.get("score") > 10 ? "great" : "not_great");
});
```

### `Empirica.onRoundEnd(callback)`

`onRoundEnd` is triggered after each round. It receives the current [game](/overview/api#game-object), and the [round](/overview/api#round-object) that just ended.

#### Example

```javascript
Empirica.onRoundEnd((game, round) => {
  let maxScore = 0;
  game.players.forEach(player => {
    const playerScore = player.round.get("score") || 0;
    if (playerScore > maxScore) {
      maxScore = playerScore;
    }
  });
  round.set("maxScore", maxScore);
});
```

### `Empirica.onGameEnd(callback)`

`onGameEnd` is triggered when the game ends. It receives the [`game`](broken://pages/-M-DTNZemLa_RUod2OLW#game-object) that just ended.

#### Example

```javascript
Empirica.onGameEnd(game => {
  let maxScore = 0;
  game.rounds.forEach(round => {
    const roundMaxScore = round.get("maxScore") || 0;
    if (roundMaxScore > maxScore) {
      maxScore = roundMaxScore;
    }
  });
  game.set("maxScore", maxScore);
});
```

### ***Change Callbacks***

[onSet](/overview/api#empirica-onset-callback), [onAppend](/overview/api#empirica-onappend-callback) and [onChange](/overview/api#empirica-onchange-callback) are called on every single update made by all players in each game, so they can rapidly become **computationally expensive** and have the potential to seriously slow down the app. Use wisely.

It is very useful to be able to react to each update a user makes. Try nontheless to limit the amount of computations and database saves done in these callbacks. You can also try to limit the amount of calls to `set()` and `append()` you make (avoid calling them on a continuous drag of a slider for example) and inside these callbacks use the `key` argument at the very beginning of the callback to filter out which keys your need to run logic against.

If you are not using these callbacks, comment them out, so the system does not call them for nothing.

### `Empirica.onSet(callback)`

`onSet` is called when the experiment code call the `.set()` method on games, rounds, stages, players, playerRounds or playerStages.

#### Example

```javascript
Empirica.onSet((
  game,
  round,
  stage,
  player, // Player who made the change
  target, // Object on which the change was made (eg. player.set() => player)
  targetType, // Type of object on which the change was made (eg. player.set() => "player")
  key, // Key of changed value (e.g. player.set("score", 1) => "score")
  value, // New value
  prevValue // Previous value
) => {
  // Example filtering
  if (key !== "value") {
    return;
  }

  // Do some important calculation
});
```

### `Empirica.onAppend(callback)`

`onSet` is called when the experiment code call the `.append()` method on games, rounds, stages, players, playerRounds or playerStages.

#### Example

```javascript
Empirica.onAppend((
  game,
  round,
  stage,
  player, // Player who made the change
  target, // Object on which the change was made (eg. player.set() => player)
  targetType, // Type of object on which the change was made (eg. player.set() => "player")
  key, // Key of changed value (e.g. player.set("score", 1) => "score")
  value, // New value
  prevValue // Previous value
) => {
  // Note: `value` is the single last value (e.g 0.2), while `prevValue` will
  // be an array of the previsous values (e.g. [0.3, 0.4, 0.65]).
});
```

### `Empirica.onChange(callback)`

`onChange` is called when the experiment code call the `.set()` or the `.append()` method on games, rounds, stages, players, playerRounds or playerStages.

`onChange` is useful to run server-side logic for any user interaction. Note the extra `isAppend` boolean that will allow to differenciate sets and appends.

#### Example

```javascript
Empirica.onChange((
  game,
  round,
  stage,
  player, // Player who made the change
  target, // Object on which the change was made (eg. player.set() => player)
  targetType, // Type of object on which the change was made (eg. player.set() => "player")
  key, // Key of changed value (e.g. player.set("score", 1) => "score")
  value, // New value
  prevValue, // Previous value
  isAppend // True if the change was an append, false if it was a set
) => {
  Game.set("lastChangeAt", new Date().toString());
});
```

### `Empirica.onSubmit(callback)`

`onSubmit` is called when the experiment code call the `.submit()` on a Stage.

Note that onSubmit is only called if `.submit()` is explicitely called on the Stage object. Players for which the stage times out naturally, `onSubmit` will not be triggered.

#### Example

```javascript
Empirica.onSubmit((game, round, stage, player) => {
  stage.set("lastSubmitAt", new Date().toString());
});
```

### ***Adding Bots***

Adding bots to a game is as simple as defining a few callbacks. You can add different bots with different behaviors.

### `Empirica.bot(name, configuration)`

The `bot` method allows to add a bot with `name` (e.g. "Alice"), while the `configuration` is a set of callbacks that will allow to configure how the bot is suppose to react in certain conditions.

The `configuration` has the follows callbacks:

* `onStageTick`: called during each stage at 1 second interval
* `onStageStart`: **CURRENTLY NOT SUPPORTED** called at the beginning of each

  stage (after `onRoundStart`/`onStageStart`)
* `onStageEnd`: **CURRENTLY NOT SUPPORTED** called at the end of each stage

  (after `onStageEnd`, before `onRoundEnd` if it's the enf of the round)
* `onPlayerChange`: **CURRENTLY NOT SUPPORTED** called each time any (human)

  player has changed a value

All callbacks are called with the following arguments:

* `bot`: is the [`Player` object](broken://pages/-M-DTNZemLa_RUod2OLW#player-object) representing this bot
* `game`: the current [`Game`](broken://pages/-M-DTNZemLa_RUod2OLW#game-object)
* `round`: the current [`Round`](broken://pages/-M-DTNZemLa_RUod2OLW#round-object)
* `stage`: the current [`Stage`](broken://pages/-M-DTNZemLa_RUod2OLW#stage-object)
* `secondsRemaining`: the number of remaining seconds in the stage

#### Example

```jsx
Empirica.bot("bob", {
  onStageTick(bot, game, round, stage, secondsRemaining) {
    let score = 0;
    game.players.forEach(player => {
      if (player === bot) {
        return;
      }
      const playerScore = player.get("score");
      if (playerScore > score) {
        score = playerScore
      }
    });
    bot.set("score", score+1);
  }
};)
```

## Client

### `Empirica.round(Component)`

Set the `Round` Component that will contain all of the UI logic for your game.

#### Props

*Component* will receive the following props:

| Prop     | Type                                  | Description         |
| -------- | ------------------------------------- | ------------------- |
| `game`   | [Game](/overview/api#game-object)     | The current game.   |
| `player` | [Player](/overview/api#player-object) | The current player. |
| `round`  | [Round](/overview/api#round-object)   | The current round.  |
| `stage`  | [Stage](/overview/api#stage-object)   | The current stage.  |

#### Example

```jsx
const Round = ({ player, game, round, stage }) => (
  <div className="round">
    <div className="profile">{player.id}: {player.get("score")}</p>
    <div className="stimulus">{stage.get("somePieceOfData...")</p>
    // ... Add round logic here. This is not a good example, we recommend you
    // take a look a Tutorial or a Demo app for better examples.
  </div>
);
Empirica.round(Round);
```

### `Empirica.consent(Component)`

Optionally set the `Consent` Component you want to present players before they are allowed to register.

#### Props

*Component* will receive the following props:

| Prop        | Type     | Description                                                                                 |
| ----------- | -------- | ------------------------------------------------------------------------------------------- |
| `onConsent` | Function | A function to call when the user has given consent (usually, clicked a "I consent" button). |

#### Example

```jsx
const Consent = ({ onConsent }) => (
  <div className="consent">
    <p>This experiment is part of...</p>
    <p>
      <button onClick={onConsent}>I CONSENT</button>
    </p>
  </div>
);
Empirica.consent(Consent);
```

### `Empirica.introSteps(callback)`

Set the intro steps to present to the user after consent and registration, and before they are allowed into the Lobby. These steps might be instructions, a quiz/test, a survey... You may present the steps in multiple pages.

The `introSteps` callback should return an array of 0 or more React Components to show the user in order.

#### Props

*Component* will receive the following props:

| Prop     | Type                                                        | Description                                                              |
| -------- | ----------------------------------------------------------- | ------------------------------------------------------------------------ |
| `game`   | [Game](broken://pages/-M-DTNZemLa_RUod2OLW#game-object)     | The current [game](broken://pages/-M-DTNZemLa_RUod2OLW#game-object).     |
| `player` | [Player](broken://pages/-M-DTNZemLa_RUod2OLW#player-object) | The current [player](broken://pages/-M-DTNZemLa_RUod2OLW#player-object). |

**N.B.: The `game` given here&#x20;*****only*****&#x20;has the `treatment` field defined as the game has not yet been created.**

#### Example

```javascript
Empirica.introSteps((game, player) => {
  const steps = [InstructionStepOne];
  if (game.treatment.playerCount > 1) {
    steps.push(InstructionStepTwo);
  }
  steps.push(Quiz);
  return steps;
});
```

N.B.: `InstructionStepOne` or `Quiz`, in this example, are components that are not implemented in this example, they are simply React Components.

### `Empirica.exitSteps(callback)`

Set the exit steps to present to the user after the game has finished successfully (all rounds finished) or not (lobby timeout, cancelled game,...)

The `exitSteps` callback should return an array of 1 or more React Components to show the user in order.

#### Props

*Component* will receive the following props:

| Prop     | Type                                  | Description         |
| -------- | ------------------------------------- | ------------------- |
| `game`   | [Game](/overview/api#game-object)     | The current game.   |
| `player` | [Player](/overview/api#player-object) | The current player. |

#### Example

```javascript
Empirica.exitSteps((game, player) => {
  if (player.exitStatus !== "finished") {
    return [Sorry];
  }
  return [ExitSurvey, Thanks];
});
```

N.B.: `ExitSurvey` or `Thanks`, in this example, are components that are not implemented in this example, they are simply React Components.

### `Empirica.lobby(Component)`

Optionally set the `Lobby` Component to replace the default lobby.

#### Props

*Component* will receive the following props:

| Prop        | Type                                        | Description             |
| ----------- | ------------------------------------------- | ----------------------- |
| `gameLobby` | [GameLobby](/overview/api#gamelobby-object) | The current game lobby. |
| `player`    | [Player](/overview/api#player-object)       | The current player.     |

#### Example

```jsx
const Lobby = ({ player, gameLobby }) => (
  <header className="lobby">
    <h1>Please wait until the game is ready...</h1>
    <p>
      There are {gameLobby.readyCount} players ready out of{" "}
      {gameLobby.treatment.playerCount} expected total.
    </p>
  </header>
);
Empirica.lobby(Lobby);
```

### `Empirica.header(Component)`

Optionally set the `Header` Component to replace the default app header.

#### Props

*Component* will NOT receive any props.

#### Example

```jsx
const Header = () => (
  <header className="app-header">
    <img src="/my-logo.png" />
    <h1>My Experiment</h1>
  </header>
);
Empirica.header(Header);
```

### `Empirica.breadcrumb(Component)`

Optionally set the `Breadcrumb` Component to replace the default Round/Stage progress indicator. This is the UI that shows which are the current Round and Stage, between the page Header and the Round

#### Props

*Component* will receive the following props:

| Prop     | Type                                  | Description         |
| -------- | ------------------------------------- | ------------------- |
| `game`   | [Game](/overview/api#game-object)     | The current game.   |
| `player` | [Player](/overview/api#player-object) | The current player. |
| `round`  | [Round](/overview/api#round-object)   | The current round.  |
| `stage`  | [Stage](/overview/api#stage-object)   | The current stage.  |

#### Example

```jsx
const Breadcrumb = ({ round, stage }) => (
  <ul className="breadcrumb">
    <li>Round {round.index + 1}</li>
    {round.stages.map(s => (
      <li key={s.name} className={s.name === stage.name ? "current" : ""}>
        {s.displayName}
      </li>
    ))}
  </ul>
);
Empirica.breadcrumb(Breadcrumb);
```

### `Empirica.routes()`

`routes` are the entry point for the Empirica app. It is required to be used as part of the React render tree for Empirica to work properly and the example below usually does not need changing, other than the HTML node to attach to (`document.getElementById("app")` here).

N.B.: This must be called after any other Empirica calls (Empirica.round(), Empirica.introSteps(), ...).

#### Example

```javascript
Meteor.startup(() => {
  render(Empirica.routes(), document.getElementById("app"));
});
```

## Shared

### `Game` object

| Property    | Type                                                   | Description                                                                                                                           |
| ----------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| `index`     | Number                                                 | An auto-increment number assigned to each Game in order (1, 2, 3...)                                                                  |
| `treatment` | Object (key: String, value: String or Integer)         | An object representing the Factors set on this game, e.g. `{ "playerCount": 12 }`.                                                    |
| `players`   | Array of [Player objects](/overview/api#player-object) | Players participating in this Game.                                                                                                   |
| `rounds`    | Array of [Round objects](/overview/api#round-object)   | On the server side, this will show every round that makes up the game. But on the client side, this will only show the current round. |
| `createdAt` | Date                                                   | Time at which the game was created which corresponds approximately to the time at which the Game started.                             |

### `Round` object

| Property | Type                                                 | Description                                                                        |
| -------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------- |
| `index`  | Object                                               | The 0 based position of the current round in the ordered list of rounds in a game. |
| `stages` | Array of [Stage objects](/overview/api#stage-object) | Stages composing this Round.                                                       |

### `Stage` object

| Property            | Type    | Description                                                                                               |
| ------------------- | ------- | --------------------------------------------------------------------------------------------------------- |
| `index`             | Object  | The 0 based position of the current stage in the ordered list of a **all** of the game's stages.          |
| `name`              | String  | Programmatic name of stage (i.e. to be used in code, e.g `if (name === "outcome") ...`).                  |
| `displayName`       | String  | Human name of stage (i.e. to be showed to the Player, e.g "Round Outcome").                               |
| `durationInSeconds` | Integer | The stage duration, in seconds.                                                                           |
| `startTimeAt`       | Date    | Time at which the stage started. (only set if stage has already started, i.e. not set in `onStageStart`). |

### `Player` object

| Property              | Type                       | Description                                                                                                                                                                                                   |
| --------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `index`               | Number                     | An auto-increment number assigned to each Player in order (1, 2, 3...)                                                                                                                                        |
| `id`                  | String                     | The ID the player used to register (e.g. MTurk ID).                                                                                                                                                           |
| `urlParams`           | Object (key/value: String) | Parameters that were set on the URL when the user registered.                                                                                                                                                 |
| `bot`                 | String                     | Name of the bot used for this player, if the player is a bot (e.g. `Alice`).                                                                                                                                  |
| `readyAt`             | Date                       | Time at witch the player became ready (done with intro steps).                                                                                                                                                |
| `exitAt`              | Date                       | Time when the player exited the Game (whether the game ended normally or not, see exitStatus).                                                                                                                |
| `exitStatus`          | String                     | <p>Status of the Player at Game exit. <br><br> Can be: "gameFull", "gameCancelled", "gameLobbyTimedOut", "playerEndedLobbyWait", "playerLobbyTimedOut", "finished". "finished" represent the normal exit.</p> |
| `online`              | Boolean                    | True if the player is currently online.                                                                                                                                                                       |
| `idle`                | Boolean                    | True if the player is currently online but idle. Idleness is defined as either the page not being active (on another tab/window) or not detecting any activity (mouse/keyboard) for more than 60s.            |
| `lastActivityAt`      | Date                       | Time when the player was last seen online and active (not idle). Server only (this is not accessible on the client at the moment).                                                                            |
| `lastLogin.at`        | Date                       | Time the player last come online (registered, reopened page and auto-login kicked in or re-entered player ID – if they were forgotten).                                                                       |
| `lastLogin.ip`        | String                     | [IP address](https://developer.mozilla.org/en-US/docs/Glossary/IP_Address) of player on last connection.                                                                                                      |
| `lastLogin.userAgent` | String                     | [User-Agent](https://developer.mozilla.org/en-US/docs/Glossary/User_agent) of player on last connection.                                                                                                      |

### `GameLobby` object

| Property      | Type                                           | Description                                                                                                                                                                                                                                                                                                                                                                                                                       |
| ------------- | ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `treatment`   | Object (key: String, value: String or Integer) | An object representing the Factors set on this game, e.g. `{ "playerCount": 12 }`.                                                                                                                                                                                                                                                                                                                                                |
| `queuedCount` | Integer                                        | <p>Total number of players queued for this game, including ready players and players currently going through the intro steps. <br> <br> <strong>N.B.: There could be more players in queuedCount than specified by the <code>playerCount</code> Factor, as Empirica can sometimes overbook Games to shorten wait times.</strong> <br> Use <code>gameLobby.treatment.playerCount</code> to get the expected number of players.</p> |
| `readyCount`  | Integer                                        | Number of players ready to play. They have completed the intro steps, and they are on the lobby page.                                                                                                                                                                                                                                                                                                                             |


# I need help!

### I have a question about how to do something in Empirica, where can I ask it?

If you want to ask questions about how to do something in Empirica, get in touch so that you can join the Empirica Slack. Especially the `tech-support-not-bug-report` channel.

### I have a bug/technical issue with Empirica, where should I mention it?

If you encounter a technical issue or a bug with Empirica, please create a GitHub issue [here](https://github.com/empiricaly/meteor-empirica-core/issues).


# The Processes and Elements of an Empirica Experiment

### What is a React.js component?

A React.js component is the main building block of the frontend of your Empirica App. There are many tutorials online to help with your understanding of React.js.

In Empirica, we assign certain components for the Intro Steps, the Round, the Exit Steps, and a few other elements of the Game.

A component is composed of:

* **states** that affect what is rendered for the user, but that can also be changed by the user interacting with the rendered elements of the app.
* **props** provided from other components that can be used to determine what is rendered for the user.
* **other components** that it imports and builds into what it renders for the user.
* a **render function** that determines what is shown to the user with a mix of HTML (with `<> tags`) and JavaScript (with `{}`).

Each component is generally made into one `.jsx` file. Components can be imported into each other to build more complex components. Usually, the type of components used in Empirica are **class-based**.

A major perk of React.js components is that whenever one of their states change (e.g., because of the action of user), it will **refresh every component** **affected** and update what is rendered depending on the new states. This makes for web apps that live update what they look like and do. This is particularly useful for Empirica because you want to update what you show to players depending on states such as which responses they have given, which stage of the Game they are at, what other players are doing, etc.

Hence, there are some elements of a component you might want to render differently depending on certain props and states. You can use syntax such as `{ condition ? true : false }`or `{ condition && true}` where *condition* is a condition that is tested, *true* is what is rendered if this condition tests true, and *false* is what is rendered if this condition tests false.

A component might look like this:

```jsx
// Importing elements and other components
import React, { Component } from 'react'
import GivingResponse from './GivingResponse'

export default class Questionnaire extends Component {
    // The state of the questionnaire
    state = {
        showHint: false
    }

    // Handling if the player clicks to show hint (toggles the hint on and off)
    handleShowHint = () => {
        this.setState({ showHint: !this.state.showHint })
    }

    render() {

        // Getting the props
        const { player } = this.props;

        return (
            <div>
                <p> What is the name of the first person to set foot on the moon?</p>

                {/* A button that affects the conditional that
                 determines whether to show the hint or not */}
                <button onClick={this.handleShowHint()}>Show hint</button>
                {this.state.showHint && <p className="hintcolour">He was American.</p>}

                {/* Importing another component for the player to give their answer.
                 We pass down the prop of the player */}
                <GivingResponse player={player} />
            </div>
        )
    }
}
```

### How can I get rid of the "Waiting on the other players. Please wait until all players are ready"?

This is not something directly specific to Empirica, it's just how the basic template is set up.

&#x20;As shown [here](/overview/lifecycle/customising-when-players-submit-stages), it is possible to use the information that a Player has submitted their Stage to render something different than before they submit their Stage. In template, this happens in the `TaskResponse.jsx`.  You can see that two **render functions** have been created: `renderSubmitted()` and `renderInput()`. In the `render()` part of the component, you can see that there is an **if conditional** that determines whether the render function used will be `renderSubmitted()`, which will prevent the `renderSubmitted()` from being called (and thereby hiding the slider and method of response from the player):

```jsx
render() {
    const { player } = this.props;

    // If the player already submitted, don't show the slider or submit button
    if (player.stage.submitted) {
      return this.renderSubmitted();
    }

    return (
      <div className="task-response">
        <form onSubmit={this.handleSubmit}>
          {this.renderInput()}
          {" "}
          <button type="submit">Submit</button>
        </form>
      </div>
    );
  }
```

You can get rid of this message by taking out the **if conditional**, or changing what `renderSubmitted()` does.

### How can I redirect a player if I detect they are using a certain browser or a mobile device?

You might not want players to join your game from a mobile or tablet, nor from certain browsers. To do so you can use [react-device-detect](https://www.npmjs.com/package/react-device-detect) and modify the first page of your experiment (e.g., the consent page, the NewPlayer page, or the first page of your Intro Steps) to prevent them from continuing the experiment if you detect the device or browser that you do not want.

To install react-device-detect use:

```
meteor npm install react-device-detect
```

react-device-detect has different Booleans that you can import and use in one of your components to detect whether the player is using a certain browser.

* isMobile for whether they are using a mobile device
* isChrome for whether they are using Chrome
* isFirefox for whether they are using Firefox
* isSafari for whether they are using Safari
* ...

And others than you can find out about [here](https://www.npmjs.com/package/react-device-detect).

Import them into the component with:

```
import { isMobile, isFirefox, isSafari, isChrome } from 'react-device-detect';
```

For example, if you want to render a different consent form if the player is using a mobile device or is not using Chrome:

```jsx
return !isMobile && isChrome ?
(
    <div>This is the consent form...</div>
) :
(
    <div>Please use a computer and Chrome.</div>
)
```

### How can I show a different Exit Step to players depending on whether they have finished the game or if the game was cancelled/had a problem?

In the `client/main.js` you set which components form the **Exit Steps** with `Empirica.exitSteps()`. You can use the `player.exitStatus` to separate out whether they have finished the game or if they were sent to the exit steps because the game was cancelled/had an issue and send them to different Exit Steps.

For example:

```jsx
Empirica.exitSteps((game, player) => {
    return player.exitStatus === "finished"
        ? [PostSurvey, Thanks]
        : [Sorry];
});
```

### Can players navigate back and forth between the Exit Steps?

For now, players cannot navigate back and forth between the Exit Steps.&#x20;

Each Exit Step has a name set by `static stepName = "";` and players can only move from one Exit Step to the next if the component has an element (e.g., a button) that will call the `onSubmit` prop. For example:

```jsx
<button type="button" onClick={onSubmit}>
    Finish this experiment
</button>
```

If you wanted multiple pages within the Exit Steps that players can navigate through, you could create a component within one Exit Step that has different components to form "pages" and with a state that knows which page it is at and navigating to and from them.

### Can a manually sent a player to an exit step?

You can have a piece of code to manually send a player to an exit stage if they do something (e.g., you want to give them a quit button) by using:

```
player.exit("name of exit step")
```

where the string is the name of the exit stage you want to send them to.

### How can I use bots?

In the `server/bots.js` you can create bots for them to participate in your games.

See [this part](/guides/tutorial-your-first-experiment/part-3-adding-bots) of the tutorial for more details.

```jsx
Empirica.bot("bob", {
  // // NOT SUPPORTED Called at the beginning of each stage (after onRoundStart/onStageStart)
  // onStageStart(bot, game, round, stage, players) {},

  // Called during each stage at tick interval (~1s at the moment)
  onStageTick(bot, game, round, stage, secondsRemaining) {}

  // // NOT SUPPORTED A player has changed a value
  // // This might happen a lot!
  // onStagePlayerChange(bot, game, round, stage, players, player) {}

  // // NOT SUPPORTED Called at the end of the stage (after it finished, before onStageEnd/onRoundEnd is called)
  // onStageEnd(bot, game, round, stage, players) {}
});
```


# Managing Players and Games

### When are players playing synchronously and asynchronously? Can I modify this?

Players are **asynchronous during the Intro Steps** (i.e., they can finish each part at their own pace). At the **lobby**, players have to wait for each other to finish the Intro Steps. Then players are **synchronous during the Game** (i.e., they must all finish a Stage before they can move on to the next Stage or Round). Finally, once all the players have finished the Game, they are **asynchronous again during the Exit Steps**.

It is not recommended to try and modify this aspect of an Empirica app. You should consider what you want players to be doing at their own pace and what you want them to be doing synchronously. Remember that you can use your Treatments to modify how certain aspects of the game are presented throughout the app, and you can set different times for different Stages.

For more information about the life cycle of a game, see [here](/overview/lifecycle).

### Can players leave and re-join the app? Can players refresh the page?

Yes, the browser cache of the player records they Player id and the database records the status and position of the Player, so it knows whether the Player is in the Intro Steps, the Lobby, a specific Round and Stage, or the Exit Steps. If a player refreshes the page or leaves and comes back, they will be sent back to their position.&#x20;

However, remember that in Stages the timer is still ticking and during the Intro Steps other players might be waiting in the lobby; hence, it is not a good idea for players to leave the game.

It can be useful for players to know that they can safely refresh the page in case they have a graphical bug or if the page takes too long to render.

### How can I assign players to different versions of my game based on a condition set outside of the game?

Imagine you have players that have different favourite colors, and you want to create games with one player for each favourite color. This is currently hard to make with Empirica because the players are allocated to a game and then they are asked questions, not the other way round.

One solution could be to create a big game, and ask players their favourite color in the Intro Steps. Then, during the [gameInit()](/overview/lifecycle) you assign participants to subgames. This might be complicated because you might have the wrong proportions of players per color.&#x20;

Another solution is to create the groups outside of Empirica and invite them one group at a time to a game.

### Can I have an idea of what my app would look like in production/deployment on my local machine?

When you launch your meteor app locally, it will look different to what it looks like when players see the deployed version. This is because there are tools that you only to have access to as the designer when the app is running locally on your machine (e.g., `New Player`, `Reset current session`, and `Open Admin` buttons).

If you want to see what your app will look like once deployed, but still run it locally, you can run the app with:

```
meteor --production --settings settings.json
```


# Guess The Correlation

You and a group of friends can play with this experiment as we ran it by following these instructions (assuming you have [Meteor installed](https://www.meteor.com/install)):

1. [Download](https://github.com/amaatouq/guess-the-correlation) the repository (and unzip). Alternatively, from terminal just run:

```
git clone https://github.com/amaatouq/guess-the-correlation.git
```

1. Go into the folder with `cd guess-the-correlation`
2. Install the required dependencies by running `meteor npm install`
3. Edit the `admin` password in the settings file `local.json` to something you like.
4. Run the local instance with `meteor --settings local.json`
5. Go to <http://localhost:3000/admin> (or whatever port you are running Meteor on).
6. login with the credentials username: `admin` and the password you have in `local.json`
7. Start a new batch with whatever configuration you want (see the example configuration).

## Example Config:

First, you have to enter the Configuration mode instead of the Monitoring model in the admin UI.

![](https://github.com/amaatouq/guess-the-correlation/raw/master/readme_screenshots/configuration_mode.png)

This will allow you to configure the experiment: Factors, Lobby, and Treatments:

![](https://github.com/amaatouq/guess-the-correlation/raw/master/readme_screenshots/configuration_mode_inside.png)

Now, you have the option to create your own configuration (see below) or load an example configuration by clicking on `import` and then choosing the file `./example-config.yaml`. Loading the example configurations will choose some example values for the factors (i.e., independent variables), lobby configuration, and few treatments.

The example factors will look like this: ![](https://github.com/amaatouq/guess-the-correlation/raw/master/readme_screenshots/factors_example.png)

And the example treatments will look like this: ![](https://github.com/amaatouq/guess-the-correlation/raw/master/readme_screenshots/treatments_example.png)

Finally, you can go back to the Monitoring mode:

![](https://github.com/amaatouq/guess-the-correlation/raw/master/readme_screenshots/monitoring_mode.png)

Now the ***Batchs*** tab make sure you add a new batch, add the treatments you want, choose your lobby configurations, and then ***start*** the batch.

![](https://github.com/amaatouq/guess-the-correlation/raw/master/readme_screenshots/new_batch.png)

Go to <http://localhost:3000/> and enjoy! If you don't have 3 friends to play with you, you always can use the `new player` button in development (for more details see this), which can add an arbitrary number players to the experiment while staying in the same browser (i.e., no need to open different browsers).

![](https://github.com/amaatouq/guess-the-correlation/raw/master/readme_screenshots/game.png)


# Random Dot Motion

This is an experiment powered by [Empirica](https://empirica.ly/) as a follow-up for the model developed in [Moussaïd M et al. (2018) Dynamical networks of influence in small group discussions](http://journals.plos.org/plosone/article?id=10.1371/journal.pone.0190541).

## Experiment Details:

### The task

In this experiment, groups of N=3 participants simultaneously undertake a visual perception task similar to the one implemented in [Moussaïd, et al. (2017). Reach and speed of judgment propagation in the laboratory, PNAS](http://www.pnas.org/content/early/2017/03/28/1611998114.short). Participants are exposed to visual stimuli consisting of a set of moving dots. A proportion of correlated dots move in a specific direction θ, and the remaining proportion of uncorrelated dots moved in random directions. Here, θ is the true value that participants have to estimate visually. The value of θ is the same for all the group members.

![](https://www.researchgate.net/profile/Jiaxiang_Zhang/publication/230624328/figure/fig1/AS:214158353145856@1428070738125/Schematic-diagram-of-the-RDM-stimulus-with-different-motion-coherence-levels-In-each.png)

In the planned experiment, each group undertakes a series of “discussions” (each discussion is a `Round` from the point of view of Empirica). Within a given discussion round, the true value of θ remains unchanged. Each participant is given the chance to speak 3 times within a single discussion. Therefore, a single discussion round consists of 9 speaking stages (3 players each speaking 3 times), during which the participants share their current estimate with the rest of the group.

Calling A, B, and C the three participants. One discussion (the stimuli is always displayed on the participants’ screens) goes as follows:

1. Stage 1
2. A, B, and C enter their estimate
3. The estimate of A is displayed on all screens
4. Stage 2
5. A, B, and C can revise their estimate
6. The new estimate of B is displayed on all screens
7. Stage 3
8. A, B, and C can again revise their estimate
9. The estimate of C is displayed on all screens ... ...
10. Stage 9
11. The experiment continues until stage 9 is reached (i.e., everyone spoke 3 times)...
12. Stage 10
13. A summary of the scores that all participants have made in each stage is displayed on the screens.
14. A new discussion round (with a different true value θ) starts.

We set 9 speaking stages per discussion round and NR=20 discussion rounds per group.

### Speaking turns

The sequence of speaking turns determines which estimate is communicated at a given stage. It is generated using a simple random procedure: For each block of 3 stages, the speaking order is a random permutation of the 3 participants. That is, each participant speaks one and only one time in each block. With 9 speaking rounds, we have three blocks. Each participant thus speaks 3 times during the discussion round, as we mentioned earlier.

### Difficulty level

We vary the difficulty of the task between participants. That is, some group members will face an easy task — with a high proportion of correlated dots (e.g., 60%), whereas others will face a difficult task with a low proportion of correlated dots (e.g., 10%). The value of θ is the same for all the group members, irrespective of the difficulty level.

The difficulty level is fixed for the entire duration of the experiment.

## Experiment Demo:

You and a group of friends can play with this experiment as we ran it by following these instructions (assuming you have [Meteor installed](https://www.meteor.com/install)):

1. [Download](https://github.com/amaatouq/small-group-discussion) the repository (and unzip). Alternatively, from terminal just run:

```
git clone https://github.com/amaatouq/small-group-discussion
```

1. Go into the folder with `cd small-group-discussions`
2. Install the required dependencies `meteor npm install`
3. Edit the `admin` password in the settings file `local.json` to something you like.
4. Run the local instance with `meteor --settings local.json`
5. Go to <http://localhost:3000/admin> (or whatever port you are running Meteor on).
6. login with the credentials username: `admin` and the password you have in `local.json`
7. Start a new batch with whatever configuration you want (see the example configuration).

### Example Config:

First, you have to enter the Configuration mode instead of the Monitoring model in the admin UI.

![](https://github.com/amaatouq/small-group-discussion/raw/master/readme_screenshots/configuration_mode.png) This will allow you to configure the experiment: Factors, Lobby, and Treatments:

![](https://github.com/amaatouq/small-group-discussion/raw/master/readme_screenshots/configuration_mode_inside.png)

Now, you have the option to create your own configuration (see below) or load an example configuration by clicking on `import` and then choosing the file `./example-config`. Loading the example configurations will choose some example values for the factors (i.e., independent variables), lobby configuration, and few treatments.

The example factors will look like this: ![](https://github.com/amaatouq/small-group-discussion/raw/master/readme_screenshots/factors_example.png)

And the example treatments will look like this: ![](https://github.com/amaatouq/small-group-discussion/raw/master/readme_screenshots/treatments_example.png)

Finally, you can go back to the Monitoring mode:

![](https://github.com/amaatouq/small-group-discussion/raw/master/readme_screenshots/monitoring_mode.png)

Now the ***Batchs*** tab make sure you add a new batch, add the treatments you want, choose your lobby configurations, and then ***start*** the batch.

![](https://github.com/amaatouq/small-group-discussion/raw/master/readme_screenshots/new_batch.png)

Go to <http://localhost:3000/> and enjoy! If you don't have 3 friends to play with you, you always can use the `new player` button in development (for more details see this), which can add an arbitrary number players to the experiment while staying in the same browser (i.e., no need to open different browsers).

![](https://github.com/amaatouq/small-group-discussion/raw/master/readme_screenshots/game.png)


# Room Assignment

This is an experiment powered by [Empirica](https://github.com/empiricaly/empirica). Through this experiment we attempt to answer the question: **How does team composition affect team performance?**

## Experiment Details:

### The task

In this experiment, participants are asked to assign N students into M rooms to maximize utility while respecting certain constraints. The task difficulty can vary in complexity levels:

* High complexity: Assign 9 students to 6 rooms given 8 constraints
* Low complexity: Assign 6 students to 4 rooms given 2 constraints

When the task is performed in groups then:

* All participants can do the assignment simultaneously, however, ony one

  student can be moved by one player at any given time (i.e., locking the

  student being moved, but the others are free to be moved).
* Participants can chat freely using the in-experiment chatting system.
* All events (i.e., which student being assigned to which room etc) will be

  logged and announced in the experiment as they happen.

### Procedure

In the planned experiment, **in step 1** each participants will be asked to complete a number of room assignment tasks and other test questions (e.g., read emotions from eyes tests) individually. This will allow us to determine 3 attributes about the individual:

* Ability: measured by the performance in the game.
* Social Perceptiveness (SP): Measured through

  [Reading Emotions from Eye (RME)](https://github.com/amaatouq/RME_test) test.
* Cognitive Style (CS): an in-task measure of problem-solving style (e.g.,

  intuitive versus analytical).

Then, **in step 2**, we randomly construct teams of 3 participants.

## Experiment Demo:

You and a group of friends can play with this experiment as we ran it by following these instructions (assuming you have [Meteor installed](https://www.meteor.com/install)):

1. [Download](https://github.com/amaatouq/room-assigment.git) the repository (and unzip). Alternatively, from terminal just run:

```
git clone https://github.com/amaatouq/room-assigment
```

1. Go into the folder with `cd room-assigment`
2. Install the required dependencies `meteor npm install`
3. Edit the `admin` password in the settings file `local.json` to something you like.
4. Run the local instance with `meteor --settings local.json`
5. Go to <http://localhost:3000/admin> (or whatever port you are running Meteor on).
6. login with the credentials username: `admin` and the password you have in `local.json`
7. Start a new batch with whatever configuration you want (see the example configuration).

### Example Config:

First, you have to enter the Configuration mode instead of the Monitoring model in the admin UI.

![](https://raw.githubusercontent.com/amaatouq/room-assigment/master/readme_screenshots/configuration_mode.png)

This will allow you to configure the experiment: Factors, Lobby, and Treatments. Now, you have the option to create your own configuration (see below) or load an example configuration by clicking on `import` and then choosing the file `./example-config.yaml`. Loading the example configurations will choose some example values for the factors (i.e., independent variables), lobby configuration, and few treatments.

Now, you can go back to the Monitoring mode:

![](https://raw.githubusercontent.com/amaatouq/room-assigment/master/readme_screenshots/monitoring_mode.png)

Now the ***Batchs*** tab make sure you add a new batch, add the treatments you want, choose your lobby configurations, and then ***start*** the batch.

![](https://raw.githubusercontent.com/amaatouq/room-assigment/master/readme_screenshots/new_batch.png)

Go to <http://localhost:3000/> and enjoy! If you don't have 3 friends to play with you, you always can use the `new player` button in development (for more details see this), which can add an arbitrary number players to the experiment while staying in the same browser (i.e., no need to open different browsers).

![](https://raw.githubusercontent.com/amaatouq/room-assigment/master/readme_screenshots/game.png)


# Helpful Linux Commands

Here is a list of helpful commands that should enhance your experience with the command line in Linux and WSL.

## Commands

To find in which directory you currently are, use:

```
pwd
```

To list all the files and folders in your directory, use:

```
ls
```

To navigate between directories use *cd* followed by the path or name of the directory you want to access. If you start typing a location that is present in your current directory, you can then use the TAB key to autocomplete the name of a directory.

```
cd <directory>
```

To go up one directory, use:

```
cd ..
```

To go back to the root (*/home/\<user>*), use:

```
cd ~
```

To delete a file, use:

```
rm <filename>
```

To delete a directory, use:

```
rm -r <directoryname>
```

Now that you have run multiple commands, and that you will be launching Empirica apps, there are a few useful tricks you should know:

* Use **ctrl+l** to clear your command line.
* Use **ctrl+c** to cancel (whilst writing it) or interrupt (when it is running) a command.

## Tips for Windows WSL users

### Viewing, accessing, and modifying your files

If you correctly installed WSL 2, you can view, access, and modify the files and folders in your WSL directly from your explorer. To open up the WSL in your explorer use:

```
explorer.exe .
```

Nevertheless, you will also need to get accustomed to using the command line to navigate in, and use, the the files and folders in your WSL directory. Here are some useful commands.

{% hint style="info" %}
Head over to our Code Editors advice page to find out how to use our recommended code editor with Windows WSL:
{% endhint %}


# Code Editors

There are multiple code editors that you could use in when creating your Empirica apps. Here we share some information about Editors/IDEs we use and recommend.

## VS Code

Visual Studio Code (VS Code) is a cross-platform editor from Microsoft. It has a plethora of features, built-in tools, and plugins to help your write and debug your Empirica code. And it is particularly easy to install, launch, and use.

To get started, head over to <https://code.visualstudio.com/download>, download the installer, and follow the instructions. That's it's you're ready to go.

{% hint style="info" %}

#### On Windows with WSL

You first need to install it on your normal Windows machine as instructed above. Then you need to get this extension install on your VS Code: <https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl>

Once this is done, you can easily launch VS Code from the command line in your WSL with:

```
code <directory>
```

Or if you want to open the directory you are currently in with VS Code you can use:

```
code .
```

{% endhint %}


