Skip to content

Commit

Permalink
#27 - Added most of the remaining support for workout goals. Remaining
Browse files Browse the repository at this point in the history
work includes:
- notify UI of current goal achievement status
- add support to animated watch for indicating goal achievement status
- ensure in-flight goal-achievement timer events are handled properly
after cancellation of timer
- make GoalSpec attribute names follow convention (lower case first
letter)
- test workout goal handling with Verifier
  • Loading branch information
John Wolfe committed Jul 10, 2014
1 parent 1ecdc79 commit 380c459
Show file tree
Hide file tree
Showing 8 changed files with 506 additions and 108 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,16 @@ INSERT INTO SPR_RS
VALUES ("d9d00089-99ea-429a-9af0-86fc7db383e8",
'setTargetPressed',
'',
'',
'// Find the singleton instance of workout session, and if there is a
// goal currently executing for it, notify it that its execution
// has completed.
select any session from instances of WorkoutSession;
if ( not empty session )
select one goal related by session->Goal[R11.''is currently executing''];
if ( not empty goal )
generate Goal1:Completed to goal;
end if;
end if;',
1);
INSERT INTO C_EP_PROXY
VALUES ("3e2d7574-ba3f-4a52-90c2-6787610b555a",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,30 @@ INSERT INTO O_OBJ
'Achievement',
10,
'Achievement',
'Each instance represents one contiguous period of time during
'Each instance represents one contiguous period of time during
which a particular goal was being met (achieved).',
"00000000-0000-0000-0000-000000000000");
INSERT INTO O_TFR
VALUES ("6fac41c9-c339-4dbe-8651-11ff5f9db899",
"313e48f7-0516-49bd-9401-5c67c2e55db9",
'close',
'',
"ba5eda7a-def5-0000-0000-000000000000",
1,
'// Close this open achievement record by storing the end time, relating this
// record as a recorded one and unrelating it as the open one.
select one goal related by self->Goal[R14.''is open for''];
select one workoutTimer related by
goal->WorkoutSession[R11.''is currently executing within'']->WorkoutTimer[R8.''is timed by''];
self.endTime = workoutTimer.time;
unrelate self from goal across R14.''is open for'';
relate self to goal across R12.''specifies achievement of'';


',
1,
'',
"00000000-0000-0000-0000-000000000000");
INSERT INTO O_NBATTR
VALUES ("b3949e0b-65ec-4e72-82be-b899f2e3b63b",
"313e48f7-0516-49bd-9401-5c67c2e55db9");
Expand All @@ -19,7 +40,7 @@ INSERT INTO O_ATTR
"313e48f7-0516-49bd-9401-5c67c2e55db9",
"00000000-0000-0000-0000-000000000000",
'startTime',
'Starting time for this achievement, expressed as the number of seconds
'Starting time for this achievement, expressed as the number of seconds
since the beginning of the associated workout session.',
'',
'startTime',
Expand All @@ -38,7 +59,7 @@ INSERT INTO O_ATTR
"313e48f7-0516-49bd-9401-5c67c2e55db9",
"b3949e0b-65ec-4e72-82be-b899f2e3b63b",
'endTime',
'Ending time for this achievement, expressed as the number of seconds
'Ending time for this achievement, expressed as the number of seconds
since the beginning of the associated workout session.',
'',
'endTime',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,31 @@ INSERT INTO O_TFR
'',
"ba5eda7a-def5-0000-0000-000000000000",
0,
'',
3,
'// Create and activate an instance of a goal specified by
// the goal specification identified by the incoming parameter.

// Find the goal specification for this goal, then
// create and relate this goal to the specification
// and to the singleton workout session.
select any goalSpec from instances of GoalSpec
where ( selected.SequenceNumber == param.sequenceNumber );
create object instance goal of Goal;
relate goal to goalSpec across R9.''specified by'';
select any session from instances of WorkoutSession;
relate goal to session across R11.''is currently executing within'';

// Initialize this goal.
goal.calculateStart();
goal.isBeingAchieved = false;

// Start a timer that periodically causes evaluation of goal achievement.
create event instance evaluateEvent of Goal2:Evaluate to goal;
goal.evaluationTimer = TIM::timer_start_recurring( event_inst: evaluateEvent, microseconds: evaluationPeriod );



