ROAR DocumentationROAR Documentation
  • Databases
  • Workflows
  • Application
  • GitHub Actions
  • Dashboard Components
  • Firebase App Check
  • Cloud Functions
  • Backend Architecture
  • Internationalization
  • Integrating New Apps
  • Optimizing Assets
  • ROAR Redivis Instance
  • Logging and Querying
  • Emulation
  • Data Guidelines
  • Data Organization
  • Data Requests
GitHub
  • Databases
  • Workflows
  • Application
  • GitHub Actions
  • Dashboard Components
  • Firebase App Check
  • Cloud Functions
  • Backend Architecture
  • Internationalization
  • Integrating New Apps
  • Optimizing Assets
  • ROAR Redivis Instance
  • Logging and Querying
  • Emulation
  • Data Guidelines
  • Data Organization
  • Data Requests
GitHub
  • Databases
    • Database Information
    • gse-roar-admin
    • gse-roar-assessment
  • BigQuery
    • Querying Assessment Data
    • BigQuery schema: classes
    • BigQuery schema: districts
    • BigQuery schema: families
    • BigQuery schema: groups
    • BigQuery schema: schools
    • BigQuery schema: user_runs
    • BigQuery schema: user_trials
    • BigQuery schema: users
  • Workflows
    • Workflows
    • Creating an Assignment
    • Authentication
    • Creating new Users
    • User Roster Changes
    • How to Impersonate a Clever User on Localhost
  • Application

    • Auth
  • GitHub Actions
    • ROAR Apps GitHub Actions
      • GitHub Actions in ROAR Apps
      • firebase-deploy-preview.yml
      • firebase-hosting-merge.yml
      • publish-to-npm-create-new-release.yml
      • submit-dashboard-pr.yml
    • ROAR Dashboard GitHub Actions
      • GitHub Actions in the ROAR Dashboard
  • Dashboard Components
    • Dashboard Components
    • Organization Score Reports
  • Firebase App Check
    • Firebase App Check Configuration for roar-firekit and roar-dashboard
  • Backend Architecture
    • Architecture
      • Backend Architecture in ROAR
      • Data Models
      • Database Implementations
      • Error Handling Architecture in ROAR
      • Repository Layer Architecture
      • Service Layer Architecture
    • API
      • Classes
        • Class: AdministrationServiceError
        • Class: FirebaseClientError
        • Class: FirebaseImplementationError
        • Class: FirestoreAdministrationRepository
        • Class: FirestoreAdministrationRepositoryError
        • Class: abstract FirestoreBaseRepository<T>
        • Class: FirestoreFilterAdapter
        • Class: FirestoreIdentityProviderRepository
        • Class: FirestoreIdentityProviderRepositoryError
        • Class: FirestoreOrgRepository
        • Class: FirestoreOrgRepositoryError
        • Class: FirestoreRepositoryError
        • Class: FirestoreUserClaimRepository
        • Class: FirestoreUserClaimRepositoryError
        • Class: FirestoreUserRepository
        • Class: FirestoreUserRepositoryError
        • Class: IdentityProviderServiceError
        • Classes
      • Enumerations
        • Enumeration: CollectionType
        • Enumeration: IdentityProviderType
        • Enumeration: Operator
        • Enumerations
      • Functions
        • Functions
        • Function: chunkOrgs()
        • Function: createAdministrationService()
        • Function: createFirestoreImplementation()
        • Function: createIdentityProviderService()
        • Function: isEmptyOrgs()
      • Interfaces
        • Interface: Administration
        • Interface: AdministrationBaseRepository
        • Interface: AdministrationService
        • Interface: AssentConsent
        • Interface: Assessment
        • Interface: BaseModel
        • Interface: BaseRepository<T>
        • Interface: Claims
        • Interface: CompositeCondition
        • Interface: CompositeFilter
        • Interface: CreateAdministrationServiceParams<AdminRepo, OrgRepo, UserClaimRepo>
        • Interface: CreateParams
        • Interface: DeleteParams
        • Interface: EducationalOrgsList
        • Interface: FieldCondition
        • Interface: FilterAdapter<T>
        • Interface: FirestoreCreateParams
        • Interface: FirestoreDeleteParams
        • Interface: FirestoreFetchDocumentParams
        • Interface: FirestoreGetAllParams
        • Interface: FirestoreGetByIdParams
        • Interface: FirestoreGetByNameParams
        • Interface: FirestoreGetByRoarUidParams
        • Interface: FirestoreGetParams
        • Interface: FirestoreGetWithFiltersParams
        • Interface: FirestoreImplementation
        • Interface: FirestoreRunTransactionParams<T>
        • Interface: FirestoreUpdateParams
        • Interface: FutureParams
        • Interface: GetAdministrationIdsForAdministratorParams
        • Interface: GetAdministrationIdsFromOrgsParams
        • Interface: GetAllParams
        • Interface: GetByNameParams
        • Interface: GetByProviderIdParams
        • Interface: GetByRoarUidParams
        • Interface: GetParams
        • Interface: GetRoarUidParams
        • Interface: IdentityProvider
        • Interface: IdentityProviderBaseRepository
        • Interface: IdentityProviderService
        • Interface: Legal
        • Interface: OrgBase
        • Interface: OrgBaseRepository
        • Interface: OrgsList
        • Interfaces
        • Interface: Result<T>
        • Interface: RunTransactionParams<T>
        • Interface: SingleFilter
        • Interface: UpdateParams
        • Interface: User
        • Interface: UserBaseRepository
        • Interface: UserClaim
        • Interface: UserClaimBaseRepository
        • Interface: createIdentityProviderServiceParams<IDPRepo, UserClaimRepo, UserRepo>
        • Interface: getAdministrationIdsFromOrgsParams
        • Interface: _setAdministrationIdsParams
      • Type Aliases
        • Type Alias: BaseFilter
        • Type Alias: ComparisonOperator
        • Type Alias: Condition
        • Type Alias: DocumentCreatedEvent
        • Type Alias: DocumentDeletedEvent
        • Type Alias: DocumentUpdatedEvent
        • Type Alias: DocumentWrittenEvent
        • Type Alias: ParameterValue
        • Type Aliases
        • Type Alias: SelectAllCondition
      • Variables
        • Variable: FirebaseAppClient
        • Variable: FirebaseAuthClient
        • Variable: FirestoreClient
        • Variable: ORG_NAMES
        • Variables API Documentation
    • Examples
      • Examples
    • Guides
      • Guides
  • Cloud Functions
    • gse-roar-admin
      • Admin Database
      • appendToAdminClaims()
      • associateassessmentuid()
      • createAdministratorAccount()
      • createGuestDocsForGoogleUsers()
      • createLevanteGroup()
      • createLevanteUsers()
      • createnewfamily()
      • createstudentaccount()
      • mirrorClasses()
      • mirrorCustomClaims
      • mirrorDistricts()
      • mirrorFamilies()
      • mirrorGroups()
      • mirrorSchools()
      • removefromadminclaims()
      • saveSurveyResponses()
      • setuidcustomclaims()
      • softDeleteUserAssignment()
      • softDeleteUserExternalData
      • softDeleteUser()
      • syncAssignmentCreated()
      • syncAssignmentDeleted()
      • syncAssignmentUpdated()
      • syncAssignmentsOnAdministrationUpdate()
      • syncAssignmentsOnUserUpdate()
      • syncCleverOrgs()
      • syncCleverUser()
    • gse-roar-assessment
      • Assessment Database
      • organizeBucketLogsByDate()
      • setuidclaims()
      • softDeleteGuestTrial()
      • softDeleteGuest()
      • softDeleteUserRun()
      • softDeleteUserTrial()
      • syncOnRunDocUpdate()
  • Internationalization
    • ROAM Fluency
    • ROAR Letter
    • ROAR Phoneme
    • Internationalization of ROAR Apps
    • ROAR Sentence
    • ROAR Word
  • Integrating New Apps
    • Integrating Roar Apps into the Dashboard
    • Dashboard Integration
    • Monitoring and Testing
    • Preparing the App for Packaging and Deployment
    • Packaging and Publishing to npm
    • Secrets in the GitHub Repository
  • Assets Optimization
    • Optimizing Assets
    • Audio Optimization Guide
    • Image Optimization Guide
  • ROAR Redivis Instance
    • ROAR Redivis Instance
    • ROAR Data Validator Trigger
    • ROAR Data Validator
  • Logging and Querying
    • ROAR Logging
  • Emulation
    • Running the Emulator
      • Commands
    • Emulator Configuration Guide
      • Configuration
      • Cypress Configuration
      • Setup and Dependencies
      • Firebase CLI Configuration
      • Firebase Emulator Configuration
      • GitHub Secrets and Workflows
      • Importing and Exporting Data
      • Local Environment Variables
  • Clowder Implementation
    • Clowder Integration
    • Letter - Clowder
    • Multichoice - Clowder
    • Phoneme - Clowder
    • ARF & CALF - Clowder

