Skip to content

Commit

Permalink
Updating authorsmap methods to be more concise, implemented interface…
Browse files Browse the repository at this point in the history
… to track fields, created more robust error warnings and tested functionality fixing author errors
  • Loading branch information
vzhang03 committed Jun 12, 2024
1 parent 27c099d commit ed76a3b
Show file tree
Hide file tree
Showing 5 changed files with 359 additions and 60 deletions.
10 changes: 7 additions & 3 deletions examples/timeline-variables.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,19 @@
},
"Darnell": {
givenName: "bob",
}
},
"Bob": "Bob",
"Ostrich": {
bbq: 10,
},
},
variables: {
"trial_type" : {
description: {
"chat-plugin": "this chat plugin allows you to talk to gpt!",
}
},
"rt" : "adfasfajskf;ajdfddas",
// "rt" : "adfasfajskf;ajdfddas",
"time_elapsed": {
bbq: "indicates the number of barbeques",
description: {
Expand All @@ -49,7 +53,7 @@

var jsPsych = initJsPsych({
on_finish: async function() {
await metadata.generate(jsPsych.data.get().json());
await metadata.generate(jsPsych.data.get().json(), metadata_options);
// metadata.saveAsJsonFile();
jsPsych.data.displayData();
metadata.displayMetadata(jsPsych.getDisplayElement());
Expand Down
82 changes: 47 additions & 35 deletions packages/metadata/src/AuthorsMap.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
/**
* Interface that defines the type for the fields that are specified for authors
* according to Psych-DS regulations, with name being the one required field.
*
* @export
* @interface AuthorFields
* @typedef {AuthorFields}
*/
export interface AuthorFields {
type?: string;
name: string;
givenName?: string; // required
familyName?: string;
identifier?: string; // identifier that distinguishes across datasets (URL), confusing should check description
}

/**
* Class that helps keep track of authors and allows for easy conversion to list format when
* generating the final Metadata file.
Expand All @@ -11,9 +27,9 @@ export class AuthorsMap {
* Field that keeps track of the authors in a map.
*
* @private
* @type {({ [key: string]: {} | string })}
* @type {({ [key: string]: AuthorFields | string })}
*/
private authors: { [key: string]: {} | string }; // Define the type for authors
private authors: { [key: string]: AuthorFields | string };

/**
* Creates an empty instance of authors map. Doesn't generate default metadata because
Expand All @@ -28,9 +44,9 @@ export class AuthorsMap {
/**
* Returns the final list format of the authors according to Psych-DS standards.
*
* @returns {({} | string)[]} - List of authors
* @returns {(AuthorFields | string)[]} - List of authors
*/
getList(): ({} | string)[] {
getList(): (AuthorFields | string)[] {
const author_list = [];
for (const key of Object.keys(this.authors)) {
author_list.push(this.authors[key]);
Expand All @@ -42,49 +58,45 @@ export class AuthorsMap {
* Method that creates an author. This method can also be used to overwrite existing authors
* with the same name in order to update fields.
*
* @param {{
* type?: string;
* name: string;
* givenName?: string; // required
* familyName?: string;
* identifier?: string; // identifier that distinguish across dataset (URL), confusing should check description
* }} fields - All the required or possible fields associated with listing an author according to Psych-DS standards.
* @param {AuthorFields | string} author - All the required or possible fields associated with listing an author according to Psych-DS standards. Option as a string to define an author according only to name.
*/
setAuthor(fields: {
type?: string;
name: string;
givenName?: string; // required
familyName?: string;
identifier?: string; // identifier that distinguish across dataset (URL), confusing should check description
}): void {
if (Object.keys(fields).length == 1) {
// if only name, just add to list without dict format, according to documentation
this.authors[fields.name] = fields.name;
return;
}
const new_author: { [key: string]: any } = {}; // Define an empty object to store the variables
new_author["name"] = fields["name"]; // to ensure that name is always first
delete fields["name"];
setAuthor(author: AuthorFields | string): void {
// handling string
if (typeof author === "string") {
this.authors[author] = author;
} else {
const { type, name, givenName, familyName, identifier, ...rest } = author;

for (const key in fields) {
// Check if the property is defined and not null
if (fields[key] !== undefined && fields[key] !== null) {
new_author[key] = fields[key];
if (!name) {
console.warn("Name field is missing. Author not added.");
return;
}
}

this.authors[new_author.name] = new_author;
const newAuthor: AuthorFields = { name, type, givenName, familyName, identifier, ...rest };
this.authors[name] = newAuthor;

if (Object.keys(rest).length > 0) {
// if there are any keys that don't belong
const unexpectedFields = Object.keys(rest).join(", ");
console.warn(
`Unexpected fields (${unexpectedFields}) detected and included in the author object.`
);
}
}
}

/**
* Method that fetches an author object allowing user to update (in existing workflow should not be necessary).
*
* @param {string} name - Name of author to be used as key.
* @returns {{}} - Object with author information.
* @returns {(AuthorFields | string | {})} - Object with author information. Empty object if not found.
*/
getAuthor(name: string): {} {
getAuthor(name: string): AuthorFields | string | {} {
if (name in this.authors) {
return this.authors[name];
} else return {};
} else {
console.warn("Author (", name, ") not found.");
return {};
}
}
}
35 changes: 13 additions & 22 deletions packages/metadata/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { JsPsych } from "jspsych";

import { AuthorFields } from "./AuthorsMap";
import { AuthorsMap } from "./AuthorsMap";
import { VariablesMap } from "./VariablesMap";

Expand Down Expand Up @@ -48,7 +47,7 @@ export default class JsPsychMetadata {
* @constructor
* @param {JsPsych} JsPsych
*/
constructor(private JsPsych: JsPsych) {
constructor() {
this.generateDefaultMetadata();
}
/**
Expand Down Expand Up @@ -106,31 +105,19 @@ export default class JsPsychMetadata {
* Method that creates an author. This method can also be used to overwrite existing authors
* with the same name in order to update fields.
*
* @param {{
* type?: string;
* name: string;
* givenName?: string;
* familyName?: string;
* identifier?: string;
* }} fields - All the required or possible fields associated with listing an author according to Psych-DS standards.
* @param {AuthorFields | string} author - All the required or possible fields associated with listing an author according to Psych-DS standards. Option as a string to define an author according only to name.
*/
setAuthor(fields: {
type?: string;
name: string;
givenName?: string; // required
familyName?: string;
identifier?: string; // identifier that distinguish across dataset (URL), confusing should check description
}): void {
this.authors.setAuthor(fields);
setAuthor(fields: AuthorFields): void {
this.authors.setAuthor(fields); // Assuming `authors` is an instance of the AuthorsMap class
}

/**
* Method that fetches an author object allowing user to update (in existing workflow should not be necessary).
*
* @param {string} name - Name of author to be used as key.
* @returns {{}} - Object with author information.
* @returns {(AuthorFields | string | {})} - Object with author information. Empty object if not found.
*/
getAuthor(name: string): {} {
getAuthor(name: string): AuthorFields | string | {} {
return this.authors.getAuthor(name);
}

Expand Down Expand Up @@ -404,14 +391,17 @@ export default class JsPsychMetadata {
}
} // iterating through each individual author class
else if (key === "author") {
console.log(value);
if (typeof value !== "object" || value === null) {
console.warn("Author object is not correct type");
return;
}

for (const author_key in value) {
const author = value[author_key];
if (!("name" in author)) author["name"] = author_key;

if (typeof author !== "string" && !("name" in author)) author["name"] = author_key;

this.setAuthor(author);
}
} else this.setMetadataField(key, value);
Expand Down Expand Up @@ -457,7 +447,8 @@ export default class JsPsychMetadata {
// Return the description
return description;
} catch (error) {
console.error(`Failed to fetch info from ${unpkgUrl}:`, error);
// console.error(`Failed to fetch info from ${unpkgUrl}:`, error); // DISABLING to test other features

// Error is likely due to 1)a fetch failure, or 2)no JSDoc comments in the script content matched.

//HANDLE FETCH FAILURE CASES
Expand Down
Loading

0 comments on commit ed76a3b

Please sign in to comment.