TakeQuizViewController.swift 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. //
  2. // TakeQuizViewController.swift
  3. // Learn Genie
  4. //
  5. // Created by Suraj Kumar Mandal on 15/09/21.
  6. //
  7. import UIKit
  8. import Alamofire
  9. class TakeQuizViewController: UIViewController {
  10. @IBOutlet var quesHeadLabel: UILabel!
  11. @IBOutlet var timerLabel: UILabel!
  12. @IBOutlet var questionLabel: UILabel!
  13. @IBOutlet var nextButton: UIButton!
  14. @IBOutlet var previousButton: UIButton!
  15. @IBOutlet var cancelButton: UIButton!
  16. @IBOutlet var minuteSecondLabel: UILabel!
  17. @IBOutlet var choiceCollectionView: UICollectionView!
  18. @IBOutlet var choiceCollectionViewHeight: NSLayoutConstraint!
  19. //Result submit pop up view outlets
  20. @IBOutlet var submitPopupView: UIView!
  21. @IBOutlet var resultImageView: UIImageView!
  22. @IBOutlet var resultHeadingLabel: UILabel!
  23. @IBOutlet var resultSubHeadingLabel: UILabel!
  24. @IBOutlet var tryAgainButton: UIButton!
  25. @IBOutlet var popUpNextButton: UIButton!
  26. @IBOutlet var viewAnswerButton: UIButton!
  27. var timer = Timer()
  28. var secondsLeft: Int = 300
  29. var quesIndex = 0
  30. var selectedAnswer = [SelectedAnswerModel]()
  31. let studentId = UserDefaultsConstant.getIntValueFromUserDefults(for: Constant.studentId) as! Int
  32. var topicId = Int()
  33. var quesBankId = Int()
  34. var quesId = Int()
  35. var selectedChoiceId = Int()
  36. var answerChoiceId = Int()
  37. var choiceArray = [Int]()
  38. var selectedButtonIndexPath: IndexPath?
  39. //Not changing values in quiz process
  40. var levelId = Int()
  41. var runs = Int()
  42. var wickets = Int()
  43. override func viewDidLoad() {
  44. super.viewDidLoad()
  45. // Do any additional setup after loading the view.
  46. choiceCollectionView.delegate = self
  47. choiceCollectionView.dataSource = self
  48. ApiManager.generateCookie()
  49. }
  50. override func viewWillAppear(_ animated: Bool) {
  51. self.timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.runScheduledTask), userInfo: nil, repeats: true)
  52. setupUI()
  53. selectedAnswer.removeAll()
  54. }
  55. override func viewDidLayoutSubviews() {
  56. super.viewDidLayoutSubviews()
  57. let height = choiceCollectionView.collectionViewLayout.collectionViewContentSize.height
  58. choiceCollectionViewHeight.constant = height
  59. self.view.layoutIfNeeded()
  60. }
  61. func setupUI() {
  62. getQuesBankId()
  63. submitPopupView.isHidden = true
  64. self.quesHeadLabel.text = "\(Helper.translateText(inputText: "Question")) \(quesIndex+1)"
  65. if quesIndex == 4 {
  66. nextButton.setTitle(Helper.translateText(inputText: "SUBMIT"), for: .normal)
  67. } else {
  68. nextButton.setTitle(Helper.translateText(inputText: "Next"), for: .normal)
  69. }
  70. previousButton.setTitle(Helper.translateText(inputText: "Previous"), for: .normal)
  71. cancelButton.setTitle(Helper.translateText(inputText: "CANCEL"), for: .normal)
  72. nextButton.setTitle(Helper.translateText(inputText: "Next"), for: .normal)
  73. tryAgainButton.setTitle(Helper.translateText(inputText: "TRY AGAIN"), for: .normal)
  74. popUpNextButton.setTitle(Helper.translateText(inputText: "Next"), for: .normal)
  75. viewAnswerButton.setTitle(Helper.translateText(inputText: "View Answer"), for: .normal)
  76. minuteSecondLabel.text = "\(Helper.translateText(inputText: "Minutes")) : \(Helper.translateText(inputText: "Seconds"))"
  77. }
  78. @objc func runScheduledTask(_ runningTimer: Timer) {
  79. var minute: Int
  80. var second: Int
  81. secondsLeft -= 1
  82. if secondsLeft == 0 || secondsLeft < 0 {
  83. timerLabel.text = "00 : 00"
  84. timer.invalidate()
  85. getResult()
  86. saveScoreBoard()
  87. } else {
  88. minute = (secondsLeft % 3600) / 60
  89. second = (secondsLeft % 3600) % 60
  90. timerLabel.text = "\(String(format: "%02d", minute)) : \(String(format: "%02d", second))"
  91. print()
  92. }
  93. }
  94. func getQuesBankId() {
  95. let topicData = DBManager.sharedInstance.database.objects(TopicModel.self)
  96. for item in topicData {
  97. if self.topicId == item.id {
  98. self.levelId = item.levelId
  99. self.quesBankId = item.questionBankId
  100. self.choiceArray.removeAll()
  101. let quesBankData = DBManager.sharedInstance.database.objects(QuestionBankModel.self)
  102. for item in quesBankData {
  103. if self.quesBankId == item.id {
  104. print(item.questions[quesIndex])
  105. let quesData = DBManager.sharedInstance.database.objects(QuestionModel.self)
  106. for data in quesData {
  107. if data.id == item.questions[quesIndex].id {
  108. print("Current Question: \(data.content)")
  109. self.quesId = data.id
  110. self.answerChoiceId = data.answerId
  111. self.questionLabel.text = Helper.translateText(inputText: data.content)
  112. for choice in data.choices {
  113. let id = choice.id
  114. self.choiceArray.append(id)
  115. }
  116. }
  117. }
  118. }
  119. }
  120. }
  121. }
  122. print("Current choices: \(choiceArray)")
  123. choiceCollectionView.reloadData()
  124. }
  125. func getChoice(id:Int) -> String {
  126. let choiceData = DBManager.sharedInstance.database.objects(ChoiceModel.self)
  127. var choiceString = ""
  128. for choice in choiceData {
  129. if id == choice.id {
  130. choiceString = choice.content
  131. }
  132. }
  133. return choiceString
  134. }
  135. func saveSelectedChoice() {
  136. if let row = self.selectedAnswer.firstIndex(where: {$0.quesId == self.quesId}) {
  137. print("Before update: \(selectedAnswer[row])")
  138. selectedAnswer[row].choiceId = self.selectedChoiceId
  139. print("After update: \(selectedAnswer[row])")
  140. } else {
  141. let answer = SelectedAnswerModel(quesId: quesId, choiceId: selectedChoiceId, answerId: answerChoiceId)
  142. selectedAnswer.append(answer)
  143. }
  144. for item in selectedAnswer {
  145. print("Saved QuesId: \(item.quesId), Saved ChoiceId: \(item.choiceId), Saved Answer: \(item.answerId)")
  146. }
  147. }
  148. func getSelectedChoice() {
  149. if let row = self.selectedAnswer.firstIndex(where: {$0.quesId == self.quesId}) {
  150. selectedAnswer[row].choiceId = self.selectedChoiceId
  151. }
  152. }
  153. @objc func selectChoice(sender: UIButton) {
  154. let buttonPosition:CGPoint = sender.convert(CGPoint.zero, to:self.choiceCollectionView)
  155. let indexPath = self.choiceCollectionView.indexPathForItem(at: buttonPosition)
  156. if indexPath != selectedButtonIndexPath {
  157. selectedButtonIndexPath = indexPath
  158. } else { // If same button selected, deselect? Unless you want a different behavior
  159. selectedButtonIndexPath = nil
  160. }
  161. choiceCollectionView.reloadData()
  162. }
  163. func getCorrectAnswerNumber() -> Int {
  164. var score = 0
  165. for answer in selectedAnswer {
  166. if answer.choiceId == answer.answerId {
  167. score += 1
  168. }
  169. }
  170. return score
  171. }
  172. func getResult() {
  173. switch getCorrectAnswerNumber() {
  174. case 0, 1:
  175. resultImageView.image = UIImage(named: "i_run_out")
  176. resultHeadingLabel.text = Helper.translateText(inputText: "Oh No You are Out Better luck next time")
  177. resultSubHeadingLabel.text = "\(Helper.translateText(inputText: "You have got")) \(getCorrectAnswerNumber())/5 \(Helper.translateText(inputText: "questions right"))"
  178. runs = 0
  179. wickets = 1
  180. return
  181. case 2:
  182. resultImageView.image = UIImage(named: "i_run_two")
  183. resultHeadingLabel.text = Helper.translateText(inputText: "It\'s a two Try Again")
  184. resultSubHeadingLabel.text = "\(Helper.translateText(inputText: "You have got")) \(getCorrectAnswerNumber())/5 \(Helper.translateText(inputText: "questions right"))"
  185. runs = 0
  186. wickets = 0
  187. return
  188. case 3:
  189. resultImageView.image = UIImage(named: "i_run_three")
  190. resultHeadingLabel.text = Helper.translateText(inputText: "It\'s a three Nice Hit")
  191. resultSubHeadingLabel.text = "\(Helper.translateText(inputText: "You have got")) \(getCorrectAnswerNumber())/5 \(Helper.translateText(inputText: "questions right"))"
  192. runs = 3
  193. wickets = 0
  194. return
  195. case 4:
  196. resultImageView.image = UIImage(named: "i_run_four")
  197. resultHeadingLabel.text = Helper.translateText(inputText: "It\'s a four What a tremendous hit")
  198. resultSubHeadingLabel.text = "\(Helper.translateText(inputText: "You have got")) \(getCorrectAnswerNumber())/5 \(Helper.translateText(inputText: "questions right"))"
  199. runs = 4
  200. wickets = 0
  201. return
  202. case 5:
  203. resultImageView.image = UIImage(named: "i_run_six")
  204. resultHeadingLabel.text = Helper.translateText(inputText: "It\'s a six What a tremendous hit")
  205. resultSubHeadingLabel.text = "\(Helper.translateText(inputText: "You have got")) \(getCorrectAnswerNumber())/5 \(Helper.translateText(inputText: "questions right"))"
  206. runs = 6
  207. wickets = 0
  208. return
  209. default:
  210. return
  211. }
  212. }
  213. func saveScoreBoard() {
  214. if Reachability.isConnectedToNetwork() {
  215. let saveScore = [SaveScoreBoard]()
  216. var noOfAttempts = 0
  217. for quiz in saveScore {
  218. if quiz.topicId == self.topicId {
  219. noOfAttempts += 1
  220. } else {
  221. noOfAttempts = 1
  222. }
  223. }
  224. saveScoreboard(levelId: self.levelId, topicId: self.topicId, runs: self.runs, wickets: self.wickets, noOfAttempts: noOfAttempts)
  225. } else {
  226. var saveScore = [SaveScoreBoard]()
  227. let itemId = saveScore.count + 1
  228. var noOfAttempts = 0
  229. for quiz in saveScore {
  230. if quiz.topicId == self.topicId {
  231. noOfAttempts += 1
  232. } else {
  233. noOfAttempts = 1
  234. }
  235. }
  236. let newSaveScoreModel = SaveScoreBoard(id: itemId, levelId: levelId, topicId: topicId, runs: runs, wickets: wickets, noOfAttempts: noOfAttempts, student: studentId, synced: false)
  237. saveScore.append(newSaveScoreModel)
  238. DBManager.sharedInstance.addData(objs: saveScore)
  239. let quizTakenData = DBManager.sharedInstance.database.objects(SaveScoreBoard.self)
  240. print(quizTakenData.count)
  241. }
  242. }
  243. /*
  244. // MARK: - Navigation
  245. // In a storyboard-based application, you will often want to do a little preparation before navigation
  246. override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
  247. // Get the new view controller using segue.destination.
  248. // Pass the selected object to the new view controller.
  249. }
  250. */
  251. @IBAction func quizButtonAction(_ sender: UIButton) {
  252. switch sender.tag {
  253. case 0:
  254. if quesIndex > 0 {
  255. quesIndex -= 1
  256. setupUI()
  257. //getSelectedChoice()
  258. }
  259. break
  260. case 1:
  261. if quesIndex == 4 {
  262. saveSelectedChoice()
  263. Alert.showAlertWithAction(vc: self, title: Helper.translateText(inputText: "Are you sure, you want to submit the quiz?"), message: "\(Helper.translateText(inputText: "You have completed")) \(selectedAnswer.count) \(Helper.translateText(inputText: "out of")) 5 \(Helper.translateText(inputText: "questions"))", alertStyle: .alert, actionTitles: [Helper.translateText(inputText: "CANCEL"), Helper.translateText(inputText: "YES")], actionStyles: [.cancel, .default], actions: [{_ in
  264. print("cancel click")
  265. }, {[self]_ in
  266. print("yes click")
  267. timer.invalidate()
  268. getResult()
  269. saveScoreBoard()
  270. }])
  271. } else {
  272. if quesIndex < 4 {
  273. saveSelectedChoice()
  274. selectedButtonIndexPath = nil
  275. quesIndex += 1
  276. setupUI()
  277. }
  278. }
  279. break
  280. case 2:
  281. Alert.showAlertWithAction(vc: self, title: Helper.translateText(inputText: "Are you sure you want to exit the quiz?"), message: "", alertStyle: .alert, actionTitles: [Helper.translateText(inputText: "CANCEL"), Helper.translateText(inputText: "YES")], actionStyles: [.cancel, .default], actions: [{_ in
  282. print("cancel click")
  283. }, { [self]_ in
  284. print("yes click")
  285. timer.invalidate()
  286. self.navigationController?.popViewController(animated: true)
  287. }])
  288. break
  289. default:
  290. break
  291. }
  292. }
  293. @IBAction func resultPopupCloseAction(_ sender: Any) {
  294. submitPopupView.isHidden = true
  295. }
  296. @IBAction func resultPopupButtonAction(_ sender: UIButton) {
  297. switch sender.tag {
  298. case 0:
  299. submitPopupView.isHidden = true
  300. self.navigationController?.popViewController(animated: true)
  301. case 1:
  302. submitPopupView.isHidden = true
  303. self.navigationController?.popViewController(animated: true)
  304. case 2:
  305. //submitPopupView.isHidden = true
  306. DispatchQueue.main.async {
  307. let viewAnswerVC = self.storyboard?.instantiateViewController(withIdentifier: "ViewAnswerViewController") as! ViewAnswerViewController
  308. viewAnswerVC.selectedAnswer.removeAll()
  309. viewAnswerVC.selectedAnswer = self.selectedAnswer
  310. self.navigationController?.pushViewController(viewAnswerVC, animated: true)
  311. }
  312. default:
  313. return
  314. }
  315. }
  316. }
  317. extension TakeQuizViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
  318. func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
  319. return choiceArray.count
  320. }
  321. func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
  322. guard let cell: ChoiceCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "ChoiceCollectionViewCell", for: indexPath) as? ChoiceCollectionViewCell else {
  323. return UICollectionViewCell()
  324. }
  325. cell.choiceLabel.text = Helper.translateText(inputText: getChoice(id: choiceArray[indexPath.row]))
  326. cell.radioButton.tag = indexPath.row
  327. cell.radioButton.addTarget(self, action: #selector(selectChoice(sender:)), for: .touchUpInside)
  328. if let row = self.selectedAnswer.firstIndex(where: {$0.quesId == self.quesId}) {
  329. print(self.quesId)
  330. if selectedAnswer[row].choiceId == choiceArray[indexPath.row] {
  331. print(selectedAnswer[row].choiceId, choiceArray[indexPath.row])
  332. cell.radioButton.isSelected = true
  333. } else {
  334. cell.radioButton.isSelected = false
  335. }
  336. } else {
  337. if indexPath == selectedButtonIndexPath { // If button is selected
  338. cell.radioButton.isSelected = true
  339. self.selectedChoiceId = choiceArray[indexPath.row]
  340. } else { // If it is not selected
  341. cell.radioButton.isSelected = false
  342. }
  343. }
  344. return cell
  345. }
  346. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
  347. return CGSize(width: (collectionView.frame.size.width-10)/2, height: 70)
  348. }
  349. }
  350. extension UICollectionView {
  351. func deselectAllItems(animated: Bool) {
  352. guard let selectedItems = indexPathsForSelectedItems else { return }
  353. for indexPath in selectedItems { deselectItem(at: indexPath, animated: animated) }
  354. }
  355. }
  356. extension TakeQuizViewController {
  357. func saveScoreboard(levelId:Int, topicId:Int, runs:Int, wickets:Int, noOfAttempts: Int) {
  358. let url = "\(ApiUrl.BASE_URL + ApiUrl.API_SCOREBOARD)/save.json"
  359. print(url)
  360. let cookieValue = UserDefaultsConstant.getValueFromUserDefults(for: "cookieValue") ?? ""
  361. let headers: HTTPHeaders = [
  362. "Content-Type": "application/json",
  363. "Accept": "application/json",
  364. "Cookie": "\(Constant.CookieName) = \(cookieValue)"
  365. ]
  366. print(headers)
  367. let params: Parameters?
  368. params = [
  369. "student" : studentId,
  370. "level" : levelId,
  371. "topic" : topicId,
  372. "runs" : runs,
  373. "wickets" : wickets,
  374. "noOfAttempts" : noOfAttempts
  375. ]
  376. print(params!)
  377. AF.request(url, method: .post, parameters: params, encoding: JSONEncoding.default, headers: headers).responseJSON { response in
  378. switch response.result {
  379. case .success(let value):
  380. print(value)
  381. let scoreData = value as! NSDictionary
  382. let student = scoreData.value(forKey: "student") as! NSObject;
  383. let studentId = student.value(forKey: "id") as! NSNumber;
  384. let topic = scoreData.value(forKey: "topic") as! NSObject;
  385. let topicId = topic.value(forKey: "id") as! NSNumber;
  386. let level = scoreData.value(forKey: "level") as! NSObject;
  387. let levelId = level.value(forKey: "id") as! NSNumber;
  388. let runs = scoreData.value(forKey: "runs") as! NSNumber;
  389. let wickets = scoreData.value(forKey: "wickets") as! NSNumber;
  390. let noOfAttempts = scoreData.value(forKey: "noOfAttempts") as! NSNumber;
  391. var saveScoreModel = [SaveScoreBoard]()
  392. let id = saveScoreModel.count + 1
  393. let newSaveScoreModel = SaveScoreBoard(id: id, levelId: Int(truncating: levelId), topicId: Int(truncating: topicId), runs: Int(truncating: runs), wickets: Int(truncating: wickets), noOfAttempts: Int(truncating: noOfAttempts), student: Int(truncating: studentId), synced: true)
  394. saveScoreModel.append(newSaveScoreModel)
  395. DBManager.sharedInstance.addData(objs: saveScoreModel)
  396. let saveScoreDB = DBManager.sharedInstance.database.objects(SaveScoreBoard.self)
  397. print("save score count")
  398. print(saveScoreDB.count)
  399. self.submitPopupView.isHidden = false
  400. case .failure(let error):
  401. print(error)
  402. }
  403. }
  404. }
  405. }