X-Git-Url: https://git.r.bdr.sh/rbdr/map/blobdiff_plain/1b85f723b48d38cf345bb9a4f3fd01aa6039b50b..491463f421c86d3a7a5482108b818aa5b5e441ea:/Map/Extensions/Map%20parse.swift/rbdr/map/blobdiff_plain/1b85f723b48d38cf345bb9a4f3fd01aa6039b50b..491463f421c86d3a7a5482108b818aa5b5e441ea:/Map/Extensions/Map+parse.swift diff --git a/Map/Extensions/Map+parse.swift b/Map/Extensions/Map+parse.swift index 03e7993..d82ba99 100644 --- a/Map/Extensions/Map+parse.swift +++ b/Map/Extensions/Map+parse.swift @@ -1,106 +1,215 @@ import CoreGraphics import Foundation -let VERTEX_PATTERN = "([^\\(]+?)[\\s]*\\([\\s]*([0-9]+.?[0-9]*)[\\s]*,[\\s]*([0-9]+.?[0-9]*)[\\s]*\\)" -let EDGE_PATTERN = "(.+?)[\\s]*->[\\s]*(.+)" +let vertexPattern = + "([^\\(]+?)[\\s]*\\([\\s]*([0-9]+.?[0-9]*)[\\s]*,[\\s]*([0-9]+.?[0-9]*)[\\s]*\\)" +let edgePattern = "(.+?)[\\s]*-([->])[\\s]*(.+)" +let blockerPattern = "\\[Blocker\\][\\s]*(.+)" +let opportunityPattern = "\\[Opportunity\\][\\s]*(.+)[\\s]+([-+])[\\s]*([0-9]+.?[0-9]*)" +let stagePattern = "\\[(I{1,3})\\][\\s]*([0-9]+.?[0-9]*)" struct ParsedMap { - let vertices: [Vertex] - let edges: [MapEdge] + let vertices: [Vertex] + let edges: [MapEdge] + let blockers: [Blocker] + let opportunities: [Opportunity] + let stages: [CGFloat] } struct Vertex { - let id: Int - let label: String - let position: CGPoint + let id: Int + let label: String + let position: CGPoint } struct MapEdge { - let id: Int - let origin: CGPoint - let destination: CGPoint + let id: Int + let origin: CGPoint + let destination: CGPoint + let arrowhead: Bool } +struct Blocker { + let id: Int + let position: CGPoint +} + +struct Opportunity { + let id: Int + let origin: CGPoint + let destination: CGPoint +} + +let defaultDimensions: [CGFloat] = [ + 25.0, + 50.0, + 75.0, +] + // Extracts the vertices from the text func parseVertices(_ text: String) -> [String: CGPoint] { - - var result: [String: CGPoint] = [:] - let regex = try! NSRegularExpression(pattern: VERTEX_PATTERN, options: .caseInsensitive) - - let lines = text.split(whereSeparator: \.isNewline) - - for line in lines { - let range = NSRange(location: 0, length: line.utf16.count) - let matches = regex.matches(in: String(line), options: [], range: range) - - if matches.count > 0 && matches[0].numberOfRanges == 4{ - - let match = matches[0]; - let key = String(line[Range(match.range(at: 1), in: line)!]) - let xString = String(line[Range(match.range(at: 2), in: line)!]) - let yString = String(line[Range(match.range(at: 3), in: line)!]) - let x = CGFloat(truncating: NumberFormatter().number(from:xString) ?? 0.0) - let y = CGFloat(truncating: NumberFormatter().number(from:yString) ?? 0.0) - let point = CGPoint(x: x, y: y) - - result[key] = point - } + + var result: [String: CGPoint] = [:] + let regex = try! NSRegularExpression(pattern: vertexPattern, options: .caseInsensitive) + + let lines = text.split(whereSeparator: \.isNewline) + + for line in lines { + let range = NSRange(location: 0, length: line.utf16.count) + let matches = regex.matches(in: String(line), options: [], range: range) + + if matches.count > 0 && matches[0].numberOfRanges == 4 { + + let match = matches[0] + let key = String(line[Range(match.range(at: 1), in: line)!]) + let xString = String(line[Range(match.range(at: 2), in: line)!]) + let yString = String(line[Range(match.range(at: 3), in: line)!]) + let x = CGFloat(truncating: NumberFormatter().number(from: xString) ?? 0.0) + let y = CGFloat(truncating: NumberFormatter().number(from: yString) ?? 0.0) + let point = CGPoint(x: x, y: y) + + result[key] = point } - - return result -} + } -// Extracts the edges from the text + return result +} func parseEdges(_ text: String, vertices: [String: CGPoint]) -> [MapEdge] { - - var result: [MapEdge] = [] - let regex = try! NSRegularExpression(pattern: EDGE_PATTERN, options: .caseInsensitive) - - let lines = text.split(whereSeparator: \.isNewline) - - for (index, line) in lines.enumerated() { - let range = NSRange(location: 0, length: line.utf16.count) - let matches = regex.matches(in: String(line), options: [], range: range) - - if matches.count > 0 && matches[0].numberOfRanges == 3 { - - let match = matches[0]; - let vertexA = String(line[Range(match.range(at: 1), in: line)!]) - let vertexB = String(line[Range(match.range(at: 2), in: line)!]) - - if let origin = vertices[vertexA] { - if let destination = vertices[vertexB] { - result.append(MapEdge(id: index, origin: origin, destination: destination)) - } - } + + var result: [MapEdge] = [] + let regex = try! NSRegularExpression(pattern: edgePattern, options: .caseInsensitive) + + let lines = text.split(whereSeparator: \.isNewline) + + for (index, line) in lines.enumerated() { + let range = NSRange(location: 0, length: line.utf16.count) + let matches = regex.matches(in: String(line), options: [], range: range) + + if matches.count > 0 && matches[0].numberOfRanges == 4 { + + let match = matches[0] + let arrowhead = String(line[Range(match.range(at: 2), in: line)!]) == ">" + let vertexA = String(line[Range(match.range(at: 1), in: line)!]) + let vertexB = String(line[Range(match.range(at: 3), in: line)!]) + + if let origin = vertices[vertexA] { + if let destination = vertices[vertexB] { + result.append( + MapEdge(id: index, origin: origin, destination: destination, arrowhead: arrowhead)) } + } } - - return result + } + + return result +} + +func parseOpportunities(_ text: String, vertices: [String: CGPoint]) -> [Opportunity] { + + var result: [Opportunity] = [] + let regex = try! NSRegularExpression(pattern: opportunityPattern, options: .caseInsensitive) + + let lines = text.split(whereSeparator: \.isNewline) + + for (index, line) in lines.enumerated() { + let range = NSRange(location: 0, length: line.utf16.count) + let matches = regex.matches(in: String(line), options: [], range: range) + + if matches.count > 0 && matches[0].numberOfRanges == 4 { + + let match = matches[0] + let multiplier = CGFloat( + String(line[Range(match.range(at: 2), in: line)!]) == "-" ? -1.0 : 1.0) + let vertex = String(line[Range(match.range(at: 1), in: line)!]) + let opportunityString = String(line[Range(match.range(at: 3), in: line)!]) + let opportunity = CGFloat( + truncating: NumberFormatter().number(from: opportunityString) ?? 0.0) + + if let origin = vertices[vertex] { + let destination = CGPoint(x: origin.x + opportunity * multiplier, y: origin.y) + result.append(Opportunity(id: index, origin: origin, destination: destination)) + } + } + } + + return result +} + +func parseBlockers(_ text: String, vertices: [String: CGPoint]) -> [Blocker] { + + var result: [Blocker] = [] + let regex = try! NSRegularExpression(pattern: blockerPattern, options: .caseInsensitive) + + let lines = text.split(whereSeparator: \.isNewline) + + for (index, line) in lines.enumerated() { + let range = NSRange(location: 0, length: line.utf16.count) + let matches = regex.matches(in: String(line), options: [], range: range) + + if matches.count > 0 && matches[0].numberOfRanges == 2 { + + let match = matches[0] + let vertexA = String(line[Range(match.range(at: 1), in: line)!]) + + if let position = vertices[vertexA] { + result.append(Blocker(id: index, position: position)) + } + } + } + + return result +} + +func parseStages(_ text: String) -> [CGFloat] { + + var result = defaultDimensions + let regex = try! NSRegularExpression(pattern: stagePattern, options: .caseInsensitive) + + let lines = text.split(whereSeparator: \.isNewline) + + for line in lines { + let range = NSRange(location: 0, length: line.utf16.count) + let matches = regex.matches(in: String(line), options: [], range: range) + + if matches.count > 0 && matches[0].numberOfRanges == 3 { + + let match = matches[0] + let stage = String(line[Range(match.range(at: 1), in: line)!]) + let dimensionsString = String(line[Range(match.range(at: 2), in: line)!]) + let dimensions = CGFloat(truncating: NumberFormatter().number(from: dimensionsString) ?? 0.0) + + result[stage.count - 1] = dimensions + } + } + + return result } // Converts vetex dictionary to array func mapVertices(_ vertices: [String: CGPoint]) -> [Vertex] { - var i = 0 - return vertices.map { label, position in - i += 1; - return Vertex(id: i, label: label, position: position) - } + var i = 0 + return vertices.map { label, position in + i += 1 + return Vertex(id: i, label: label, position: position) + } } extension Map { - func parse() -> ParsedMap { - - let text = self.content ?? "" - let vertices = parseVertices(text) - let mappedVertices = mapVertices(vertices) - let edges = parseEdges(text, vertices: vertices) - print(mappedVertices) - print(edges) - - return ParsedMap(vertices: mappedVertices, edges: edges) - } + func parse() -> ParsedMap { + + let text = self.content ?? "" + let vertices = parseVertices(text) + let mappedVertices = mapVertices(vertices) + let edges = parseEdges(text, vertices: vertices) + let blockers = parseBlockers(text, vertices: vertices) + let opportunities = parseOpportunities(text, vertices: vertices) + let stages = parseStages(text) + + return ParsedMap( + vertices: mappedVertices, edges: edges, blockers: blockers, opportunities: opportunities, + stages: stages) + } }