]>
Commit | Line | Data |
---|---|---|
77d0155b RBR |
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 | ||
30 | struct Vertex { | |
31 | let id: Int | |
32 | let label: String | |
33 | let position: CGPoint | |
34 | var shape: VertexShape = .circle | |
35 | } | |
36 | ||
37 | enum VertexShape: String { | |
38 | case circle | |
39 | case square | |
40 | case triangle | |
41 | case x | |
42 | } | |
43 | ||
44 | struct MapEdge { | |
45 | let id: Int | |
46 | let origin: CGPoint | |
47 | let destination: CGPoint | |
48 | let arrowhead: Bool | |
49 | } | |
50 | ||
51 | struct Blocker { | |
52 | let id: Int | |
53 | let position: CGPoint | |
54 | } | |
55 | ||
56 | struct Opportunity { | |
57 | let id: Int | |
58 | let origin: CGPoint | |
59 | let destination: CGPoint | |
60 | } | |
61 | ||
62 | struct StageDimensions { | |
63 | let index: Int | |
64 | let dimensions: CGFloat | |
65 | } | |
66 | ||
67 | private let defaultDimensions: [CGFloat] = [ | |
68 | 25.0, | |
69 | 50.0, | |
70 | 75.0, | |
71 | ] | |
72 | ||
73 | // MARK: - MapParserStrategy protocol | |
74 | ||
75 | protocol MapParserStrategy { | |
76 | func canHandle(line: String) -> Bool | |
77 | func handle(index: Int, line: String, vertices: [String: Vertex]) -> (Any.Type, Any) | |
78 | } | |
79 | ||
80 | struct AnyMapParserStrategy: MapParserStrategy { | |
81 | ||
82 | private let base: MapParserStrategy | |
83 | ||
84 | init<T: MapParserStrategy>(_ base: T) { | |
85 | self.base = base | |
86 | } | |
87 | ||
88 | func canHandle(line: String) -> Bool { | |
89 | return base.canHandle(line: line) | |
90 | } | |
91 | func handle(index: Int, line: String, vertices: [String: Vertex]) -> (Any.Type, Any) { | |
92 | return base.handle(index: index, line: line, vertices: vertices) | |
93 | } | |
94 | } | |
95 | ||
96 | // MARK: - Map Builder | |
97 | ||
98 | class MapBuilder { | |
99 | var vertices: [String: Vertex] = [:] | |
100 | private var edges: [MapEdge] = [] | |
101 | private var blockers: [Blocker] = [] | |
102 | private var opportunities: [Opportunity] = [] | |
103 | private var stages: [CGFloat] = defaultDimensions | |
104 | ||
105 | func addObjectToMap(type: Any.Type, object: Any) { | |
106 | if type == Vertex.self { | |
107 | let vertex = object as! Vertex | |
108 | vertices[vertex.label] = vertex | |
109 | } | |
110 | ||
111 | if type == MapEdge.self { | |
112 | let edge = object as! MapEdge | |
113 | edges.append(edge) | |
114 | } | |
115 | ||
116 | if type == Blocker.self { | |
117 | let blocker = object as! Blocker | |
118 | blockers.append(blocker) | |
119 | } | |
120 | ||
121 | if type == Opportunity.self { | |
122 | let opportunity = object as! Opportunity | |
123 | opportunities.append(opportunity) | |
124 | } | |
125 | ||
126 | if type == StageDimensions.self { | |
127 | let stageDimensions = object as! StageDimensions | |
128 | stages[stageDimensions.index] = stageDimensions.dimensions | |
129 | ||
130 | } | |
131 | } | |
132 | ||
133 | func build() -> ParsedMap { | |
134 | let mappedVertices = vertices.map { label, vertex in return vertex } | |
135 | return ParsedMap( | |
136 | vertices: mappedVertices, edges: edges, blockers: blockers, opportunities: opportunities, | |
137 | stages: stages) | |
138 | } | |
139 | } |