',
1,
'',
"00000000-0000-0000-0000-000000000000");
INSERT INTO O_TPARM
Expand All @@ -29,6 +52,129 @@ INSERT INTO O_TPARM
'',
"00000000-0000-0000-0000-000000000000",
'Sequence number of the goal specification for which an instance of a goal should be created.');
INSERT INTO O_TFR
VALUES ("b3215204-3d02-48ba-9794-25ddbc40009c",
"c1022670-c44d-401e-bb23-dfcef6084fba",
'calculateStart',
'',
"ba5eda7a-def5-0000-0000-000000000000",
1,
'// Based on the span type for this goal, calculate and
// store the value of the start attribute.
select one goalSpec related by self->GoalSpec[R9.''specified by''];
if ( goalSpec.SpanType == GoalSpan::Time )
select one workoutTimer related by
self->WorkoutSession[R11.''is currently executing within'']->WorkoutTimer[R8.''is timed by''];
self.start = workoutTimer.time;
elif ( goalSpec.SpanType == GoalSpan::Distance )
select one session related by self->WorkoutSession[R11.''is currently executing within''];
self.start = session.accumulatedDistance;
else
LOG::LogFailure( message: "Goal.calculateStart: Unknown Goal Span Type." );
end if;',
1,
'',
"8ac30761-d43a-49d9-b7e4-c3ec442ea9f3");
INSERT INTO O_TFR
VALUES ("2b884ff8-637a-468b-a2fa-f96b8ef98b0a",
"c1022670-c44d-401e-bb23-dfcef6084fba",
'evaluateAchievement',
'',
"ba5eda7a-def5-0000-0000-000000000000",
1,
'// Based on the type of goal, determine whether this one is
// currently being achieved and update the appropriate attribute.

// Find the related goal specification and workout session for this goal.
select one goalSpec related by self->GoalSpec[R9.''specified by''];
select one session related by self->WorkoutSession[R11.''is currently executing within''];

// Based on the goal criteria type, get the appropriate current value
// for comparison against the criteria (minimum and maximum).
currentValue = 0.0; // Explicit declaration
if ( goalSpec.CriteriaType == GoalCriteria::HeartRate )
currentValue = session.currentHeartRate;
elif ( goalSpec.CriteriaType == GoalCriteria::Pace )
currentValue = session.currentPace;
else
LOG::LogFailure( message: "Goal.evaluateAchievement: Unknown Goal Criteria Type." );
end if;

// Save current value for handling of achievement records.
previousAchievement = self.isBeingAchieved;

// Compare the current value against the criteria and update the attribute
// indicating goal achievement status.
if ( (goalSpec.Minimum <= currentValue) and (currentValue <= goalSpec.Maximum) )
self.isBeingAchieved = true;
else
self.isBeingAchieved = false;
end if;

// Update achievement records if necessary. There are four cases:
// 0. Still not achieving this goal.
// 1. Just started achieving this goal.
// 2. Just stopped achieving this goal.
// 3. Still achieving this goal.
// For cases 0 and 3, there is nothing to be done for achievement records.
// Case 1 requires the creation of a new achievment record, storing the start time.
// Case 2 requires the storing of the end time for the open achievement record.
if ( (not previousAchievement) and self.isBeingAchieved )
// Case 1, create achievement record, store start time, relate it as open record.
create object instance achievement of Achievement;
relate self to achievement across R14.''has open'';
select one workoutTimer related by session->WorkoutTimer[R8.''is timed by''];
achievement.startTime = workoutTimer.time;
elif ( previousAchievement and (not self.isBeingAchieved) )
// Case 2, store end time, relate as recorded record, unrelate as open record.
select one achievement related by self->Achievement[R14.''has open''];
achievement.close();
end if;
',
1,
'',
"b3215204-3d02-48ba-9794-25ddbc40009c");
INSERT INTO O_TFR
VALUES ("7090ad22-2865-4836-a89f-a46b868d3ac0",
"c1022670-c44d-401e-bb23-dfcef6084fba",
'evaluateCompletion',
'',
"ba5eda7a-def5-0000-0000-000000000000",
1,
'// Based on the span type for this goal, determine
// whether it has been completed, update achievement
// records as necessary, and advance to the next goal
// if appropriate.

select one goalSpec related by self->GoalSpec[R9.''specified by''];

// Based on the span type for the goal, get the elapsed span
// for comparison against the specified span for the goal.
elapsedSpan = 0.0; // Explicit declaration
if ( goalSpec.SpanType == GoalSpan::Distance )
select one session related by self->WorkoutSession[R11.''is currently executing within''];
elapsedSpan = session.accumulatedDistance - self.start;
elif ( goalSpec.SpanType == GoalSpan::Time )
select one workoutTimer related by
self->WorkoutSession[R11.''is currently executing within'']->WorkoutTimer[R8.''is timed by''];
elapsedSpan = workoutTimer.time - self.start;
else
LOG::LogFailure( message: "Goal.evaluateCompletion: Unknown Goal Span Type." );
end if;

// Compare the current value against the specified span to determine
// whether the execution of this workout goal is complete.
if ( elapsedSpan >= goalSpec.Span )
select one openAchievement related by self->Achievement[R14.''has open''];
if ( not empty openAchievement )
openAchievement.close();
end if;
generate Goal1:Completed to self;
end if;
',
1,
'',
"2b884ff8-637a-468b-a2fa-f96b8ef98b0a");
INSERT INTO O_NBATTR
VALUES ("fa9000ac-0495-47fe-bbaf-66bc8f9a4f0a",
"c1022670-c44d-401e-bb23-dfcef6084fba");
Expand Down Expand Up @@ -58,17 +204,17 @@ INSERT INTO O_ATTR
"c1022670-c44d-401e-bb23-dfcef6084fba",
"645a58ca-7e54-4f1b-bb56-64249dab5aaa",
'start',
'Captures the starting point of the span for this particular goal so
that the end of the goal execution period can be determined. In other
words, using the value of this attribute together with the span specified
by the associated goal specification, the goal knows it is finished.
For distance-based goals, it is expressed as the accumulated distance
in meters for the associated workout session at the time this goal
execution commenced.
For time-based goals, it is expressed as the elapsed time in seconds
for the associated workout session at the time this goal execution
'Captures the starting point of the span for this particular goal so
that the end of the goal execution period can be determined. In other
words, using the value of this attribute together with the span specified
by the associated goal specification, the goal knows when it is finished.

