Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added video several keyboard responses plugin #83

Merged
merged 6 commits into from
Dec 20, 2023
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
5 changes: 5 additions & 0 deletions .changeset/plugin-video-several-keyboard-responses.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@jspsych/plugin-video-several-keyboard-responses": major
---

Added video plugin based on video-keyboard-response plugin that allows for multiple responses and records video time
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Plugin/Extension | Contributor | Description
[rdk](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-rdk/docs/jspsych-rdk.md#jspsych-rdk-plugin) | [Sivananda Rajananda](https://github.com/vrsivananda) | This plugin displays a Random Dot Kinematogram (RDK) and allows the subject to report the primary direction of motion by pressing a key on the keyboard.
[rok](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-rok/docs/jspsych-rok.md#jspsych-rok-plugin) | [Younes Strittmatter](https://github.com/younesStrittmatter) | This plugin displays a Random Object Kinematogram (ROK) and allows the subject to report the primary direction of motion or the primary orientation by pressing a key on the keyboard.
[self-paced-reading](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-self-paced-reading/docs/jspsych-self-paced-reading.md) | [@igmmgi](https://github.com/igmmgi) | Self-paced reading tasks with different display options.
[video-several-keyboard-responses](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-video-several-keyboard-responses/docs/jspsych-video-several-keyboard-responses.md)|[@marianylund](https://github.com/marianylund) | This plugin is based on [video-keyboard-response](https://github.com/jspsych/jsPsych/tree/main/packages/plugin-video-keyboard-response) with possibility of recording multiple responses together with video timestamps.
[vsl-animate-occlusion](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-vsl-animate-occlusion/docs/jspsych-vsl-animate-occlusion.md#jspsych-vsl-animate-occlusion-plugin) | [Josh de Leeuw](https://github.com/jodeleeuw) | The VSL (visual statistical learning) animate occlusion plugin displays an animated sequence of shapes that disappear behind an occluding rectangle while they change from one shape to another.
[vsl-grid-scene](https://github.com/jspsych/jspsych-contrib/blob/main/packages/plugin-vsl-grid-scene/docs/jspsych-vsl-grid-scene.md#jspsych-vsl-grid-scene-plugin) | [Josh de Leeuw](https://github.com/jodeleeuw) | The VSL (visual statistical learning) grid scene plugin displays images arranged in a grid.

Expand Down
Empty file.
3 changes: 3 additions & 0 deletions packages/plugin-video-several-keyboard-responses/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# @jspsych/plugin-video-several-keyboard-responses


35 changes: 35 additions & 0 deletions packages/plugin-video-several-keyboard-responses/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# plugin-video-several-keyboard-responses

## Overview

This plugin plays a video and records responses generated by the keyboard, based on [plugin-video-keyboard-response](https://www.jspsych.org/latest/plugins/video-keyboard-response). The stimulus can be displayed until the end or for a pre-determined amount of time. In addition to responses and response times, the video time is saved when a response is given using a keyboard.

## Loading

### In browser

```js
<script src="https://unpkg.com/@jspsych-contrib/[email protected]">
```

### Via NPM

```
npm install @jspsych-contrib/plugin-video-several-keyboard-responses
```

```js
import jsPsychVideoSeveralKeyboardResponses from '@jspsych-contrib/plugin-video-several-keyboard-responses';
```

## Compatibility

jsPsych v7.3.4

## Documentation

See [documentation](docs/jspsych-video-several-keyboard-responses.md)

## Author / Citation

This plugin was created by [marianylund](https://github.com/marianylund) with support from the [Department of Psychology](https://www.sv.uio.no/psi/english/index.html) at the University of Oslo.
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# jspsych-self-paced-reading plugin

Based on [video-keyboard-response](https://github.com/jspsych/jsPsych/tree/main/packages/plugin-video-keyboard-response) plugin, this plugin allows playing video and recording multiple responses together with video timestamps.

## Parameters

In addition to the [parameters available in all plugins](https://www.jspsych.org/overview/plugins#parameters-available-in-all-plugins) and [video-keyboard-response](https://github.com/jspsych/jsPsych/blob/main/docs/plugins/video-keyboard-response.md) plugin, this plugin accepts the following parameters. Parameters with a default value of _undefined_ must be specified. Other parameters can be left unspecified if the default value is acceptable.

| Parameter | Type | Default Value | Description |
| -------------------------- | ---- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| multiple_responses_allowed | bool | true | If true, multiple responses are recorded. If false, only the first response will be recorded, thus behaving as video-keyboard-response plugin. |

## Data Generated

In addition to the [default data collected by all plugins](https://www.jspsych.org/overview/plugins#data-collected-by-all-plugins), this plugin collects the following data for each trial.

| Name | Type | Value |
| ---------- | -------- | ---------------------------------------------------------------- |
| video_time | number[] | Array of playback positions of video when response was given (s) |

## Example

```javascript
const trial = {
type: VideoSeveralKeyboardResponsesPlugin,
stimulus: ['video/sample_video.mp4'],
choices: "ALL_KEYS",
prompt: "Press any keys",
width: 600,
autoplay: true,
trial_ends_after_video: true,
response_ends_trial: false,
response_allowed_while_playing: true,
multiple_responses_allowed: true,
};
```
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require("@jspsych/config/jest").makePackageConfig(__dirname);
44 changes: 44 additions & 0 deletions packages/plugin-video-several-keyboard-responses/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"name": "@jspsych/plugin-video-several-keyboard-responses",
"version": "0.1.0",
"description": "jsPsych plugin for playing a video file and getting several keyboard responses",
"type": "module",
"main": "dist/index.cjs",
"exports": {
"import": "./dist/index.js",
"require": "./dist/index.cjs"
},
"typings": "dist/index.d.ts",
"unpkg": "dist/index.browser.min.js",
"files": [
"src",
"dist"
],
"source": "src/index.ts",
"scripts": {
"test": "jest --passWithNoTests",
"test:watch": "npm test -- --watch",
"tsc": "tsc",
"build": "rollup --config",
"build:watch": "npm run build -- --watch"
},
"repository": {
"type": "git",
"url": "git+https://github.com/jspsych/jspsych-contrib.git",
"directory": "packages/plugin-video-several-keyboard-responses"
},
"author": "Maria Emine Nylund",
"license": "MIT",
"bugs": {
"url": "https://github.com/jspsych/jspsych-contrib/issues"
},
"homepage": "https://github.com/jspsych/jspsych-contrib/tree/main/packages/plugin-video-several-keyboard-responses",
"peerDependencies": {
"jspsych": ">=7.1.0"
},
"devDependencies": {
"@jspsych/config": "^2.0.0",
"@jspsych/test-utils": "^1.1.2",
"jspsych": "^7.1.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { makeRollupConfig } from "@jspsych/config/rollup";

export default makeRollupConfig("jsPsychVideoSeveralKeyboardResponses");
82 changes: 82 additions & 0 deletions packages/plugin-video-several-keyboard-responses/src/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { pressKey, simulateTimeline, startTimeline } from "@jspsych/test-utils";
import { initJsPsych } from "jspsych";

import videoSeveralKeyboardResponses from ".";

jest.useFakeTimers();

beforeAll(() => {
window.HTMLMediaElement.prototype.pause = () => {};
});

// I can't figure out how to get this tested with jest
describe("video-several-keyboard-responses", () => {
test("throws error when stimulus is not array #1537", async () => {
const jsPsych = initJsPsych();

const timeline = [
{
type: videoSeveralKeyboardResponses,
stimulus: "foo.mp4",
},
];

await expect(async () => {
await jsPsych.run(timeline);
}).rejects.toThrowError();
});
});

describe("video-several-keyboard-responses simulation", () => {
test("data mode works", async () => {
const timeline = [
{
type: videoSeveralKeyboardResponses,
stimulus: ["foo.mp4"],
},
];

const { expectFinished, getData } = await simulateTimeline(timeline);

await expectFinished();

expect(getData().values()[0].rt).toBeGreaterThan(0);
expect(typeof getData().values()[0].response).toBe("string");
});

// can't run this until we mock video elements.
test("visual mode works", async () => {
const jsPsych = initJsPsych();

const timeline = [
{
type: videoSeveralKeyboardResponses,
stimulus: ["foo.mp4"],
prompt: "foo",
trial_duration: 1000,
},
];

const { expectFinished, expectRunning, getHTML, getData } = await simulateTimeline(
timeline,
"visual",
{},
jsPsych
);

await expectRunning();

expect(getHTML()).toContain("foo");

jest.runAllTimers();

await expectFinished();

const rt = getData().values()[0].rt;
const response = getData().values()[0].response;
const video_time = getData().values()[0].video_time;
expect(rt.every(value => value > 0)).toBe(true);
expect(response.every(value => typeof value === "string")).toBe(true);
expect(video_time.every(value => typeof value === "number")).toBe(true);
});
});
Loading