diff --git a/ios/FlankerNativeComponents/GameManager.swift b/ios/FlankerNativeComponents/GameManager.swift
index 2e3d124ac..8e08f41a5 100644
--- a/ios/FlankerNativeComponents/GameManager.swift
+++ b/ios/FlankerNativeComponents/GameManager.swift
@@ -26,7 +26,6 @@ enum Constants {
static let bigFont: UIFont = .systemFont(ofSize: 50.0, weight: .bold)
static let smallFont: UIFont = .systemFont(ofSize: 30.0, weight: .bold)
static let tag: String = "trial"
- static let trialTag: String = "html-button-response"
}
enum TypeTimeStamps {
@@ -54,7 +53,7 @@ class GameManager {
private var timerSetText: Timer?
private var timeResponse: Timer?
- private var countTest = 0
+ private var countTest = -1
private var countAllGame = 0
private var correctAnswers = 0
@@ -72,8 +71,7 @@ class GameManager {
private var endFeedbackTimestamp: Double?
private var respondTouchButton: Double?
-
- private var isFirst = true
+ private var hasRespondedInCurrentTrial = false
private var gameParameters: ParameterModel?
@@ -93,10 +91,10 @@ class GameManager {
isShowFixations = parameters.showFixation
isShowResults = parameters.showResults
countAllGame = parameters.trials.count
- updateButtonTitle()
resultManager.cleanData()
- countTest = 0
+ countTest = -1
correctAnswers = 0
+ arrayTimes = []
startLogicTimer()
}
@@ -110,70 +108,12 @@ class GameManager {
switch type {
case .fixations:
startFixationsTimestamp = time
-
- if
- let startFeedbackTimestamp = startFeedbackTimestamp,
- let endFeedbackTimestamp = endFeedbackTimestamp,
- let gameParameters = gameParameters,
- gameParameters.showFeedback {
- let resultTime = (time - startFeedbackTimestamp) * 1000
- let model = FlankerModel(rt: resultTime,
- stimulus: "
\(responseText)
",
- button_pressed: nil,
- image_time: endFeedbackTimestamp * 1000,
- correct: nil,
- start_timestamp: 0,
- tag: "feedback",
- trial_index: countTest,
- start_time: startFeedbackTimestamp * 1000,
- response_touch_timestamp: 0)
- delegate?.resultTest(avrgTime: nil, procentCorrect: nil, data: model, dataArray: nil, isShowResults: gameParameters.showResults, minAccuracy: gameParameters.minimumAccuracy)
- resultManager.addStepData(data: model)
- }
case .trial:
- startTrialTimestamp = time
-
- if
- let startFixationsTimestamp = startFixationsTimestamp,
- let endFixationsTimestamp = endFixationsTimestamp,
- let gameParameters = gameParameters,
- gameParameters.showFixation {
- let resultTime = (time - startFixationsTimestamp) * 1000
- let model = FlankerModel(rt: resultTime,
- stimulus: "-----
",
- button_pressed: nil,
- image_time: endFixationsTimestamp * 1000,
- correct: nil,
- start_timestamp: 0,
- tag: "fixation",
- trial_index: countTest + 1,
- start_time: startFixationsTimestamp * 1000,
- response_touch_timestamp: 0)
- delegate?.resultTest(avrgTime: nil, procentCorrect: nil, data: model, dataArray: nil, isShowResults: gameParameters.showResults, minAccuracy: gameParameters.minimumAccuracy)
- resultManager.addStepData(data: model)
- } else if
- let startFeedbackTimestamp = startFeedbackTimestamp,
- let endFeedbackTimestamp = endFeedbackTimestamp,
- let gameParameters = gameParameters,
- gameParameters.showFeedback,
- !gameParameters.showFixation {
- let resultTime = (time - startFeedbackTimestamp) * 1000
- let model = FlankerModel(rt: resultTime,
- stimulus: "\(responseText)
",
- button_pressed: nil,
- image_time: endFeedbackTimestamp * 1000,
- correct: nil,
- start_timestamp: 0,
- tag: "feedback",
- trial_index: countTest,
- start_time: startFeedbackTimestamp * 1000,
- response_touch_timestamp: 0)
- delegate?.resultTest(avrgTime: nil, procentCorrect: nil, data: model, dataArray: nil, isShowResults: gameParameters.showResults, minAccuracy: gameParameters.minimumAccuracy)
- resultManager.addStepData(data: model)
- }
+ break
case .feedback:
startFeedbackTimestamp = time
- case .response: break
+ case .response:
+ break
}
} else {
switch type {
@@ -184,108 +124,56 @@ class GameManager {
case .feedback:
endFeedbackTimestamp = time
case .response:
- respondTouchButton = time
+ break
}
}
}
func checkedAnswer(button: SelectedButton) {
+ guard !hasRespondedInCurrentTrial else { return }
+ hasRespondedInCurrentTrial = true
+ respondTouchButton = CACurrentMediaTime()
invalidateTimers()
delegate?.setEnableButton(isEnable: false)
guard let gameParameters = gameParameters else { return }
- guard
- let startTrialTimestamp = startTrialTimestamp,
- let endTrialTimestamp = endTrialTimestamp,
- let respondTouchButton = respondTouchButton
- else { return }
- let resultTime = (respondTouchButton - startTrialTimestamp) * 1000
- arrayTimes.append(resultTime.convertToInt())
+ guard let startTrialTimestamp = startTrialTimestamp else { return }
+ var resultTime = (respondTouchButton! - startTrialTimestamp) * 1000
+
+ arrayTimes.append(Int(resultTime))
delegate?.updateTime(time: String(format: "%.3f", resultTime))
- switch button {
- case .left:
- if gameParameters.trials[countTest].correctChoice == 0 {
- correctAnswers += 1
- let model = FlankerModel(rt: resultTime,
- stimulus: text,
- button_pressed: "0",
- image_time: endTrialTimestamp * 1000,
- correct: true,
- start_timestamp: 0,
- tag: Constants.tag,
- trial_index: countTest + 1,
- start_time: startTrialTimestamp * 1000,
- response_touch_timestamp: respondTouchButton * 1000)
-
- resultManager.addStepData(data: model)
- delegate?.resultTest(avrgTime: nil, procentCorrect: nil, data: model, dataArray: nil, isShowResults: gameParameters.showResults, minAccuracy: gameParameters.minimumAccuracy)
- if gameParameters.showFeedback {
- delegate?.updateText(text: Constants.correctText, color: Constants.greenColor, font: Constants.smallFont, isStart: false, typeTime: .feedback)
- }
- responseText = Constants.correctText
- } else {
- let model = FlankerModel(rt: resultTime,
- stimulus: text,
- button_pressed: "0",
- image_time: endTrialTimestamp * 1000,
- correct: false,
- start_timestamp: 0,
- tag: Constants.tag,
- trial_index: countTest + 1,
- start_time: startTrialTimestamp * 1000,
- response_touch_timestamp: respondTouchButton * 1000)
-
- resultManager.addStepData(data: model)
- delegate?.resultTest(avrgTime: nil, procentCorrect: nil, data: model, dataArray: nil, isShowResults: gameParameters.showResults, minAccuracy: gameParameters.minimumAccuracy)
- if gameParameters.showFeedback {
- delegate?.updateText(text: Constants.inCorrectText, color: Constants.redColor, font: Constants.smallFont, isStart: false, typeTime: .feedback)
- }
- responseText = Constants.inCorrectText
- }
- case .right:
- if gameParameters.trials[countTest].correctChoice == 1 {
- correctAnswers += 1
- let model = FlankerModel(rt: resultTime,
- stimulus: text,
- button_pressed: "1",
- image_time: endTrialTimestamp * 1000,
- correct: true,
- start_timestamp: 0,
- tag: Constants.tag,
- trial_index: countTest + 1,
- start_time: startTrialTimestamp * 1000,
- response_touch_timestamp: respondTouchButton * 1000)
-
- resultManager.addStepData(data: model)
- delegate?.resultTest(avrgTime: nil, procentCorrect: nil, data: model, dataArray: nil, isShowResults: gameParameters.showResults, minAccuracy: gameParameters.minimumAccuracy)
- if gameParameters.showFeedback {
- delegate?.updateText(text: Constants.correctText, color: Constants.greenColor, font: Constants.smallFont, isStart: false, typeTime: .feedback)
- }
- responseText = Constants.correctText
- } else {
- let model = FlankerModel(rt: resultTime,
- stimulus: text,
- button_pressed: "1",
- image_time: endTrialTimestamp * 1000,
- correct: false,
- start_timestamp: 0,
- tag: Constants.tag,
- trial_index: countTest + 1,
- start_time: startTrialTimestamp * 1000,
- response_touch_timestamp: respondTouchButton * 1000)
-
- resultManager.addStepData(data: model)
- delegate?.resultTest(avrgTime: nil, procentCorrect: nil, data: model, dataArray: nil, isShowResults: gameParameters.showResults, minAccuracy: gameParameters.minimumAccuracy)
- if gameParameters.showFeedback {
- delegate?.updateText(text: Constants.inCorrectText, color: Constants.redColor, font: Constants.smallFont, isStart: false, typeTime: .feedback)
- }
- responseText = Constants.inCorrectText
- }
+
+ endTrialTimestamp = respondTouchButton
+
+ startFeedbackTimestamp = CACurrentMediaTime()
+
+ let correctChoice = gameParameters.trials[countTest].correctChoice
+ let isCorrect = (button == .left && correctChoice == 0) || (button == .right && correctChoice == 1)
+ if isCorrect {
+ correctAnswers += 1
}
+ let buttonPressed = (button == .left) ? "0" : "1"
+ let model = FlankerModel(rt: resultTime,
+ stimulus: text,
+ button_pressed: buttonPressed,
+ image_time: endTrialTimestamp! * 1000,
+ correct: isCorrect,
+ start_timestamp: 0,
+ tag: Constants.tag,
+ trial_index: countTest + 1,
+ start_time: startTrialTimestamp * 1000,
+ response_touch_timestamp: respondTouchButton! * 1000)
+
+ resultManager.addStepData(data: model)
+ delegate?.resultTest(avrgTime: nil, procentCorrect: nil, data: model, dataArray: nil, isShowResults: false, minAccuracy: gameParameters.minimumAccuracy)
+
if gameParameters.showFeedback {
- let timer = Timer(timeInterval: Constants.lowTimeInterval, target: self, selector: #selector(self.setDefaultText), userInfo: nil, repeats: false)
+ let feedbackText = isCorrect ? Constants.correctText : Constants.inCorrectText
+ let feedbackColor = isCorrect ? Constants.greenColor : Constants.redColor
+ delegate?.updateText(text: feedbackText, color: feedbackColor, font: Constants.smallFont, isStart: false, typeTime: .feedback)
+ let timer = Timer(timeInterval: Constants.lowTimeInterval, target: self, selector: #selector(setDefaultText), userInfo: nil, repeats: false)
RunLoop.main.add(timer, forMode: .common)
} else {
setDefaultText(isFirst: false)
@@ -295,24 +183,30 @@ class GameManager {
@objc func setDefaultText(isFirst: Bool) {
guard let gameParameters = gameParameters else { return }
+ hasRespondedInCurrentTrial = false
+ delegate?.setEnableButton(isEnable: false)
+
if !isFirst {
+ endFeedbackTimestamp = CACurrentMediaTime()
countTest += 1
+ } else {
+ countTest = 0
}
-
- if gameParameters.showFixation {
- if let image = URL(string: gameParameters.fixation), gameParameters.fixation.contains("https") {
- delegate?.updateFixations(image: image, isStart: false, typeTime: .fixations)
- } else {
- delegate?.updateText(text: gameParameters.fixation, color: .black, font: Constants.bigFont, isStart: false, typeTime: .fixations)
- }
+ if isEndGame() {
+ handleEndOfGame()
+ return
}
- if isEndGame() { return }
- invalidateTimers()
updateButtonTitle()
if gameParameters.showFixation {
+ startFixationsTimestamp = CACurrentMediaTime()
+ if let image = URL(string: gameParameters.fixation), gameParameters.fixation.contains("https") {
+ delegate?.updateFixations(image: image, isStart: true, typeTime: .fixations)
+ } else {
+ delegate?.updateText(text: gameParameters.fixation, color: .black, font: Constants.bigFont, isStart: true, typeTime: .fixations)
+ }
timerSetText = Timer(timeInterval: gameParameters.fixationDuration / 1000, target: self, selector: #selector(setText), userInfo: nil, repeats: false)
RunLoop.main.add(timerSetText!, forMode: .common)
} else {
@@ -322,8 +216,14 @@ class GameManager {
@objc func setText() {
guard let gameParameters = gameParameters else { return }
+ guard countTest < gameParameters.trials.count else {
+ handleEndOfGame()
+ return
+ }
- delegate?.setEnableButton(isEnable: true)
+ endFixationsTimestamp = CACurrentMediaTime()
+
+ startTrialTimestamp = CACurrentMediaTime()
text = gameParameters.trials[countTest].stimulus.en
@@ -333,27 +233,32 @@ class GameManager {
delegate?.updateText(text: text, color: .black, font: Constants.bigFont, isStart: true, typeTime: .trial)
}
- timeResponse = Timer(timeInterval: gameParameters.trialDuration / 1000, target: self, selector: #selector(self.timeResponseFailed), userInfo: nil, repeats: false)
- RunLoop.main.add(timeResponse!, forMode: .common)
+ DispatchQueue.main.asyncAfter(deadline: .now()) {
+ self.delegate?.setEnableButton(isEnable: true)
+ self.timeResponse = Timer(timeInterval: gameParameters.trialDuration / 1000, target: self, selector: #selector(self.timeResponseFailed), userInfo: nil, repeats: false)
+ RunLoop.main.add(self.timeResponse!, forMode: .common)
+ }
}
@objc func timeResponseFailed() {
guard let gameParameters = gameParameters else { return }
delegate?.setEnableButton(isEnable: false)
+
+ endTrialTimestamp = CACurrentMediaTime()
+
+ startFeedbackTimestamp = CACurrentMediaTime()
+
if gameParameters.showFeedback {
delegate?.updateText(text: Constants.timeRespondText, color: .black, font: Constants.smallFont, isStart: false, typeTime: .feedback)
}
- guard
- let startTrialTimestamp = startTrialTimestamp,
- let endTrialTimestamp = endTrialTimestamp
- else { return }
+ guard let startTrialTimestamp = startTrialTimestamp else { return }
let model = FlankerModel(rt: 0.0,
stimulus: text,
button_pressed: nil,
- image_time: endTrialTimestamp * 1000, // має намалювати
+ image_time: endTrialTimestamp! * 1000, // має намалювати
correct: false,
start_timestamp: 0, // вже намальовано
tag: Constants.tag,
@@ -362,93 +267,93 @@ class GameManager {
response_touch_timestamp: 0)
resultManager.addStepData(data: model)
- delegate?.resultTest(avrgTime: nil, procentCorrect: nil, data: model, dataArray: nil, isShowResults: gameParameters.showResults, minAccuracy: gameParameters.minimumAccuracy)
- responseText = Constants.timeRespondText
+ delegate?.resultTest(avrgTime: nil, procentCorrect: nil, data: model, dataArray: nil,isShowResults: gameParameters.showResults, minAccuracy: gameParameters.minimumAccuracy)
- let timer = Timer(timeInterval: Constants.lowTimeInterval, target: self, selector: #selector(self.setDefaultText), userInfo: nil, repeats: false)
- RunLoop.main.add(timer, forMode: .common)
+ if gameParameters.showFeedback {
+ let timer = Timer(timeInterval: Constants.lowTimeInterval, target: self, selector: #selector(setDefaultText), userInfo: nil, repeats: false)
+ RunLoop.main.add(timer, forMode: .common)
+ } else {
+ setDefaultText(isFirst: false)
+ }
}
- func clearData() {
- resultManager.cleanData()
- countTest = 0
- correctAnswers = 0
- arrayTimes = []
- invalidateTimers()
- }
-}
+ func handleEndOfGame() {
+ guard let gameParameters = gameParameters else { return }
-private extension GameManager {
- func randomString(length: Int = 5) -> String {
- let letters = "<>"
- let lettersArray = Array(letters)
- let symbolArray = [">>", "<<", "--"]
+ let sumArray = arrayTimes.reduce(0, +)
+ let avrgArray = arrayTimes.count > 0 ? sumArray / arrayTimes.count : 0
+ let procentsCorrect = Float(correctAnswers) / Float(countAllGame) * 100
- let randSymbol = arc4random_uniform(UInt32(symbolArray.count))
- let randLetters = arc4random_uniform(UInt32(lettersArray.count))
+ clearData()
+
+ delegate?.setEnableButton(isEnable: false)
- return symbolArray[Int(randSymbol)] + String(lettersArray[Int(randLetters)]) + symbolArray[Int(randSymbol)]
+ delegate?.resultTest(
+ avrgTime: avrgArray,
+ procentCorrect: Int(procentsCorrect),
+ data: nil,
+ dataArray: resultManager.oneGameDataResult,
+ isShowResults: gameParameters.showResults,
+ minAccuracy: gameParameters.minimumAccuracy
+ )
}
func isEndGame() -> Bool {
guard let gameParameters = gameParameters else { return false }
- if countTest == gameParameters.trials.count {
- let sumArray = arrayTimes.reduce(0, +)
- var avrgArray: Int = 0
- if arrayTimes.count != 0 {
- avrgArray = sumArray / arrayTimes.count
- }
- let procentsCorrect = Float(correctAnswers) / Float(countAllGame) * 100
- if !gameParameters.showFixation {
- setEndTimeViewingImage(time: CACurrentMediaTime(), isStart: true, type: .fixations)
- }
- delegate?.resultTest(avrgTime: avrgArray, procentCorrect: Int(procentsCorrect), data: nil, dataArray: resultManager.oneGameDataResult, isShowResults: gameParameters.showResults, minAccuracy: gameParameters.minimumAccuracy)
- clearData()
- return true
- } else {
- return false
- }
+ return countTest >= gameParameters.trials.count
+ }
+
+ func clearData() {
+ resultManager.cleanData()
+ countTest = -1
+ correctAnswers = 0
+ arrayTimes = []
+ invalidateTimers()
}
func invalidateTimers() {
timeResponse?.invalidate()
timerSetText?.invalidate()
}
+}
+private extension GameManager {
func updateButtonTitle() {
guard let gameParameters = gameParameters else { return }
+ guard countTest < gameParameters.trials.count else { return }
- if gameParameters.trials[countTest].choices.count == 2 {
- if
- let leftImage = URL(string: gameParameters.trials[countTest].choices[0].name.en),
- let rightImage = URL(string: gameParameters.trials[countTest].choices[1].name.en),
- gameParameters.trials[countTest].choices[0].name.en.contains("https"),
- gameParameters.trials[countTest].choices[1].name.en.contains("https") {
- delegate?.updateTitleButton(left: nil, right: nil, leftImage: leftImage, rightImage: rightImage, countButton: 2)
- }
- else if
- let leftImage = URL(string: gameParameters.trials[countTest].choices[0].name.en),
- gameParameters.trials[countTest].choices[0].name.en.contains("https"),
- !gameParameters.trials[countTest].choices[1].name.en.contains("https") {
- delegate?.updateTitleButton(left: nil, right: gameParameters.trials[countTest].choices[1].name.en, leftImage: leftImage, rightImage: nil, countButton: 2)
- }
- else if
- let rightImage = URL(string: gameParameters.trials[countTest].choices[1].name.en),
- gameParameters.trials[countTest].choices[1].name.en.contains("https"),
- !gameParameters.trials[countTest].choices[0].name.en.contains("https") {
- delegate?.updateTitleButton(left: gameParameters.trials[countTest].choices[0].name.en, right: nil, leftImage: nil, rightImage: rightImage, countButton: 2)
- }
- else {
- delegate?.updateTitleButton(left: gameParameters.trials[countTest].choices[0].name.en, right: gameParameters.trials[countTest].choices[1].name.en, leftImage: nil, rightImage: nil, countButton: 2)
+ let choices = gameParameters.trials[countTest].choices
+ let countButton = choices.count
+
+ var leftTitle: String? = nil
+ var rightTitle: String? = nil
+ var leftImage: URL? = nil
+ var rightImage: URL? = nil
+
+ if countButton >= 1 {
+ let leftChoice = choices[0].name.en
+ if let url = URL(string: leftChoice), leftChoice.contains("https") {
+ leftImage = url
+ } else {
+ leftTitle = leftChoice
}
- } else {
- if
- let leftImage = URL(string: gameParameters.trials[countTest].choices[0].name.en),
- gameParameters.trials[countTest].choices[0].name.en.contains("https") {
- delegate?.updateTitleButton(left: nil, right: nil, leftImage: leftImage, rightImage: nil, countButton: 1)
+ }
+
+ if countButton == 2 {
+ let rightChoice = choices[1].name.en
+ if let url = URL(string: rightChoice), rightChoice.contains("https") {
+ rightImage = url
} else {
- delegate?.updateTitleButton(left: gameParameters.trials[countTest].choices[0].name.en, right: nil, leftImage: nil, rightImage: nil, countButton: 1)
+ rightTitle = rightChoice
}
}
+
+ delegate?.updateTitleButton(
+ left: leftTitle,
+ right: rightTitle,
+ leftImage: leftImage,
+ rightImage: rightImage,
+ countButton: countButton
+ )
}
}