carekit-apple / CareKit

CareKit is an open source software framework for creating apps that help people better understand and manage their health.
https://www.researchandcare.org
Other
2.4k stars 443 forks source link

Creating new OCKOutcomes for different days #494

Open prmehra opened 4 years ago

prmehra commented 4 years ago

Hi, I have one task (call it task X), which repeats everyday. I want to create a new OCKOutcome object for each day that the task repeats, and associate this outcome with the occurrence of the task on that specific day. The problem is that after I associate one OCKOutcome to the task, I get a "duplicate value" everytime I try to add another OCKOutcome to the database associated with that task.

Here is what I am doing:

The localDBId seems to be the same no matter what date I query the task for, which is why I cannot seem to associate different OCKOutcomes to the task for different dates. Is there any way I can achieve this using the carekit schema?

For Task X, I want to store an array of values for each day that that the task repeats. Right now, as a workaround I am just creating one OCKOutcome object associated with the task and storing the values across all days in the value array.

Would really appreciate any guidance you have here! Thanks :)

erik-apple commented 4 years ago

Hi Prmehra,

An OCKTask can only have one outcome per time that it is scheduled (OCKEvent). The solution to your problem is to attach multiple OCKOutcomeValues to the single OCKOutcome. You can update an existing outcome to include extra values if you need to.

You'll also want to keep an eye on the occurrence index of your outcomes. Outcomes are uniquely identified by a combination of their task's ID and their occurrence index.

The outcome for first occurrence of your task (on day 0) will have occurrence index 0. The outcome for the second occurrence will be occurrence 1. All of the outcomes for the same version of the same task will have the same task ID.

Day 0 - Outcome(taskUUID: "abc123...", occurrence: 0)
Day 1 - Outcome(taskUUID: "abc123...", occurrence: 1)
Day 2 - Outcome(taskUUID: "abc123...", occurrence: 2)
prmehra commented 3 years ago

Hi Erik,

Thanks for the response! Does the DB automatically create a new Outcome with a different occurrence index for every day that the task repeats?

I currently implemented it just by having one OCKOutcome associated with the Task and I add new items to the values array (associated with that one OCKOutcome) everyday.

Is it a better design pattern to be using a new OCKOutcome (with a different occurrence index) for each day?

erik-apple commented 3 years ago

CareKit only saves outcomes where they exist. If you have a task that repeats every day, but the user has only completed it on days 2 and 4, then there will only be two outcomes in the database.

Yes, you should save one outcome for each occurrence of your task. If your task repeats every day, then there should be one outcome per day. If your task repeats 3 times per day, there should be 3 outcomes per day.

alanpm commented 3 years ago

I'm just getting my head around this at the moment as well @prmehra. All covered above already, but just to note I think the key is distinguishing between events and outcomes.

Does the DB automatically create a new Outcome with a different occurrence index for every day that the task repeats?

If you call fetchEvents on the store for a given task for a given time interval, CareKit will automatically generate events for each time the task is scheduled. In your example if you queried based on your daily task, with a time interval of one day, one event would be returned. These events may or may not have associated outcomes, depending on whether the task was completed as per the scheduled time or not.

I currently implemented it just by having one OCKOutcome associated with the Task and I add new items to the values array (associated with that one OCKOutcome) everyday.

Is it a better design pattern to be using a new OCKOutcome (with a different occurrence index) for each day?

As mentioned above, yes your second option is correct, and you can use the occurrence index as provided by the event (event.scheduleEvent.occurrence) to ensure your outcomes are unique. So these outcomes are saved to the DB, while the events are not, they are just temporarily generated any time you need to link tasks to outcomes.

erik-apple commented 3 years ago

That's a great explanation @alanpm! Thanks for contributing to the conversation!