@@ -8,15 +8,16 @@ final class GameControllerBarcodeParser {
88 /// Configuration for the barcode scanner
99 let configuration : HIDBarcodeParserConfiguration
1010 /// Callback that is triggered when a barcode scan completes (success or failure)
11- let onScan : ( Result < String , Error > ) -> Void
11+ let onScan : ( HIDBarcodeParserResult ) -> Void
1212
1313 private let timeProvider : TimeProvider
1414
1515 private var buffer = " "
1616 private var lastKeyPressTime : Date ?
17+ private var scanStartTime : Date ?
1718
1819 init ( configuration: HIDBarcodeParserConfiguration ,
19- onScan: @escaping ( Result < String , Error > ) -> Void ,
20+ onScan: @escaping ( HIDBarcodeParserResult ) -> Void ,
2021 timeProvider: TimeProvider = DefaultTimeProvider ( ) ) {
2122 self . configuration = configuration
2223 self . onScan = onScan
@@ -41,6 +42,12 @@ final class GameControllerBarcodeParser {
4142 } else {
4243 guard !excludedKeyCodes. contains ( keyCode) else { return }
4344 checkForTimeoutBetweenKeystrokes ( )
45+
46+ // Start timing on first character
47+ if buffer. isEmpty {
48+ scanStartTime = timeProvider. now ( )
49+ }
50+
4451 buffer. append ( character)
4552 }
4653 }
@@ -69,7 +76,10 @@ final class GameControllerBarcodeParser {
6976
7077 if let lastTime = lastKeyPressTime,
7178 currentTime. timeIntervalSince ( lastTime) > configuration. maximumInterCharacterTime {
72- onScan ( . failure( HIDBarcodeParserError . timedOut ( barcode: buffer) ) )
79+ let scanDurationMs = calculateScanDurationMs ( )
80+ let result = HIDBarcodeParserResult . failure ( error: HIDBarcodeParserError . timedOut ( barcode: buffer) , scanDurationMs: scanDurationMs)
81+
82+ onScan ( result)
7383 resetScan ( )
7484 }
7585
@@ -175,14 +185,24 @@ final class GameControllerBarcodeParser {
175185 private func resetScan( ) {
176186 buffer = " "
177187 lastKeyPressTime = nil
188+ scanStartTime = nil
189+ }
190+
191+ private func calculateScanDurationMs( ) -> Int {
192+ guard let startTime = scanStartTime else { return 0 }
193+ return Int ( timeProvider. now ( ) . timeIntervalSince ( startTime) * 1000 )
178194 }
179195
180196 private func processScan( ) {
181197 checkForTimeoutBetweenKeystrokes ( )
198+ let scanDurationMs = calculateScanDurationMs ( )
199+
182200 if buffer. count >= configuration. minimumBarcodeLength {
183- onScan ( . success( buffer) )
201+ let result = HIDBarcodeParserResult . success ( barcode: buffer, scanDurationMs: scanDurationMs)
202+ onScan ( result)
184203 } else {
185- onScan ( . failure( HIDBarcodeParserError . scanTooShort ( barcode: buffer) ) )
204+ let result = HIDBarcodeParserResult . failure ( error: HIDBarcodeParserError . scanTooShort ( barcode: buffer) , scanDurationMs: scanDurationMs)
205+ onScan ( result)
186206 }
187207 resetScan ( )
188208 }
@@ -211,4 +231,34 @@ struct HIDBarcodeParserConfiguration {
211231enum HIDBarcodeParserError : Error {
212232 case scanTooShort( barcode: String )
213233 case timedOut( barcode: String )
234+
235+ var analyticsReason : String {
236+ switch self {
237+ case . scanTooShort:
238+ return " too_short "
239+ case . timedOut:
240+ return " no_terminator "
241+ }
242+ }
243+
244+ var barcode : String {
245+ switch self {
246+ case . scanTooShort( let barcode) , . timedOut( let barcode) :
247+ return barcode
248+ }
249+ }
250+ }
251+
252+ enum HIDBarcodeParserResult {
253+ case success( barcode: String , scanDurationMs: Int )
254+ case failure( error: HIDBarcodeParserError , scanDurationMs: Int )
255+
256+ var asResult : Result < String , Error > {
257+ switch self {
258+ case . success( let barcode, _) :
259+ return . success( barcode)
260+ case . failure( let error, _) :
261+ return . failure( error)
262+ }
263+ }
214264}
0 commit comments