Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // CFUnitParser.swift
- // DLG
- //
- // Created by Nik Suprunov on 10/11/2019.
- // Copyright © 2019 SHAPE A/S. All rights reserved.
- //
- import Foundation
- import Entities
- public struct ConversionFactorUnit {
- public let weight: Double
- public let destination: String
- public let base: String
- }
- public class CFUnitParser: NSObject {
- ///Graph holding references to all adjacent edges, its weighs and total conversion path's weighs
- private var graph = [String : [String: (Double,Double)]]()
- struct UnitNode {
- let weight: Double
- let name: String
- }
- public init(_ conversionFactors: [ConversionFactor]) {
- super.init()
- var unitsSet = Set<String>()
- conversionFactors.forEach({
- guard let nominatorUnit = $0.numeratorUnit, let denominatorUnit = $0.denominatorUnit, $0.denominator > 0 && $0.numerator > 0 else {return}
- unitsSet.insert(denominatorUnit)
- unitsSet.insert(nominatorUnit)
- if graph[denominatorUnit] == nil {
- graph[denominatorUnit] = [String : (Double,Double)]()
- }
- if graph[nominatorUnit] == nil {
- graph[nominatorUnit] = [String : (Double,Double)]()
- }
- ///Make graph bidirectional where Y-->Z edge has a value of (x) and Z-->Y a value of 1/(x)
- graph[denominatorUnit]?[nominatorUnit] = (Double($0.numerator) / Double($0.denominator), 0)
- graph[nominatorUnit]?[denominatorUnit] = (Double($0.denominator) / Double($0.numerator), 0)
- })
- }
- /// This function returns ConversionFactorUnit based on unit characteristics input.
- ///
- /// - warning: Works only if the format makes any logical sense. In case of multiple translations with same argument, different values: 1) 2 "a" = 2 "b" ; 2"a" = 3"b", it will return the first found conversion (path).
- ///
- ///
- /// Usage:
- ///
- /// let convertedFactorUnit = convertUnits(from: "baseUnit", to: "desiredUnit")
- ///
- /// - parameter from: The base unit of conversion.
- /// - parameter to: The destination unit of conversion.
- ///
- ///
- /// - returns: `ConversionFactorUnit` with conversion characteristics and result. Nil if the conversion is not found.
- public func convertUnits(from: String, to: String) -> ConversionFactorUnit? {
- var graph = self.graph
- var queue = Queue<UnitNode>()
- ///Set initial path (unit conversion) to 1 (1 "unit" = 1 "unit")
- queue.enqueue(UnitNode(weight: 1, name: from))
- while let current = queue.dequeue() {
- if current.name == to {
- ///Interrupt BFS and return needed path
- return ConversionFactorUnit(weight: current.weight, destination: current.name, base: from)
- }
- for edge in graph[current.name] ?? [:] {
- if graph[current.name]?[edge.key]?.1 == 0 {
- let neighBorNode = UnitNode(weight: edge.value.0 * current.weight, name: edge.key)
- graph[current.name]?[edge.key]?.1 = edge.value.0 * current.weight
- queue.enqueue(neighBorNode)
- }
- }
- }
- return nil
- }
- public func convertFromPalle(to: String) -> ConversionFactorUnit? {
- let kPalleName = "palle"
- let kPalleNamePlural = "paller"
- return convertUnits(from: kPalleName, to: to) ?? convertUnits(from: kPalleNamePlural, to: to)
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement