aboutsummaryrefslogtreecommitdiff
path: root/Map/Extensions/Map+parse.swift
blob: 03e799330bcadeeb833be57beabf317af77514b8 (plain)
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)
    }
}