]> git.r.bdr.sh - rbdr/map/blob - Map/Extensions/Map+parse.swift
03e799330bcadeeb833be57beabf317af77514b8
[rbdr/map] / Map / Extensions / Map+parse.swift
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 }