OOAIViewModel.swift 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. //
  2. // OOAIViewModel.swift
  3. // O2Platform
  4. //
  5. // Created by FancyLou on 2018/9/10.
  6. // Copyright © 2018 zoneland. All rights reserved.
  7. //
  8. import UIKit
  9. import Promises
  10. /// 活动状态
  11. ///
  12. /// - listen: 正在听命令
  13. /// - speak: 正在说话
  14. enum AIActivityStatus {
  15. case listen
  16. case speak
  17. }
  18. /// 当前状态
  19. ///
  20. /// - normal: 普通状态
  21. /// - working: 正在处理工作
  22. enum AIStatus {
  23. case normal
  24. case working
  25. }
  26. /// 当前路由 路由就是接下来怎么处理
  27. ///
  28. /// - listen: 开始听命令
  29. /// - finish: 退出AI语音助手
  30. /// - findtask: 查找待办工作
  31. /// - dealTaskWithCommand: 根据命令处理工作
  32. /// - dealTaskWithNeural: 根据人工智能算法处理工作
  33. enum AICommandRoute {
  34. case listen
  35. case finish
  36. case findtask
  37. case dealTaskWithCommand
  38. case dealTaskWithNeural
  39. }
  40. protocol OOAIVoiceControllerDelegate {
  41. func changeActivityStatus(status: AIActivityStatus?)
  42. func changeSpeakMessage(message: String?)
  43. func finishController()
  44. }
  45. class OOAIViewModel: NSObject {
  46. override init() {
  47. super.init()
  48. }
  49. private let tulingAPI = OOMoyaProvider<Tuling123API>()
  50. private let taskAPI = OOMoyaProvider<OOTaskAPI>()
  51. private var taskList:[O2TodoTask] = []
  52. private var currentDealTaskIndex: Int = -1
  53. /// 前台ui获取当前任务,展现路由命令给UI
  54. func getCurrentDealTask() -> O2TodoTask? {
  55. if self.currentDealTaskIndex >= 0 && self.taskList.count > 0 {
  56. return self.taskList[self.currentDealTaskIndex]
  57. }
  58. return nil
  59. }
  60. /// 当前路由
  61. private var commandRoute: AICommandRoute = .listen
  62. /// 当前状态
  63. private var aiStatus: AIStatus = .normal
  64. /// 前台ui获取当前状态
  65. func getAIStatus() -> AIStatus {
  66. return aiStatus
  67. }
  68. /// ViewController里面实现处理前台页面UI相关的
  69. var aiVoiceControllerDelegate: OOAIVoiceControllerDelegate?
  70. //MARK: - MVVM arguments
  71. /// 活动状态 当前是在listen 还是在speak
  72. var activityStatus:AIActivityStatus? {
  73. didSet {
  74. self.aiVoiceControllerDelegate?.changeActivityStatus(status: activityStatus)
  75. }
  76. }
  77. /// 命令 listen后得到的命令
  78. var command: String? {
  79. didSet {
  80. if command != nil {
  81. listenFinish()
  82. }else {
  83. listenError()
  84. }
  85. }
  86. }
  87. /// 语音合成的文字,需要显示到UI上的
  88. var speakMessage: String? {
  89. didSet {
  90. self.aiVoiceControllerDelegate?.changeSpeakMessage(message: speakMessage)
  91. }
  92. }
  93. }
  94. extension OOAIViewModel {
  95. /// 前台说话结束后执行
  96. func speakFinish() {
  97. switch commandRoute {
  98. case .listen:
  99. self.activityStatus = .listen
  100. break
  101. case .finish:
  102. self.aiVoiceControllerDelegate?.finishController()
  103. break
  104. case .findtask:
  105. self.findTask()
  106. break
  107. case .dealTaskWithCommand:
  108. self.askHowToDealWithNextTask()
  109. break
  110. case .dealTaskWithNeural:
  111. self.dealWorkWithNeural()
  112. break
  113. }
  114. }
  115. private func listenFinish() {
  116. func isCurrentTaskRouteCommand() -> Bool {
  117. let task = self.taskList[self.currentDealTaskIndex]
  118. return (task.routeNameList?.contains(self.command!) == true)
  119. }
  120. if self.aiStatus == .normal {
  121. if isInStopCommand() {
  122. self.speakMessage = "感谢使用,下次再见!"
  123. self.commandRoute = .finish
  124. self.activityStatus = .speak
  125. }else if isInTaskCommand() {
  126. self.speakMessage = "正在查询您的工作"
  127. self.commandRoute = .findtask
  128. self.activityStatus = .speak
  129. }else {
  130. self.searchFromTuling()
  131. }
  132. }else {
  133. if isInTaskNeuralCommand() {
  134. self.speakMessage = "正在生成人工神经网络.提取您的处理数据进行分析."
  135. self.commandRoute = .dealTaskWithNeural
  136. self.activityStatus = .speak
  137. }else if isCurrentTaskRouteCommand() {
  138. self.dealWork(routeName: self.command!)
  139. }else if isInIgnoreCommand() {
  140. self.currentDealTaskIndex = self.currentDealTaskIndex + 1
  141. self.speakMessage = "好的!"
  142. self.commandRoute = .dealTaskWithCommand
  143. self.activityStatus = .speak
  144. }else if isInStopCommand() {
  145. self.speakMessage = "好的!还有什么需要我为您做的吗?"
  146. self.aiStatus = .normal
  147. self.commandRoute = .listen
  148. self.activityStatus = .speak
  149. }else {
  150. self.speakMessage = "对不起,我无法处理这个命令。您可以选择 退出工作 或 继续下一个工作"
  151. self.commandRoute = .listen
  152. self.activityStatus = .speak
  153. }
  154. }
  155. }
  156. private func listenError() {
  157. self.speakMessage = "对不起,我没有听清!"
  158. self.activityStatus = .speak
  159. }
  160. private func askHowToDealWithNextTask() {
  161. if self.currentDealTaskIndex >= self.taskList.count {
  162. self.aiStatus = .normal
  163. self.commandRoute = .listen
  164. self.speakMessage = "所有工作已经处理完成!还有什么需要我为您做的吗?"
  165. self.activityStatus = .speak
  166. }else {
  167. if self.currentDealTaskIndex < 0 {
  168. self.currentDealTaskIndex = 0
  169. }
  170. let task = self.taskList[self.currentDealTaskIndex]
  171. let person = task.person?.split(separator: "@").first ?? ""
  172. let routeList = task.routeNameList?.joined(separator: "或") ?? ""
  173. let processName = task.processName ?? ""
  174. let title = task.title ?? ""
  175. self.commandRoute = .listen
  176. self.speakMessage = "来自\(person)的\(processName),标题:\(title)"+" , 您可以选择:\(routeList)"
  177. self.activityStatus = .speak
  178. }
  179. }
  180. private func dealWorkWithNeural() {
  181. let param:[String:String] = ["type":""]
  182. let task = self.taskList[self.currentDealTaskIndex]
  183. self.taskAPI.request(.taskSubmitNeural(task.id!, param), completion: { result in
  184. let response = OOResult<BaseModelClass<[O2TodoTaskNeural]>>(result)
  185. if response.isResultSuccess() {
  186. self.currentDealTaskIndex = self.currentDealTaskIndex + 1
  187. self.speakMessage = "工作处理完成!"
  188. self.commandRoute = .dealTaskWithCommand
  189. self.activityStatus = .speak
  190. }else {
  191. let routeList = task.routeNameList?.joined(separator: "或") ?? ""
  192. self.commandRoute = .listen
  193. self.speakMessage = "任务处理失败,当前任务无法自动判断,您可以选择:\(routeList)"
  194. self.activityStatus = .speak
  195. }
  196. })
  197. }
  198. private func dealWork(routeName: String) {
  199. let param:[String:String] = ["routeName":routeName, "opinion":""]
  200. let task = self.taskList[self.currentDealTaskIndex]
  201. self.taskAPI.request(.taskSaveAndSubmit(task.id!, (param as Dictionary<String, AnyObject>)), completion: { result in
  202. let response = OOResult<BaseModelClass<O2WorkPostResult>>(result)
  203. if response.isResultSuccess() {
  204. self.currentDealTaskIndex = self.currentDealTaskIndex + 1
  205. self.speakMessage = "工作处理完成!"
  206. self.commandRoute = .dealTaskWithCommand
  207. self.activityStatus = .speak
  208. }else {
  209. let routeList = task.routeNameList?.joined(separator: "或") ?? ""
  210. self.commandRoute = .listen
  211. self.speakMessage = "任务处理失败,您可以选择:\(routeList)"
  212. self.activityStatus = .speak
  213. }
  214. })
  215. }
  216. private func findTask() {
  217. self.taskAPI.request(.taskList(OOTaskPageParameter()), completion: { result in
  218. let response = OOResult<BaseModelClass<[O2TodoTask]>>(result)
  219. if response.isResultSuccess() {
  220. if let data = response.model?.data {
  221. self.taskList = data
  222. self.speakMessage = "您有\(data.count)项工作需要处理."
  223. self.aiStatus = .working
  224. self.commandRoute = .dealTaskWithCommand //路由到处理工作
  225. }else {
  226. self.taskList = []
  227. self.speakMessage = "没有查询到需要处理的工作!还有什么需要我为您做的吗?"
  228. }
  229. self.activityStatus = .speak
  230. }else {
  231. self.taskList = []
  232. self.speakMessage = "没有查询到需要处理的工作!还有什么需要我为您做的吗?"
  233. self.activityStatus = .speak
  234. }
  235. })
  236. }
  237. private func searchFromTuling() {
  238. let post = TulingPostModel()
  239. post.key = "1bbde256119f4d6eaf3c25e67dedbd38"
  240. post.info = self.command
  241. self.tulingAPI.request(.openapi(post)) { (result) in
  242. switch result {
  243. case .failure(let error):
  244. print(error)
  245. self.speakMessage = "更多功能还在升级学习中,非常抱歉!"
  246. self.commandRoute = .listen
  247. self.activityStatus = .speak
  248. break
  249. case .success(let data):
  250. let res = data.mapObject(TulingResponseModel.self)
  251. if let code = res?.code {
  252. if code == "100000" {
  253. self.speakMessage = res?.text
  254. }else if code == "40001" || code == "40002" || code == "40004" || code == "40007" {
  255. print("图灵识别错误")
  256. self.speakMessage = "更多功能还在升级学习中,非常抱歉!"
  257. }else {
  258. print("图灵识别错误, 未知的code。。。。。。。")
  259. self.speakMessage = "更多功能还在升级学习中,非常抱歉!"
  260. }
  261. }else {
  262. print("图灵识别错误, 没有返回code。。。。。。。")
  263. self.speakMessage = "更多功能还在升级学习中,非常抱歉!"
  264. }
  265. self.commandRoute = .listen
  266. self.activityStatus = .speak
  267. break
  268. }
  269. }
  270. }
  271. private func isInStopCommand() -> Bool {
  272. guard let c = self.command else {
  273. return false
  274. }
  275. return AI_COMMAND_STOP.contains(c)
  276. }
  277. private func isInTaskCommand() -> Bool {
  278. guard let c = self.command else {
  279. return false
  280. }
  281. if AI_COMMAND_TASK.contains(c) {
  282. return true
  283. }else if AI_COMMAND_TASK_TYPO.contains(c) {
  284. return true
  285. }
  286. return false
  287. }
  288. private func isInTaskNeuralCommand() -> Bool {
  289. guard let c = self.command else {
  290. return false
  291. }
  292. return AI_COMMAND_TASK_NEURAL.contains(c)
  293. }
  294. private func isInIgnoreCommand() -> Bool {
  295. guard let c = self.command else {
  296. return false
  297. }
  298. return AI_COMMAND_IGNORE.contains(c)
  299. }
  300. }