]>
Commit | Line | Data |
---|---|---|
1 | import CoreGraphics | |
2 | import Foundation | |
3 | ||
4 | let VERTEX_PATTERN = "([^\\(]+?)[\\s]*\\([\\s]*([0-9]+.?[0-9]*)[\\s]*,[\\s]*([0-9]+.?[0-9]*)[\\s]*\\)" | |
5 | let EDGE_PATTERN = "(.+?)[\\s]*->[\\s]*(.+)" | |
6 | ||
7 | struct ParsedMap { | |
8 | let vertices: [Vertex] | |
9 | let edges: [MapEdge] | |
10 | } | |
11 | ||
12 | struct Vertex { | |
13 | let id: Int | |
14 | let label: String | |
15 | let position: CGPoint | |
16 | } | |
17 | ||
18 | struct MapEdge { | |
19 | let id: Int | |
20 | let origin: CGPoint | |
21 | let destination: CGPoint | |
22 | } | |
23 | ||
24 | // Extracts the vertices from the text | |
25 | ||
26 | func parseVertices(_ text: String) -> [String: CGPoint] { | |
27 | ||
28 | var result: [String: CGPoint] = [:] | |
29 | let regex = try! NSRegularExpression(pattern: VERTEX_PATTERN, options: .caseInsensitive) | |
30 | ||
31 | let lines = text.split(whereSeparator: \.isNewline) | |
32 | ||
33 | for line in lines { | |
34 | let range = NSRange(location: 0, length: line.utf16.count) | |
35 | let matches = regex.matches(in: String(line), options: [], range: range) | |
36 | ||
37 | if matches.count > 0 && matches[0].numberOfRanges == 4{ | |
38 | ||
39 | let match = matches[0]; | |
40 | let key = String(line[Range(match.range(at: 1), in: line)!]) | |
41 | let xString = String(line[Range(match.range(at: 2), in: line)!]) | |
42 | let yString = String(line[Range(match.range(at: 3), in: line)!]) | |
43 | let x = CGFloat(truncating: NumberFormatter().number(from:xString) ?? 0.0) | |
44 | let y = CGFloat(truncating: NumberFormatter().number(from:yString) ?? 0.0) | |
45 | let point = CGPoint(x: x, y: y) | |
46 | ||
47 | result[key] = point | |
48 | } | |
49 | } | |
50 | ||
51 | return result | |
52 | } | |
53 | ||
54 | // Extracts the edges from the text | |
55 | ||
56 | func parseEdges(_ text: String, vertices: [String: CGPoint]) -> [MapEdge] { | |
57 | ||
58 | var result: [MapEdge] = [] | |
59 | let regex = try! NSRegularExpression(pattern: EDGE_PATTERN, options: .caseInsensitive) | |
60 | ||
61 | let lines = text.split(whereSeparator: \.isNewline) | |
62 | ||
63 | for (index, line) in lines.enumerated() { | |
64 | let range = NSRange(location: 0, length: line.utf16.count) | |
65 | let matches = regex.matches(in: String(line), options: [], range: range) | |
66 | ||
67 | if matches.count > 0 && matches[0].numberOfRanges == 3 { | |
68 | ||
69 | let match = matches[0]; | |
70 | let vertexA = String(line[Range(match.range(at: 1), in: line)!]) | |
71 | let vertexB = String(line[Range(match.range(at: 2), in: line)!]) | |
72 | ||
73 | if let origin = vertices[vertexA] { | |
74 | if let destination = vertices[vertexB] { | |
75 | result.append(MapEdge(id: index, origin: origin, destination: destination)) | |
76 | } | |
77 | } | |
78 | } | |
79 | } | |
80 | ||
81 | return result | |
82 | } | |
83 | ||
84 | // Converts vetex dictionary to array | |
85 | ||
86 | func mapVertices(_ vertices: [String: CGPoint]) -> [Vertex] { | |
87 | var i = 0 | |
88 | return vertices.map { label, position in | |
89 | i += 1; | |
90 | return Vertex(id: i, label: label, position: position) | |
91 | } | |
92 | } | |
93 | ||
94 | extension Map { | |
95 | func parse() -> ParsedMap { | |
96 | ||
97 | let text = self.content ?? "" | |
98 | let vertices = parseVertices(text) | |
99 | let mappedVertices = mapVertices(vertices) | |
100 | let edges = parseEdges(text, vertices: vertices) | |
101 | print(mappedVertices) | |
102 | print(edges) | |
103 | ||
104 | return ParsedMap(vertices: mappedVertices, edges: edges) | |
105 | } | |
106 | } |