// // CharacterAutoTest.swift // KdanAuto // // Created by 朱东勇 on 2022/11/22. // import Foundation import Cocoa class CharacterAutoTest : AutoTest { // override func type() -> String { // return "PDFConvert_China_Auto_Test" // } override func name() -> String { return _name } override func keys() -> NSArray { return ["字符", "快照"] } static var cSharedInstance = CharacterAutoTest() override class func shared() -> AutoTest? { return cSharedInstance } // Auto Test refrence Check File override func autoTest(_ complention:@escaping (_ object:AutoTest, _ report:NSAttributedString?) -> ()) { clearCacheFiles() let checkString = self.selectedKeys().contains("字符") let needCompare = self.selectedKeys().contains("快照") if !needCompare && !checkString { _status = .Finished complention(self, self.reportString) return } _status = .Process reportString = NSMutableAttributedString.init(string: "\n【\(String(self.fileType())) - \(self.name())】字符比对开始!\n", attributes:[.foregroundColor : NSColor.blue]) let files = DataModel.shared.originFilesFor(_fileType, type: _type) let checkDirectory = self.checkFileDirectory() let originDirectory = self.originFileDirectory() let resultDirectory = self.resultFileDirectory() if (files.count > 0) { try? FileManager.default.createDirectory(atPath: checkDirectory, withIntermediateDirectories: true); try? FileManager.default.createDirectory(atPath: resultDirectory, withIntermediateDirectories: true); } var tDegree = Double(0); var tCount = Int(0) var fileIndex = 0; var convertFileBlock = { (files:[String]) in } convertFileBlock = { (files:[String]) in if (fileIndex >= files.count) { TestDegreeManager.shared().set(((tCount != 0) ? tDegree/Double(tCount) : 0.0), fileType: self.fileType(), type: self.type()) self._status = .Finished DispatchQueue.main.async { autoreleasepool { complention(self, self.reportString); } } return } let fileName = files[fileIndex] let fName = NSString(string: fileName).deletingPathExtension let originPath = NSString(string: originDirectory).appendingPathComponent(fName+".pdf") let resultPath = NSString(string: resultDirectory).appendingPathComponent(fName+"."+self.extention()) let checkPath = NSString(string: checkDirectory).appendingPathComponent(fName+"."+self.extention()) self.reportString?.append(NSMutableAttributedString.init(string: "\n【\(String(self.fileType())) - \(self.name())】开始转换文件 \"\(fName)\"\n", attributes:[.foregroundColor : NSColor.black])) // ... // 执行转换过程 self.process(originPath, resultPath: resultPath) { status in if FileManager.default.fileExists(atPath: resultPath) && status == 1 { if checkString && FileManager.default.fileExists(atPath: checkPath) { // Load check file let checkData = NSData.init(contentsOfFile: checkPath) as! Data var documentAttributes:NSDictionary! let checkAttString = NSAttributedString.init(rtf: checkData, documentAttributes: &documentAttributes) var checkString = NSString(string: checkAttString!.string) as NSString let resultString = try? NSString.init(contentsOfFile: resultPath, encoding: NSUTF8StringEncoding) #if false //识别字符串 \shptxt\shptxt ... } let pageInfoStrings = resultString!.components(separatedBy: "\\shptxt\\shptxt") as NSArray var finalString = "" if pageInfoStrings.count > 0 { let subStrings = pageInfoStrings.subarray(with: NSMakeRange(1, Int(pageInfoStrings.count - 1))) as! [String] for pageInfoString in subStrings { let endRange = NSString(string: pageInfoString).range(of: "}") finalString = finalString.appending(NSString(string: pageInfoString).substring(to: endRange.location)) } } //识别所有 【空格 ~ \】 之间的值,并进行缝合 // Detect all strings between Spaces and \ and stitch let strings = finalString.components(separatedBy: " ") var resultStr = "" as NSString for str in strings { let markStr = str as NSString if (markStr.contains("\\f")) { let fRange = markStr.range(of: "\\f") let cRange = markStr.range(of: "\\c") let bRange = markStr.range(of: "\\b") let iRange = markStr.range(of: "\\i") let eRange = markStr.range(of: "\\e") let pRange = markStr.range(of: "\\p") let minPos = min(Int(fRange.location), Int(cRange.location), Int(bRange.location), Int(iRange.location), Int(eRange.location), Int(pRange.location)) resultStr = resultStr.appending(markStr.substring(to: minPos)) as NSString }else { resultStr = resultStr.appending(markStr as String) as NSString } } resultStr = self.replaceUnicodeString(resultStr) #else let resultData = NSData.init(contentsOfFile: resultPath) as! Data var rDocumentAttributes:NSDictionary! let resultAttString = NSAttributedString.init(rtf: resultData, documentAttributes: &rDocumentAttributes) var resultStr = NSString(string: resultAttString!.string) #endif resultStr = resultStr.replacingOccurrences(of: "\n", with: "") as NSString checkString = checkString.replacingOccurrences(of: "\n", with: "") as NSString resultStr = resultStr.replacingOccurrences(of: " ", with: "") as NSString checkString = checkString.replacingOccurrences(of: " ", with: "") as NSString resultStr = resultStr.replacingOccurrences(of: "\\pard", with: "") as NSString resultStr = resultStr.replacingOccurrences(of: "\\par", with: "") as NSString // do { // save cache file for test // try? NSString(string: resultStr).write(toFile: NSString(string: DataModel.shared.resultPath()).appending("/\(self.name())-result-cache.txt"), // atomically: true, encoding: NSUTF8StringEncoding) // // try? NSString(string: checkString).write(toFile: NSString(string: DataModel.shared.resultPath()).appending("/\(self.name())-check-cache.txt"), // atomically: true, encoding: NSUTF8StringEncoding) // } let maxSize = checkString.length var successCount = 0; /** (A0 = B0) - A-1 & B-1 (A0 != B0) & (A0 in B) & (B0 in A) - 取 A0,B0最小 Range 值 - 字符串裁剪对齐 (A0 != B0) & (A0 in B) - 存储B0到识别错误缓存 (A0 != B0) & (B0 in A) - 存储 A0到识别遗漏字符串 (A0 != B0) - 分别存储 A0、B0到遗漏及错误字串 */ var skipString = NSString() var failString = NSString() while (checkString.length > 0 && resultStr.length > 0) { let subc = checkString.substring(to: 1) as NSString let subr = resultStr.substring(to: 1) as NSString if subc.isEqual(to: subr) { // (A0 = B0) // Check Success self.appendErrorInfo(skipString, failString: failString) skipString = NSString() failString = NSString() checkString = checkString.substring(from:1) as NSString resultStr = resultStr.substring(from:1) as NSString successCount = successCount + 1 }else if (checkString.contains(subr as String) && resultStr.contains(subc as String)) { self.appendErrorInfo(skipString, failString: failString) skipString = NSString() failString = NSString() let cRange = checkString.range(of: subr as String) let rRange = resultStr.range(of: subc as String) if (cRange.location < rRange.location) { let cacheString = checkString.substring(to:cRange.location + cRange.length) self.reportString?.append(NSMutableAttributedString.init(string: "对照字符串【\(cacheString)】未识别到\n", attributes:[.foregroundColor : NSColor.red])) checkString = checkString.substring(from:cRange.location) as NSString }else { let cacheString = resultStr.substring(to:rRange.location) self.reportString?.append(NSMutableAttributedString.init(string: "字符串【\(cacheString)】识别出错\n", attributes:[.foregroundColor : NSColor.red])) resultStr = resultStr.substring(from:rRange.location + rRange.length) as NSString } }else if (checkString.contains(subr as String)) { skipString = skipString.appending(subc as String) as NSString checkString = checkString.substring(from:1) as NSString }else if (resultStr.contains(subc as String)) { failString = failString.appending(subr as String) as NSString resultStr = resultStr.substring(from:1) as NSString }else { skipString = skipString.appending(subc as String) as NSString failString = failString.appending(subr as String) as NSString checkString = checkString.substring(from:1) as NSString resultStr = resultStr.substring(from:1) as NSString } } skipString = skipString.appending(checkString as String) as NSString failString = failString.appending(resultStr as String) as NSString self.appendErrorInfo(skipString, failString: failString) let degree = Float(successCount)/Float(maxSize) * 100 var color = NSColor.black if fabs(degree-100.0) >= 0.01 { color = NSColor.red } self.reportString?.append(NSAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】文件 \"\(fName)\"比对完成,准确率\(degree)%(\(successCount)/\(maxSize))\n", attributes:[.foregroundColor : color])) } // compare screenshoot between result file with check file if needCompare { self.reportString?.append(NSMutableAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】文件 \"\(fName)\"快照生成中\n", attributes:[.foregroundColor : NSColor.black])) let rComparePath = NSString(string: resultDirectory).appendingPathComponent(fName+".jpg") let cComparePath = NSString(string: checkDirectory).appendingPathComponent(fName+".jpg") let processThumbSemaphore = DispatchSemaphore(value: 0) var processSuccess = false let thumbnailQueue = DispatchQueue.global() thumbnailQueue.async { autoreleasepool { processSuccess = ProcessThumbnal.process(resultPath, desPath: rComparePath, outputSize: CGSize.init(width: 2048, height: 2048)) if (processSuccess && FileManager.default.fileExists(atPath: rComparePath)) { let degree = ImageProcess.compareJPEG(rComparePath, checkPath: cComparePath, processCover: true) if degree == -1 { self.reportString?.append(NSMutableAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】文件 \"\(fName)\"快照对比失败,生成快照失败或无比对文件\n", attributes:[.foregroundColor : NSColor.red])) }else { var color = NSColor.black if fabs(degree-100.0) >= 0.01 { color = NSColor.red } TestDegreeManager.shared().set(degree, fileType: self.fileType(), type: self.type(), fileName: fileName); TestDegreeManager.shared().set(degree, fileType: self.fileType(), type: self.type(), fileName: fileName, refFilePath: fName+".jpg"); tDegree += degree tCount += 1 self.reportString?.append(NSMutableAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】文件 \"\(fName)\"快照对比完成,图像相似度 \(degree)%\n", attributes:[.foregroundColor : color])) } }else { self.reportString?.append(NSMutableAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】文件 \"\(fName)\"快照生成失败\n", attributes:[.foregroundColor : NSColor.red])) } processThumbSemaphore.signal() } } processThumbSemaphore.wait() } }else { if (status == 0) { self.reportString?.append(NSMutableAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】文件 \"\(fName)\"转档失败!\n", attributes:[.foregroundColor : NSColor.red])) }else if (status == -1 || status == -2) { self.reportString?.append(NSMutableAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】文件 \"\(fName)\"文档无法打开!\n", attributes:[.foregroundColor : NSColor.red])) }else if (status == -3) { self.reportString?.append(NSMutableAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】文件 \"\(fName)\"转档中 Crash!\n", attributes:[.foregroundColor : NSColor.red])) } } fileIndex += 1 convertFileBlock(files); } } convertFileBlock(files); } ///Compare /// Tools func appendErrorInfo(_ skipString:NSString, failString: NSString) { if skipString.length > 0 && failString.length > 0 { reportString?.append(NSMutableAttributedString.init(string: "对比字符串【\(skipString)】错识别为【\(failString)】\n", attributes:[.foregroundColor : NSColor.red])) }else if (skipString.length > 0) { reportString?.append(NSMutableAttributedString.init(string: "对比字符串【\(skipString)】未识别到\n", attributes:[.foregroundColor : NSColor.red])) }else if failString.length > 0 { reportString?.append(NSMutableAttributedString.init(string: "字符串【\(failString)】识别出错\n", attributes:[.foregroundColor : NSColor.red])) } } func replaceUnicodeString(_ string:NSString) -> NSString {//中 let items = string.components(separatedBy: "\\u") as [NSString] var resultString = NSString() for item in items { if (item.contains("?")) { let unicodeValue = item.intValue let skipRange = item.range(of: "?") let nextString = item.substring(from: Int(skipRange.location + skipRange.length)) as NSString let bytes : [UInt8] = [UInt8(unicodeValue/256),UInt8(unicodeValue%256)] let data = NSData.init(bytes: bytes, length: 2) let unicodeString = NSString.init(data: data as Data, encoding: NSUnicodeStringEncoding)! as NSString resultString = resultString.appending(String("\(unicodeString)\(nextString)")) as NSString }else { resultString = resultString.appending(String(item)) as NSString } } return resultString } }