Skip to content

Commit

Permalink
Refine Assessment Charts and Fix Bugs (#43)
Browse files Browse the repository at this point in the history
# *Refine Assessment Charts and Fix Bugs*

## ♻️ Current situation & Problem
Previously, we set up the assessment tab with trail-making and stroop
tests. This PR refines the assessment tab by (1) fixing the error that
stroop test fails to start, and (2) refine the chart visualizations.

## ⚙️ Release Notes 
- Fix the error that the app will crash when attempting to start the
stroop test with `NSInvalidArgumentException`. The error was possibly
due to that the delegate no longer has a window property by default in
the newer version. Currently, we walk around this error by manually
adding the window property back, but might be better to check with the
Spezi team about whether this could be fixed by either updating the
forked ResearchKit version in
[StanfordBDHG](https://github.com/StanfordBDHG) or fixing it there.
- Plot the line chart of the assessment results.
- Enable highlighting the selected result line mark, and click again to
de-select. Similar to the HealthKit visualizations, the charts are coded
with reference to the [Swift-Charts-Examples
repo](https://github.com/jordibruin/Swift-Charts-Examples/blob/main/Swift%20Charts%20Examples/Charts/LineCharts/SingleLineLollipop.swift)
- Show the result details (time spent and error count/score) when
selected. If no mark is selected, show the details of the last result if
available.
- Style the buttons that start assessments to restrict clickable areas
to not start tests on clicking the chars.

<p align="left">
<img
src="https://github.com/CS342/2024-PICS/assets/32094663/803a9b59-434c-4fef-aab5-6b7063f004c9"
width="300">
<img
src="https://github.com/CS342/2024-PICS/assets/32094663/fba34759-d365-4ef6-9cdc-d12d7e5b57ba"
width="300">
<img
src="https://github.com/CS342/2024-PICS/assets/32094663/299cb976-3e70-4143-bb76-dffa87c1874d"
width="300">
</p>

## 📚 Documentation
Related comments are added to the codes.

## ✅ Testing
Manually tested in simulator.

## 📝 Code of Conduct & Contributing Guidelines 

By submitting creating this pull request, you agree to follow our [Code
of
Conduct](https://github.com/CS342/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/CS342/.github/blob/main/CONTRIBUTING.md):
- [x] I agree to follow the [Code of
Conduct](https://github.com/CS342/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/CS342/.github/blob/main/CONTRIBUTING.md).
  • Loading branch information
YurenSUN authored Mar 4, 2024
1 parent 464e9c3 commit 2d56adc
Show file tree
Hide file tree
Showing 7 changed files with 352 additions and 110 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/google/GoogleDataTransport.git",
"state" : {
"revision" : "a732a4b47f59e4f725a2ea10f0c77e93a7131117",
"version" : "9.3.0"
"revision" : "a637d318ae7ae246b02d7305121275bc75ed5565",
"version" : "9.4.0"
}
},
{
"identity" : "googleutilities",
"kind" : "remoteSourceControl",
"location" : "https://github.com/google/GoogleUtilities.git",
"state" : {
"revision" : "bc27fad73504f3d4af235de451f02ee22586ebd3",
"version" : "7.12.1"
"revision" : "830ffa9276e10267881f2697283c2fcd867603fd",
"version" : "7.13.0"
}
},
{
Expand Down Expand Up @@ -104,8 +104,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/firebase/leveldb.git",
"state" : {
"revision" : "9d108e9112aa1d65ce508facf804674546116d9c",
"version" : "1.22.3"
"revision" : "43aaef65e0c665daadf848761d560e446d350d3d",
"version" : "1.22.4"
}
},
{
Expand Down Expand Up @@ -140,8 +140,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordBDHG/ResearchKitOnFHIR",
"state" : {
"revision" : "300fbc0038df28f53a9b653298931f71aa6f0bb5",
"version" : "1.1.1"
"revision" : "7c2efdcb17796fc9ee686900304dbbe9dd4aaf85",
"version" : "1.1.2"
}
},
{
Expand Down Expand Up @@ -183,10 +183,10 @@
{
"identity" : "spezifoundation",
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordSpezi/SpeziFoundation.git",
"location" : "https://github.com/StanfordSpezi/SpeziFoundation",
"state" : {
"revision" : "0346857e2f1d6fd4b1d950d271be6c82df97107f",
"version" : "1.0.2"
"revision" : "01af5b91a54f30ddd121258e81aff2ddc2a99ff9",
"version" : "1.0.4"
}
},
{
Expand All @@ -212,8 +212,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordSpezi/SpeziOnboarding",
"state" : {
"revision" : "91463ae190611bd14ef52b0657e8db3bf53c9ae8",
"version" : "1.1.0"
"revision" : "4971a82e94996ce0c3d8ecf64fdeec874a1f20d6",
"version" : "1.1.1"
}
},
{
Expand All @@ -239,17 +239,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordSpezi/SpeziStorage.git",
"state" : {
"revision" : "eaed2220375c35400aa69d1f96a8d32b7e66b1c7",
"version" : "1.0.0"
"revision" : "7d1c8ff8310e2f628f918fb535d80f368730ad6b",
"version" : "1.0.1"
}
},
{
"identity" : "speziviews",
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordSpezi/SpeziViews.git",
"state" : {
"revision" : "d49f716e4a4d634604bb0dcd6d53df679b6c1358",
"version" : "1.3.0"
"revision" : "4d2a724d97c8f19ac7de7aa2c046b1cb3ef7b279",
"version" : "1.3.1"
}
},
{
Expand Down
105 changes: 52 additions & 53 deletions PICS/Assessment/Assessments.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,6 @@ struct Assessments: View {
case stroopTest
}

// Environment objects for app-wide settings and scheduling.
@Environment(PICSStandard.self) private var standard
@Environment(PICSScheduler.self) private var scheduler
@Environment(AppointmentInformation.self) private var appointmentInfo

// Binding to control the display of account-related UI.
@Binding private var presentingAccount: Bool

Expand All @@ -44,74 +39,78 @@ struct Assessments: View {

// Main body of the Assessments view, switching between the list of assessments and the currently active assessment.
var assessmentList: some View {
List {
trailMakingTestSection
stroopTestSection
}
List {
trailMakingTestSection
.padding(10)
stroopTestSection
.padding(10)
}

var body: some View {
NavigationStack {
if assessmentsIP {
// Displays the active assessment based on the currentTest state.
switch currentTest {
case .trailMaking:
TrailMakingTaskView()
case .stroopTest:
StroopTestView()
}
} else {
assessmentList
.navigationTitle(String(localized: "ASSESSMENTS_NAVIGATION_TITLE"))
.toolbar {
if AccountButton.shouldDisplay {
AccountButton(isPresented: $presentingAccount)
}
}
}

var body: some View {
NavigationStack {
if assessmentsIP {
// Displays the active assessment based on the currentTest state.
switch currentTest {
case .trailMaking:
TrailMakingTaskView()
case .stroopTest:
StroopTestView()
}
} else {
assessmentList
.navigationTitle(String(localized: "ASSESSMENTS_NAVIGATION_TITLE"))
.toolbar {
if AccountButton.shouldDisplay {
AccountButton(isPresented: $presentingAccount)
}
}
}
}
}

private var trailMakingTestSection: some View {
Section {
// Button text to start the Trail Making Test or view results
// based on whether results are available.
let btnText = if tmStorageResults.isEmpty {
String(localized: "ASSESSMENT_TM_START_BTN")
} else {
String(localized: "ASSESSMENT_RESULTS_BTN")
}
return Section {
VStack {
trailMakingTestResultsView
Divider()
.padding(.bottom, 5)
// Button to start the Trail Making Test or view results, based on whether results are available.
if tmStorageResults.isEmpty {
Button(action: startTrailMaking) {
Text(String(localized: "ASSESSMENT_TM_START_BTN"))
}
.frame(maxWidth: .infinity)
} else {
Button(action: startTrailMaking) {
Text(String(localized: "ASSESSMENT_RESULTS_BTN"))
}
.frame(maxWidth: .infinity)
.padding(.bottom, 5)
Button(action: startTrailMaking) {
Text(btnText)
.foregroundStyle(.accent)
}
// Use style to restrict clickable area.
.buttonStyle(.plain)
}
}
}

private var stroopTestSection: some View {
Section {
// Button text to start the Stroop Test or view results
// based on whether results are available.
let btnText = if stroopTestResults.isEmpty {
String(localized: "ASSESSMENT_STROOP_START_BTN")
} else {
String(localized: "ASSESSMENT_RESULTS_BTN")
}
return Section {
VStack {
stroopTestResultsView
Divider()
.padding(.bottom, 5)
// Button to start the Stroop Test or view results, based on whether results are available.
if stroopTestResults.isEmpty {
Button(action: startStroopTest) {
Text(String(localized: "ASSESSMENT_STROOP_START_BTN"))
}
.frame(maxWidth: .infinity)
} else {
Button(action: startStroopTest) {
Text(String(localized: "ASSESSMENT_RESULTS_BTN"))
}
.frame(maxWidth: .infinity)
Button(action: startStroopTest) {
Text(btnText)
.foregroundStyle(.accent)
}
// Use style to restrict clickable area.
.buttonStyle(.plain)
}
}
}
Expand Down
Loading

0 comments on commit 2d56adc

Please sign in to comment.