]> git.r.bdr.sh - rbdr/map/blobdiff - Map/Extensions/Map+parse.swift
Let app store know we're about productivity
[rbdr/map] / Map / Extensions / Map+parse.swift
index 03e799330bcadeeb833be57beabf317af77514b8..d82ba99173f534750026aacbb4f01362d00a84f2 100644 (file)
 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)
+  }
 }