Special Empirica Elements (and how to modify them)
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:
<Centered>
<div> Other elements </div>
</Centered>
There is a
Timer.jsx
component that represents the stage timer and shows players how much time is left at that stage. 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: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));
. Here is the code for a basic Timer component:
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));
The About section is a small window that will upon when players click the top right corner button
About
. For example:In
client/main.js
you can set your custom component for the About section. 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.The Header is the blue rectangle at the top of the page in an Empirica app.
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);
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: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:
export default class Round extends Component {
render() {
const { round, stage, player, game } = this.props
return (
<DevWrapper {...this.props}>
<div>
The Rounds
</div>
</DevWrapper>
)
}
}
The Breadcrumb is the track at the top of a Round that shows the player which Stage of the Round they are currently at.
In
client/main.js
you can set your custom component for the Breadcrumb. 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);
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.
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:
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>);
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 expectsgameLobby.queuedCount
will give you the total number of players queued for this game, including ready players and players currently going through the intro steps.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.
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>);
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.
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.
First, install Empirica Chat with:
meteor npm install --save @empirica/chat
In the components you want to use the chat, import this:
import { Chat } from "@empirica/chat";
Then you can create the chat component with:
<Chat player={player} scope={game} />
chat
expects 2 required props:player
: the current playerscope
: object that the chat will be attached to, can be game, round, or stage objects.
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:
const chat = round.get("chat") ?? []
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.<Chat player={player} scope={game} customKey="casual_chat" />
Chat
also displays a name for each participant, which you need to set in the experiment independently of the playerId
: player.set('name', "myPseudonym")
You can pass an optional
timeStamp
date prop to add the timestamp attribute on each message sent. 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:
// reactive time value only updates at 1000 ms
const timeStamp = new Date(TimeSync.serverTime(null, 1000));
<Chat player={player} scope={game} timeStamp={timeStamp} />
Last modified 2yr ago