1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
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]*(.+)"
struct ParsedMap {
let vertices: [Vertex]
let edges: [MapEdge]
}
struct Vertex {
let id: Int
let label: String
let position: CGPoint
}
struct MapEdge {
let id: Int
let origin: CGPoint
let destination: CGPoint
}
// 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
}
}
return result
}
// Extracts the edges from the text
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))
}
}
}
}
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)
}
}
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)
}
}
|