]> git.r.bdr.sh - rbdr/map/blob - Map/MapParser/MapParser.swift
cce62514d8b29ff9303a759e12dccc5c1aed05a6
[rbdr/map] / Map / MapParser / MapParser.swift
1 import CoreGraphics
2 import Foundation
3
4 // MARK: - Types
5
6 struct MapParsingPatterns {
7 static let vertex = try! NSRegularExpression(
8 pattern:
9 "([^\\(]+?)[\\s]*\\([\\s]*([0-9]+.?[0-9]*)[\\s]*,[\\s]*([0-9]+.?[0-9]*)[\\s]*\\)[\\s]*(?:\\[(.*?)\\])?",
10 options: .caseInsensitive)
11 static let edge = try! NSRegularExpression(
12 pattern: "(.+?)[\\s]*-([->])[\\s]*(.+)", options: .caseInsensitive)
13 static let blocker = try! NSRegularExpression(
14 pattern: "\\[(Blocker)\\][\\s]*(.+)", options: .caseInsensitive)
15 static let opportunity = try! NSRegularExpression(
16 pattern: "\\[(Opportunity)\\][\\s]*(.+)[\\s]+([-+])[\\s]*([0-9]+.?[0-9]*)",
17 options: .caseInsensitive)
18 static let stage = try! NSRegularExpression(
19 pattern: "\\[(I{1,3})\\][\\s]*([0-9]+.?[0-9]*)", options: .caseInsensitive)
20 }
21
22 struct ParsedMap {
23 let vertices: [Vertex]
24 let edges: [MapEdge]
25 let blockers: [Blocker]
26 let opportunities: [Opportunity]
27 let stages: [CGFloat]
28
29 static let empty: ParsedMap = ParsedMap(
30 vertices: [], edges: [], blockers: [], opportunities: [], stages: defaultDimensions)
31 }
32
33 struct Vertex {
34 let id: Int
35 let label: String
36 let position: CGPoint
37 var shape: VertexShape = .circle
38 }
39
40 enum VertexShape: String {
41 case circle
42 case square
43 case triangle
44 case x
45 }
46
47 struct MapEdge {
48 let id: Int
49 let origin: CGPoint
50 let destination: CGPoint
51 let arrowhead: Bool
52 }
53
54 struct Blocker {
55 let id: Int
56 let position: CGPoint
57 }
58
59 struct Opportunity {
60 let id: Int
61 let origin: CGPoint
62 let destination: CGPoint
63 }
64
65 struct StageDimensions {
66 let index: Int
67 let dimensions: CGFloat
68 }
69
70 private let defaultDimensions: [CGFloat] = [
71 25.0,
72 50.0,
73 75.0,
74 ]
75
76 // MARK: - MapParserStrategy protocol
77
78 protocol MapParserStrategy {
79 func canHandle(line: String) -> Bool
80 func handle(index: Int, line: String, vertices: [String: Vertex]) -> (Any.Type, Any)
81 }
82
83 struct AnyMapParserStrategy: MapParserStrategy {
84
85 private let base: MapParserStrategy
86
87 init<T: MapParserStrategy>(_ base: T) {
88 self.base = base
89 }
90
91 func canHandle(line: String) -> Bool {
92 return base.canHandle(line: line)
93 }
94 func handle(index: Int, line: String, vertices: [String: Vertex]) -> (Any.Type, Any) {
95 return base.handle(index: index, line: line, vertices: vertices)
96 }
97 }
98
99 // MARK: - Map Builder
100
101 class MapBuilder {
102 var vertices: [String: Vertex] = [:]
103 private var edges: [MapEdge] = []
104 private var blockers: [Blocker] = []
105 private var opportunities: [Opportunity] = []
106 private var stages: [CGFloat] = defaultDimensions
107
108 func addObjectToMap(type: Any.Type, object: Any) {
109 if type == Vertex.self {
110 let vertex = object as! Vertex
111 vertices[vertex.label] = vertex
112 }
113
114 if type == MapEdge.self {
115 let edge = object as! MapEdge
116 edges.append(edge)
117 }
118
119 if type == Blocker.self {
120 let blocker = object as! Blocker
121 blockers.append(blocker)
122 }
123
124 if type == Opportunity.self {
125 let opportunity = object as! Opportunity
126 opportunities.append(opportunity)
127 }
128
129 if type == StageDimensions.self {
130 let stageDimensions = object as! StageDimensions
131 stages[stageDimensions.index] = stageDimensions.dimensions
132
133 }
134 }
135
136 func build() -> ParsedMap {
137 let mappedVertices = vertices.map { label, vertex in return vertex }
138 return ParsedMap(
139 vertices: mappedVertices, edges: edges, blockers: blockers, opportunities: opportunities,
140 stages: stages)
141 }
142 }