ARF & CALF - Clowder

📝 NOTE: ROAM apps will use the URL param mode=cat to switch between adaptive and non-adaptive modes.

1. Fetch and Parse Corpus for Clowder (tasks/fluency/helpers/fetchAndParseCorpus.js)

  • Add the needed rows to the corpus handler
// Add CAT corpus-specific columns if in CAT mode
    if (store.session.get("config").userMode === "cat") {
      ["sum", "minus", "mult", "div", "total"].forEach((op) => {
        ["a", "b", "c", "d"].forEach((suffix) => {
          newRow[`${op}.${suffix}`] = row[`${op}.${suffix}`];
        });
      });
    }
  • Select the corpus for clowder
if (store.session.get("config").userMode === "cat") {
    block0: `link to block 0 order`,	    
    corpusLocation = {
        fluencyArf: {
            order: {
            block0: `block 0 link for arf`,
            },
            stimulus: `link for items-all-cat.csv`,
            practice: `link for items-practice-cat.csv`,
        },	      
    // more locations
        };
    };
    // more apps location
};
  • Initialize Clowder
if (store.session.get("config").userMode === "cat") {
    initializeClowder();
}

export const initializeClowder = () => {
// Define the `cats` configuration
const catsConfig = {
    sum: {
        method: "MLE", // EAP
        itemSelect: store.session("itemSelect"),
        minTheta: -8,
        maxTheta: 8,
        randomSeed: "seed-sum",
    },
    minus: {
        method: "MLE",
        itemSelect: store.session("itemSelect"),
        minTheta: -8,
        maxTheta: 8,
        randomSeed: "seed-minus",
    },
    mult: {
        method: "MLE",
        itemSelect: store.session("itemSelect"),
        minTheta: -8,
        maxTheta: 8,
        randomSeed: "seed-mult",
    },
    div: {
        method: "MLE",
        itemSelect: store.session("itemSelect"),
        minTheta: -8,
        maxTheta: 8,
        randomSeed: "seed-div",
    },
    total: {
        method: "MLE",
        itemSelect: store.session("itemSelect"),
        minTheta: -8,
        maxTheta: 8,
        randomSeed: "seed-total",
    },
};
  • Prepare corpus and create a new instance of Clowder
// USE THIS EXAMPLE TO GET EARLY STOPPING CATS -- REMEMBER TO IMPORT FUNCTIONS FROM CLOWDER AS NEEDED

  // if (store.session.get('config').earlyStopping) {
  // earlyStoppingCats = new StopAfterNItems({
  //   requiredItems: {
  //     sum:  5,
  //     minus: 5,
  //     div: 15,
  //     mult: 15,
  //   },
  //   logicalOperation: 'only',
  // });

  const corpusClowder = store.session.get("corpusAll")["stimulus"]["block0"];

  const clowderCorpus = prepareClowderCorpus(
    corpusClowder,
    ["sum", "minus", "mult", "div", "total"],
    ".",
  );

  /* In the case of ROAM there are 2 separate stimulus files, 
    one for practice and the other one for stimuli test, we need to add the zetas
    in the corresponding block -- we are not using a cat for practice */

  const corpusWithClowder = store.session.get("corpusAll");

  corpusWithClowder.stimulus.block0 = clowderCorpus;

  store.session.set("corpusAll", corpusWithClowder);

  clowder = new Clowder({
    cats: catsConfig,
    corpus: corpusWithClowder.stimulus.block0,
    randomSeed: store.session.get("config").randomSeed ?? "random-seed",
    // earlyStopping: earlyStoppingCats, --- use this if early stopping is needed
  });

2. Update the stimulus for Clowder (tasks/shared/helpers/updateStimulus.js)

import { clowder } from "../../fluency/helpers/fetchAndParseCorpus";

const catOrderMap = {
  0: "sum",
  1: "minus",
  2: "mult",
  3: "div",
};

const getNextStimulus = (corpusName) => {
  let corpus, nextStimulus, remainingStimuli;

  // read the current version of the corpus
  corpus = store.session.get("currentCorpus");
  if (
    store.session.get("config").userMode === "cat" &&
    corpusName === "stimulus"
  ) {
    let catIndex = store.session.get("currentCatIndex");

    if (catIndex == undefined) {
      store.session.set("currentCatIndex", 0);
      catIndex = 0;
    }

    const catName = catOrderMap[catIndex];
    const previousItem = store.session.get("previousItem");
    const previousAnswer = store.session.get("previousAnswer");

    const nextStimulus = clowder.updateCatAndGetNextItem({
      catToSelect: catName,
      catsToUpdate: ["total", "sum", "minus", "mult", "div"],
      items: previousItem ?? undefined,
      answers: previousAnswer ?? undefined,
      randomlySelectUnvalidated: false,
    });

    if (nextStimulus === undefined) {
      store.session.remove("nextStimulus");
      const catIndex = (store.session.get("currentCatIndex") ?? -1) + 1;
      store.session.set("currentCatIndex", catIndex);
      if (catIndex < 4) {
        getNextStimulus(corpusName);
      }
    } else {
      store.session.set("nextStimulus", nextStimulus);
    }
  } else {
    nextStimulus = corpus[0];
    // get the remaining stimuli
    remainingStimuli = corpus.slice(1);
    // store the item for use in the trial
    store.session.set("nextStimulus", nextStimulus);
    // update the corpus with the remaining unused items
    corpus = remainingStimuli;
    store.session.set("currentCorpus", corpus);
  }
};

3. Save previous items and responses (tasks/responseModalityStudy/trials/responseTimeBlock.js)

  • Since we are only updating from the stimulus corpus names, we need to save the previous seen items and answers from the stimulus block
if (corpusName === "stimulus") {
    store.session.set("previousItem", stimulus);
    store.session.set("previousAnswer", store.session.get("dataCorrect"));
}
Edit this page
Last Updated:
Contributors: Elijah Kelly, emily-ejag
Prev
Phoneme - Clowder