For distance-based goals, it is expressed as the accumulated distance
in meters for the associated workout session at the time this goal
execution commenced.

For time-based goals, it is expressed as the elapsed time in seconds
for the associated workout session at the time this goal execution
commenced.',
'',
'start',
Expand Down Expand Up @@ -103,7 +249,7 @@ INSERT INTO O_BATTR
INSERT INTO O_ATTR
VALUES ("c307e400-f06b-4450-8e3c-94dadad961ff",
"c1022670-c44d-401e-bb23-dfcef6084fba",
"fa9000ac-0495-47fe-bbaf-66bc8f9a4f0a",
"0078004b-9cab-4a56-beac-5014d746ad80",
'current_state',
'',
'',
Expand All @@ -112,6 +258,24 @@ INSERT INTO O_ATTR
"ba5eda7a-def5-0000-0000-000000000006",
'',
'');
INSERT INTO O_NBATTR
VALUES ("0078004b-9cab-4a56-beac-5014d746ad80",
"c1022670-c44d-401e-bb23-dfcef6084fba");
INSERT INTO O_BATTR
VALUES ("0078004b-9cab-4a56-beac-5014d746ad80",
"c1022670-c44d-401e-bb23-dfcef6084fba");
INSERT INTO O_ATTR
VALUES ("0078004b-9cab-4a56-beac-5014d746ad80",
"c1022670-c44d-401e-bb23-dfcef6084fba",
"fa9000ac-0495-47fe-bbaf-66bc8f9a4f0a",
'evaluationTimer',
'Handle for the timer used for periodic evaluation of goal achievement.',
'',
'evaluationTimer',
0,
"ba5eda7a-def5-0000-0000-00000000000f",
'',
'');
INSERT INTO O_ID
VALUES (0,
"c1022670-c44d-401e-bb23-dfcef6084fba");
Expand Down
Loading

0 comments on commit 380c459

Please sign in to comment.