Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/classes/factories/ScreenPropFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,16 @@ class ScreenPropFactory implements Factory {
}
break;

case "statusPreview":
// Setup the props
returned.props = {
trial: this.trial.trial,
display: this.trial.display,
isPartnerHighStatus: this.trial.isPartnerHighStatus,
handler: this.handler.callback.bind(this.handler),
};
break;

// Loading screen
case "loading":
if (this.trial.loadingType === "social") {
Expand Down
126 changes: 27 additions & 99 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -836,39 +836,6 @@ timeline.push({
},
});

// Insert instructions if the participant will be shown their status
if (Configuration.manipulations.enableStatusPhaseOne === true) {
timeline.push({
type: "instructions",
pages: [
react2html(
<Grommet>
<Box style={{ maxWidth: "50%", margin: "auto" }}>
<Heading level={1} margin="small" fill>
Instructions
</Heading>
<Heading level={2} margin="small" fill>
Stage One
</Heading>
<Paragraph margin="small" size="large" fill>
In the next phase, you will be able to see your partner&#39;s social
standing in comparison to your own.
</Paragraph>
<Paragraph margin="small" size="large" fill>
Press &#39;Next &gt;&#39; to continue.
</Paragraph>
</Box>
</Grommet>
),
],
allow_keys: Configuration.manipulations.useButtonInput,
key_forward: BINDINGS.NEXT,
key_backward: BINDINGS.PREVIOUS,
show_page_number: true,
show_clickable_nav: true,
});
}

// Insert instructions to let the participant know they will
// be matched with a partner
timeline.push({
Expand Down Expand Up @@ -914,6 +881,15 @@ timeline.push({
loadingType: "matchingIntentions",
});

// Insert `statusPreview` screen if the participant will be shown their status
if (Configuration.manipulations.enableStatusPhaseOne === true) {
timeline.push({
type: Configuration.studyName,
display: "statusPreview",
isPartnerHighStatus: Configuration.manipulations.isPartnerHighStatusPhaseOne,
})
}

// Set and store the data collection
let dataCollection: Row[];

Expand Down Expand Up @@ -1235,39 +1211,6 @@ for (let i = 0; i < dataCollection.length; i++) {
},
});

// Insert instructions if the participant will be shown their status
if (Configuration.manipulations.enableStatusPhaseTwo === true) {
timeline.push({
type: "instructions",
pages: [
react2html(
<Grommet>
<Box style={{ maxWidth: "50%", margin: "auto" }}>
<Heading level={1} margin="small" fill>
Instructions
</Heading>
<Heading level={2} margin="small" fill>
Stage Two
</Heading>
<Paragraph margin="small" size="large" fill>
In the next phase, you will be able to see your partner&#39;s social
standing in comparison to your own.
</Paragraph>
<Paragraph margin="small" size="large" fill>
Press &#39;Next &gt;&#39; to continue.
</Paragraph>
</Box>
</Grommet>
),
],
allow_keys: Configuration.manipulations.useButtonInput,
key_forward: BINDINGS.NEXT,
key_backward: BINDINGS.PREVIOUS,
show_page_number: true,
show_clickable_nav: true,
});
}

// Insert instructions to let the participant know they will
// be matched with a partner
timeline.push({
Expand Down Expand Up @@ -1313,6 +1256,15 @@ for (let i = 0; i < dataCollection.length; i++) {
loadingType: "matchingIntentions",
});

// Insert `statusPreview` screen if the participant will be shown their status
if (Configuration.manipulations.enableStatusPhaseTwo === true) {
timeline.push({
type: Configuration.studyName,
display: "statusPreview",
isPartnerHighStatus: Configuration.manipulations.isPartnerHighStatusPhaseTwo,
})
}

break;
}
case "mid2": {
Expand Down Expand Up @@ -1451,39 +1403,6 @@ for (let i = 0; i < dataCollection.length; i++) {
},
});

