Advertisement
Guest User

Untitled

a guest
Jul 13th, 2018
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Swift 10.08 KB | None | 0 0
  1. import UIKit
  2. import Foundation
  3. import PlaygroundSupport
  4.  
  5. import AVFoundation
  6. PlaygroundPage.current.needsIndefiniteExecution = true
  7.  
  8.  
  9. class AsyncOperation: Operation {
  10.    
  11.     internal enum State {
  12.         case pending, executing, finished
  13.     }
  14.    
  15.     private var managedKeyPaths: [KeyPath<AsyncOperation, Bool>] {
  16.         return [\AsyncOperation.isExecuting, \AsyncOperation.isFinished]
  17.     }
  18.  
  19.     internal var state = State.pending {
  20.         willSet { managedKeyPaths.forEach { willChangeValue(for: $0) } }
  21.         didSet { managedKeyPaths.forEach { didChangeValue(for: $0) } }
  22.     }
  23.    
  24.     override var isAsynchronous: Bool {
  25.         return true
  26.     }
  27.    
  28.     override var isExecuting: Bool {
  29.         return state == .executing
  30.     }
  31.    
  32.     override var isFinished: Bool {
  33.         return state == .finished
  34.     }
  35. }
  36.  
  37. extension Operation {
  38.     func cancelRecursively(removingCompletions: Bool = true) {
  39.         if removingCompletions {
  40.             completionBlock = nil
  41.         }
  42.         cancel()
  43.         dependencies.forEach { $0.cancelRecursively(removingCompletions: removingCompletions) }
  44.     }
  45. }
  46.  
  47. extension Array where Element: Operation {
  48.     func cancel() {
  49.         self.forEach { $0.cancel() }
  50.     }
  51. }
  52.  
  53.  
  54. extension Array where Element: LessonOperation {
  55.     func connected() -> Array {
  56.         zip(self, self[1...]).forEach { $0.1.addDependency($0.0); $0.0.parent = $0.1 }
  57.         return self
  58.     }
  59. }
  60.  
  61. extension ArraySlice where Element: Operation {
  62.     func cancel() {
  63.         self.forEach { $0.cancel() }
  64.     }
  65. }
  66.    
  67. extension OperationQueue {
  68.     func addWithDependencies(_ op: Operation) {
  69.         addOperation(op)
  70.         op.dependencies.forEach { self.addWithDependencies($0) }
  71.     }
  72.    
  73.     func addSeries(_ ops: [Operation]) {
  74.         guard let target = ops.last else { return }
  75.         addWithDependencies(target)
  76.     }
  77. }
  78.  
  79. protocol ReplicatableOperation {
  80.     func replicate() -> LessonOperation
  81. }
  82.  
  83. protocol ChildOperation: class {
  84.     var parent: LessonOperation? { get set }
  85. }
  86.  
  87.  
  88. protocol AsyncOperationDelegate {
  89.     func operationDidStartExecuting(_ op: Operation)
  90. }
  91.  
  92. protocol MonitoredAsyncOperation: class {
  93.     var delegate: AsyncOperationDelegate? { get set }
  94. }
  95.  
  96. class LessonOperation: AsyncOperation & MonitoredAsyncOperation & ChildOperation & ReplicatableOperation {
  97.     var parent: LessonOperation?
  98.     var delegate: AsyncOperationDelegate?
  99.    
  100.     func replicate() -> LessonOperation {
  101.         preconditionFailure("not implemented")
  102.     }
  103. }
  104.  
  105. extension LessonOperation {
  106.     func restart(on queue: OperationQueue = OperationQueue.main, after timeout: Double = 0.0, completion: @escaping (LessonOperation) -> ()) {
  107.         let rep = self.replicate()
  108.         parent?.addDependency(rep)
  109.         self.cancel()
  110.         DispatchQueue.global(qos: .userInteractive).asyncAfter(deadline: .now() + timeout) {
  111.             queue.addOperation(rep)
  112.             completion(rep)
  113.         }
  114.     }
  115. }
  116.  
  117. extension LessonOperation {
  118.     func cycle(on queue: OperationQueue, onProduce: @escaping (LessonOperation) -> ()) {
  119.         let rep = self.replicate()
  120.         rep.parent = self.parent
  121.         parent?.addDependency(rep)
  122.         queue.addOperation(rep)
  123.         onProduce(rep)
  124.         self.completionBlock = {
  125.             rep.cycle(on: queue, onProduce: onProduce)
  126.         }
  127.     }
  128.    
  129.     func stopCycle() {
  130.         parent?.dependencies.forEach { $0.cancelRecursively() }
  131.     }
  132. }
  133.  
  134.  
  135. extension LessonOperation {
  136.     override func addDependency(_ op: Operation) {
  137.         super.addDependency(op)
  138.         if let op = op as? LessonOperation {
  139.             op.parent = self
  140.         }
  141.     }
  142. }
  143.  
  144. extension LessonOperation {
  145.     func interrupt(with op: LessonOperation, on queue: OperationQueue, completion: @escaping (LessonOperation, LessonOperation) -> ()) {
  146.         let rep = self.replicate()
  147.        
  148.         parent?.addDependency(rep)
  149.         rep.addDependency(op)
  150.        
  151.         self.cancel()
  152.        
  153.         queue.addOperation(op)
  154.         queue.addOperation(rep)
  155.        
  156.         completion(op, rep)
  157.     }
  158. }
  159.  
  160.  
  161. extension LessonOperation {
  162.     func replace(with op: LessonOperation, on queue: OperationQueue, completion: @escaping (LessonOperation) -> ()) {
  163.         parent?.addDependency(op)
  164.         self.cancel()
  165.        
  166.         queue.addOperation(op)
  167.  
  168.         completion(op)
  169.     }
  170. }
  171.  
  172.  
  173.  class GuidingOperation: LessonOperation, AVSpeechSynthesizerDelegate {
  174.     let text: String
  175.     let talk: AVSpeechSynthesizer
  176.     let lang: String
  177.    
  178.     override var name: String? {
  179.         get { return super.name ?? text }
  180.         set { super.name = newValue }
  181.     }
  182.    
  183.     override func replicate() -> GuidingOperation {
  184.         return GuidingOperation(text: text, talk: talk)
  185.     }
  186.    
  187.     func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) {
  188.         state = .finished
  189.     }
  190.    
  191.     func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didCancel utterance: AVSpeechUtterance) {
  192.         state = .finished
  193.     }
  194.    
  195.     func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didStart utterance: AVSpeechUtterance) {
  196.         state = .executing
  197.         delegate?.operationDidStartExecuting(self)
  198.     }
  199.    
  200.     init(text: String, lang: String = "en", talk: AVSpeechSynthesizer) {
  201.         self.text = text
  202.         self.lang = lang
  203.         self.talk = talk
  204.         super.init()
  205.     }
  206.    
  207.     override func cancel() {
  208.         super.cancel()
  209.         talk.stopSpeaking(at: .word)
  210.         DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) { [weak self] in
  211.             self?.state = .finished
  212.         }
  213.     }
  214.    
  215.     override func start() {
  216.         guard !isCancelled else {
  217.             state = .finished
  218.             return
  219.         }
  220.         talk.delegate = self
  221.         speak()
  222.     }
  223.    
  224.     func speak() {
  225.         let utterance = AVSpeechUtterance(string: text)
  226.         let voice = AVSpeechSynthesisVoice(language: lang)
  227.         utterance.voice = voice
  228.         talk.speak(utterance)
  229.     }
  230. }
  231.  
  232. class ListeningOperation: GuidingOperation {
  233.     override func replicate() -> ListeningOperation {
  234.         return ListeningOperation(text: text, lang: lang, talk: talk)
  235.     }
  236. }
  237.  
  238. class TargetOperation: LessonOperation {
  239.    
  240.     override var name: String? {
  241.         get { return target }
  242.         set { super.name = newValue }
  243.     }
  244.    
  245.     let target: String
  246.    
  247.     init(target: String) {
  248.         self.target = target
  249.         super.init()
  250.     }
  251.    
  252.     override func replicate() -> TargetOperation {
  253.         return TargetOperation(target: target)
  254.     }
  255.    
  256.     override func start() {
  257.         guard !isCancelled else {
  258.             state = .finished
  259.             return
  260.         }
  261.         state = .executing
  262.         state = .finished
  263.     }
  264. }
  265.  
  266. class PauseOperation: LessonOperation {
  267.     override func cancel() {
  268.         super.cancel()
  269.         state = .finished
  270.     }
  271.    
  272.     override func main() {
  273.         guard !isCancelled else {
  274.             state = .finished
  275.             return
  276.         }
  277.         state = .executing
  278.     }
  279.    
  280.     override func replicate() -> PauseOperation {
  281.         return PauseOperation()
  282.     }
  283. }
  284.  
  285.  
  286. class Lesson: AsyncOperationDelegate {
  287.     var steps = [LessonOperation]()
  288.     var currentStep: LessonOperation?
  289.     var onFinish: (() -> ())?
  290.    
  291.     let internalQueue = OperationQueue()
  292.     var pause: PauseOperation?
  293.    
  294.     func pauseCurrent(skipInterrupted: Bool = false) {
  295.         let pause = PauseOperation()
  296.         self.pause = pause
  297.         skipInterrupted ? replaceCurrent(with: pause) : interruptCurrent(with: pause)
  298.     }
  299.    
  300.     func resumeCurrent() {
  301.         pause?.cancel()
  302.     }
  303.    
  304.     init(steps: [LessonOperation], onFinish: (() -> ())? = nil) {
  305.         steps.forEach { addStep($0) }
  306.         self.onFinish = onFinish
  307.         steps.last?.completionBlock = { [weak self] in
  308.             self?.onFinish?()
  309.         }
  310.     }
  311.    
  312.     func operationDidStartExecuting(_ op: Operation) {
  313.         self.currentStep = op as? LessonOperation
  314.     }
  315.    
  316.     func addStep(_ op: LessonOperation) {
  317.         op.delegate = self
  318.         steps.append(op)
  319.     }
  320.    
  321.     func start() {
  322.         OperationQueue.main.addSeries(steps.connected())
  323.     }
  324.    
  325.     func cycleCurrent() {
  326.         currentStep?.cycle(on: .main) { [weak self] produced in
  327.             produced.delegate = self
  328.         }
  329.     }
  330.    
  331.     func stopCycleCurrent() {
  332.         currentStep?.stopCycle()
  333.     }
  334.    
  335.     func restartCurrent() {
  336.         currentStep?.restart(on: .main, after: 0) { [weak self] produced in
  337.             produced.delegate = self
  338.         }
  339.     }
  340.    
  341.     func skipCurrent() {
  342.         currentStep?.cancel()
  343.     }
  344.    
  345.     func replaceCurrent(with op: LessonOperation) {
  346.         currentStep?.replace(with: op, on: .main) { [weak self] op in
  347.             op.delegate = self
  348.         }
  349.     }
  350.    
  351.     func interruptCurrent(with op: LessonOperation) {
  352.         currentStep?.interrupt(with: op, on: .main) { [weak self] op, interrupted in
  353.             op.delegate = self
  354.             interrupted.delegate = self
  355.         }
  356.     }
  357. }
  358.  
  359. let talk = AVSpeechSynthesizer()
  360.  
  361. let step1 = GuidingOperation(text: "This is the very first lesson in learning a second language, the Spanish Language!", talk: talk)
  362. let step2 = GuidingOperation(text: "This lesson begins with simple greetings.", talk: talk)
  363. let step3 = ListeningOperation(text: "¡Hola, Roberto! ¿Cómo estás?", lang: "es", talk: talk)
  364. let step4 = GuidingOperation(text: "Hello Roberto, how are you?", talk: talk)
  365. let step5 = TargetOperation(target: "Finish Lesson")
  366.  
  367. let lesson = Lesson(steps: [step1, step3, step4, step5]) {
  368.     print("Lesson is finished.")
  369. }
  370.  
  371. lesson.start()
  372. lesson.pauseCurrent(skipInterrupted: true)
  373. lesson.resumeCurrent()
  374. lesson.interruptCurrent(with: step2)
  375. lesson.resumeCurrent()
  376.  
  377. lesson.skipCurrent()
  378. lesson.cycleCurrent()
  379. lesson.skipCurrent()
  380. lesson.cycleCurrent()
  381. lesson.stopCycleCurrent()
  382. lesson.restartCurrent()
  383. lesson.skipCurrent()
  384. lesson.stopCycleCurrent()
  385. lesson.stopCycleCurrent()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement