Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

First and foremost, schedules are global in scope along with studies, so if a study defines a set of events, the schedule may or may not be valid since it could reference events from another study.

Second, the existing system supports study burst designs, but only indirectly through automatic custom events. These events themselves represent time sequences that are not directly represented in the model.

To address these issues, I propose the following changes.

Scope schedules 1:1 with studies in our API

The long-term plan had been for studies to be associated to protocols, which would have referenced one or more study arms and schedules which could be associated to those study arms. If we eliminate the protocol from the domain design, the study becomes the primary object for this purpose. Schedules What this means however is that a schedule can only be used in the context of a study. If a study designer wanted to reuse a schedule (or events, or study arms) these would need to be copied between studies…there would be no protocol that could be associated to multiple studies.

Second, the existing system supports study burst designs, but only indirectly through automatic custom events. These events themselves represent time sequences that are not directly represented in the model.

To address these issues, I propose the following changes.

Scope schedules 1:1 with studies in our API

Remove into the new study. It would no longer be possible to just reference the same protocol as the original study.

Therefore, remove the following APIs:

Code Block
GET /v5/schedules
POST /v5/schedules
GET /v5/schedules/{guid}
GET /v5/schedules/{guid}/timeline
POST /v5/schedules/{guid}
POST /v5/schedules/{guid}/publish
DELETE /v5/schedules/{guid}

Add the following APIs (to be phased out with the introduction of later APIs to support multi-arm studies with multiple schedules):

Code Block
GET /v5/studies/{studyId}/schedule - will create a starter record if it doesn't exist
POST /v5/studies/{studyId}/schedule - will create the record if it doesn't exist
GET /v5/studies/{studyId}/timeline - transitional

Schedule publication will happen only as part of changing the phase of the study from design. The schedule will only be deleted when the study is deleted. Now events can be defined in a study, referenced from a schedule, and we can expand to multiple arms/schedules later that will share this set of event definitions.

...

Code Block
class Study {
  List<CustomEvent> customEvents;
  List<AutoCustomEvent> automaticCustomEvents;
  List<StudyBurst> studyBursts;
}

Custom events and automatic custom events will function identically to their App model counter-parts. For study-scoped events, but they will be configured with some additional information, so am embedded object is appropriate (along with a separate tablereferenced for validation rather than the app-scoped custom events and automatic custom events (which are being replaced with study bursts, see below):

Code Block
languagejava
/**
 * This is the same event as in the App map, but with a display label.
 */
class CustomEvent {
  String identifier;
  String label;
  ActivityEventUpdateType updateType;
}

Schedules will take a new array of StudyBurst objects which will be used to validate submitted events and to trigger schedules:

Code Block
class Schedule2 /**{
 * AlmostList<StudyBurst> identicalstudyBursts;
to}
automatic
custom// eventsSession inis theaugmented App,to butreference withone aor labelmore study *bursts. andA asession means
of// findingmust allreferenced theat automaticleast customone eventsevent that are generated
 * from aID or study burst configuration.ID (it */does classnot
AutomaticCustomEvent// {need to have Stringboth, identifier;but it can).
Stringclass label;Session {
 String studyBurstId;
  String originEventId;
  Period offset; // positive or negative
}

The new configuration is the StudyBurst, which describes how to generate a set of automatic custom events:

Code Block
List<String> studyBurstIds;
}

class StudyBurst {
  String identifier;
  String originEventId;
  String int occurrences;
  Period interval; // positive or negative
}

On study create and update, the server will remove all automatic custom events with a studyBurstId, then iterate through the study burst configurations and create the automatic custom events specified by that configuration.

For example, a study burst named “foo” triggered from “enrollment” four times, at When an event is published (this can be a custom event or a compound system event, like the time a session is finished), and it matches a study burst originEventId, then a sequence of events will be published based on the StudyBurst configuration. The event ID will be in the format burst:<studyBurstIdentifier>:# where the # is the occurrence number of the new event (1-based). The value will be the timestamp of the event + (the interval specified by the study burst * the occurrence number). All these events are published up-front because they are mutable. If the internal publication of these events finds that the event is already in the user’s event map, then it will not be regenerated.

Info

Example

A study burst with an identifier of “foo” triggered on enrollment, four times, with an interval of P1W, would

...

Initially a schedule would need to reference these automatic custom events, but we can probably include a study burst reference in the Session object and expand that when generating a timeline to include the auto custom events that the client would expect to find in the participant’s event map.

Make automatic custom events mutable

...

produce the following event IDs and timestamps if the enrollment was published at 2021-05-14T10:00:00.000-07:00:

  • burst:foo:1 = 2021-05-21T10:00:00.000Z

  • burst:foo:2 = 2021-05-28T10:00:00.000Z

  • burst:foo:3 = 2021-06-04T10:00:00.000Z

  • burst:foo:4 = 2021-06-11T10:00:00.000Z

In effect, study bursts are calculated and treated similarly to automatic custom events, but they are defined in a way that captures the intent of automatic custom events.

When a study is converted to a Timeline, each session that has one or more study bursts will determine the event identifiers of the study burst (which does not require calculation of a time), and all these event IDs will be added to the session’s startEventIds before the session is then converted into scheduled sessions that encode one starting event each.

Info

Example

Continuing the example above, if the “foo” study burst were referenced in a Session that specified startEventIds as [“event1”, “event2”] then the final set of events that would be processed into a timeline would be [“event1”, “event2”, “burst:foo:1”, “burst:foo:2”, “burst:foo:3”, “burst:foo:4”]. Every single instance of a scheduled session would produce six scheduled sessions, each of which would encode a different instanceGuid for a different event ID, but all would point to the same SessionInfo object.