// Insert instructions if the participant will be shown their status
if (Configuration.manipulations.enableStatusPhaseThree === true) {
timeline.push({
type: "instructions",
pages: [
react2html(
<Grommet>
<Box style={{ maxWidth: "50%", margin: "auto" }}>
<Heading level={1} margin="small" fill>
Instructions
</Heading>
<Heading level={2} margin="small" fill>
Stage Three
</Heading>
<Paragraph margin="small" size="large" fill>
In the next phase, you will be able to see your partner&#39;s social
standing in comparison to your own.
</Paragraph>
<Paragraph margin="small" size="large" fill>
Press &#39;Next &gt;&#39; to continue.
</Paragraph>
</Box>
</Grommet>
),
],
allow_keys: Configuration.manipulations.useButtonInput,
key_forward: BINDINGS.NEXT,
key_backward: BINDINGS.PREVIOUS,
show_page_number: true,
show_clickable_nav: true,
});
}

timeline.push({
type: "instructions",
pages: [
Expand Down Expand Up @@ -1529,6 +1448,15 @@ for (let i = 0; i < dataCollection.length; i++) {
loadingType: "matchingIntentions",
});

// Insert `statusPreview` screen if the participant will be shown their status
if (Configuration.manipulations.enableStatusPhaseThree === true) {
timeline.push({
type: Configuration.studyName,
display: "statusPreview",
isPartnerHighStatus: Configuration.manipulations.isPartnerHighStatusPhaseThree,
})
}

break;
}
case "playerGuess": {
Expand Down
7 changes: 6 additions & 1 deletion src/view/components/Wrapper/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ import Status from "../../screens/Questionnaires/Status";
import DASS from "../../screens/Questionnaires/DASS";
import Screentime from "../../screens/Questionnaires/Screentime";
import Demographics from "../../screens/Questionnaires/Demographics";
import Loaded from "../../screens/Loaded";
import Loading from "../../screens/Loading";
import Loaded from "../../screens/Loaded";
import StatusPreview from "src/view/screens/StatusPreview";
import Waiting from "../../screens/Waiting";
import End from "../../screens/End";
import Resources from "../../screens/Resources";
Expand Down Expand Up @@ -134,6 +135,10 @@ const Wrapper: FC<Props.Components.Wrapper> = (

{activeDisplay === "loaded" && <Loaded {...(props.props as Props.Screens.Loaded)} />}

{activeDisplay === "statusPreview" && (
<StatusPreview {...(props.props as Props.Screens.StatusPreview)} />
)}

{activeDisplay === "loading" && (
<Loading {...(props.props as Props.Screens.Loading)} />
)}
Expand Down
76 changes: 76 additions & 0 deletions src/view/screens/StatusPreview/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* @file `StatusPreview` screen to show participants their partner's social standing.
*
* This screen displays the partner's social standing to participants
* at the start of a game phase. Key features include:
* - Partner social standing presentation
* - Partner avatar presentation
*
* @author Henry Burgess <henry.burgess@wustl.edu>
*/

// React import
import React, { FC, ReactElement } from "react";

// Grommet UI components
import { Box, Button, Layer, Paragraph } from "grommet";
import { LinkNext } from "grommet-icons";
import Status from "src/view/components/Status";
import Avatar from "boring-neutral-avatars";

// Configuration
import { Configuration } from "src/configuration";

/**
* @summary Generate a 'StatusPreview' screen containing a card with the partner avatar for the subsequent phase of the game
* @param {FC} props Props object containing:
* - isPartnerHighStatus: {boolean} Whether the partner is in high status
* - handler: {function} Function to handle the continue button click
* @return {ReactElement} 'StatusPreview' screen with partner avatar and success message
*/
const Loaded: FC<Props.Screens.StatusPreview> = (props: Props.Screens.StatusPreview): ReactElement => {
// Get the current partner avatar and social standing
const experiment = window.Experiment;
const partnerStatus = props.isPartnerHighStatus ? experiment.getState().get("partnerHighStatus") : experiment.getState().get("partnerLowStatus");

// Get the updated partner avatar
const partnerAvatar = Configuration.avatars.names.partner[
experiment.getState().get("partnerAvatar")
]

return (
<Layer plain full>
<Box justify="center" align="center" gap="small" responsive fill>
<Paragraph margin="small" size="large" fill>
In this phase you will be able to see your partner&apos;s social standing.
</Paragraph>
<Avatar
size={100}
name={partnerAvatar}
variant={Configuration.avatars.variant as "beam"}
colors={Configuration.avatars.colours}
/>
<Status
participantStatus={experiment.getState().get("participantDefaultStatus")}
partnerStatus={partnerStatus}
/>
<Paragraph margin="small" size="large" fill>
Their ID has been hidden to preserve anonymity.
</Paragraph>
<Button
a11yTitle="Continue"
primary
color="button"
label="Continue"
icon={<LinkNext />}
reverse
onClick={() => {
props.handler();
}}
/>
</Box>
</Layer>
);
};

export default Loaded;
6 changes: 3 additions & 3 deletions src/view/screens/Trial/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -198,19 +198,19 @@ const Trial: FC<Props.Screens.Trial> = (
// If status display is enabled, interpret and apply the manipulations
if (
props.display === "playerChoice" &&
Configuration.manipulations.enableStatusPhaseOne
Configuration.manipulations.isPartnerHighStatusPhaseOne
) {
// Phase One: If `isHighStatusPhaseOne` is true, then the participant is low status and the partner is high status
partnerStatus = experiment.getState().get("partnerHighStatus");
} else if (
props.display === "playerGuess" &&
Configuration.manipulations.enableStatusPhaseTwo
Configuration.manipulations.isPartnerHighStatusPhaseTwo
) {
// Phase Two: If `isHighStatusPhaseTwo` is true, then the participant is low status and the partner is high status
partnerStatus = experiment.getState().get("partnerHighStatus");
} else if (
props.display === "playerChoice2" &&
Configuration.manipulations.enableStatusPhaseThree
Configuration.manipulations.isPartnerHighStatusPhaseThree
) {
// Phase Three: If `isHighStatusPhaseThree` is true, then the participant is low status and the partner is high status
partnerStatus = experiment.getState().get("partnerHighStatus");
Expand Down
8 changes: 7 additions & 1 deletion types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ declare type Display =
| "mid2"
| "playerGuess"
| "playerGuessPractice"
| "loaded"
| "loading"
| "loaded"
| "statusPreview"
| "selection"
| "inference"
| "agency"
Expand Down Expand Up @@ -104,6 +105,11 @@ declare type Trial = {
// Loading screen configuration (used by Loading screen)
loadingType?: "matchingIntentions" | "matchingCyberball" | "social" | "default"; // Type of loading: "matchingIntentions" (partner matching), "matchingCyberball" (cyberball partners), "social" (status generation), or "default" (generic loading)
fetchData: boolean; // Whether to fetch data from server (only used when loadingType is "matchingIntentions")

// Status preview screen configuration (used by StatusPreview screen)
isPartnerHighStatus?: boolean; // Used for the `StatusPreview` screen

// Waiting screen configuration (used by Waiting screen)
mode: "facilitator" | "mri";

// Spotlight configuration (used by Trial screen)
Expand Down
3 changes: 2 additions & 1 deletion types/jsPsych.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ declare type TimelineNode = {
message: string;
};

// Matching screen
// Loading and loaded screens
fetchData?: boolean;
loadingType?: "matchingIntentions" | "matchingCyberball" | "social" | "default";
isPartnerHighStatus?: boolean;

// Waiting screen
mode?: "facilitator" | "mri";
Expand Down
6 changes: 6 additions & 0 deletions types/props.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,12 @@ declare namespace Props {
) => void;
};

// Status preview screen
type StatusPreview = GenericScreenProps & {
isPartnerHighStatus: boolean;
handler: () => void;
};

// DASS screen
type DASS = GenericScreenProps & {
version: "adult" | "adolescent";
Expand Down