Advertisement
Guest User

Untitled

a guest
Nov 12th, 2019
165
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Swift 3.55 KB | None | 0 0
  1. //
  2. //  CFUnitParser.swift
  3. //  DLG
  4. //
  5. //  Created by Nik Suprunov on 10/11/2019.
  6. //  Copyright © 2019 SHAPE A/S. All rights reserved.
  7. //
  8.  
  9. import Foundation
  10. import Entities
  11.  
  12. public struct ConversionFactorUnit {
  13.     public let weight: Double
  14.     public let destination: String
  15.     public let base: String
  16. }
  17.  
  18. public class CFUnitParser: NSObject {
  19.    
  20.     ///Graph holding references to all adjacent edges, its weighs and total conversion path's weighs
  21.     private var graph = [String : [String: (Double,Double)]]()
  22.    
  23.     struct UnitNode {
  24.         let weight: Double
  25.         let name: String
  26.     }
  27.    
  28.    
  29.     public init(_ conversionFactors: [ConversionFactor]) {
  30.         super.init()
  31.         var unitsSet = Set<String>()
  32.        
  33.         conversionFactors.forEach({
  34.             guard let nominatorUnit = $0.numeratorUnit, let denominatorUnit = $0.denominatorUnit, $0.denominator > 0 && $0.numerator > 0 else {return}
  35.             unitsSet.insert(denominatorUnit)
  36.             unitsSet.insert(nominatorUnit)
  37.             if graph[denominatorUnit] == nil {
  38.                 graph[denominatorUnit] = [String : (Double,Double)]()
  39.             }
  40.             if graph[nominatorUnit] == nil {
  41.                 graph[nominatorUnit] = [String : (Double,Double)]()
  42.             }
  43.             ///Make graph bidirectional where Y-->Z edge has a value of (x) and Z-->Y a value of 1/(x)
  44.             graph[denominatorUnit]?[nominatorUnit] = (Double($0.numerator) / Double($0.denominator), 0)
  45.             graph[nominatorUnit]?[denominatorUnit] = (Double($0.denominator) / Double($0.numerator), 0)
  46.         })
  47.     }
  48.    
  49.     /// This function returns ConversionFactorUnit based on unit characteristics input.
  50.     ///
  51.     /// - 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).
  52.     ///
  53.     ///
  54.     /// Usage:
  55.     ///
  56.     ///     let convertedFactorUnit = convertUnits(from: "baseUnit", to: "desiredUnit")
  57.     ///
  58.     /// - parameter from: The base unit of conversion.
  59.     /// - parameter to: The destination unit of conversion.
  60.     ///
  61.     ///
  62.     /// - returns: `ConversionFactorUnit` with conversion characteristics and result. Nil if the conversion is not found.
  63.  
  64.     public func convertUnits(from: String, to: String) -> ConversionFactorUnit? {
  65.         var graph = self.graph
  66.         var queue = Queue<UnitNode>()
  67.         ///Set initial path (unit conversion) to 1 (1 "unit" = 1 "unit")
  68.         queue.enqueue(UnitNode(weight: 1, name: from))
  69.        
  70.         while let current = queue.dequeue() {
  71.             if current.name == to {
  72.                 ///Interrupt  BFS and return needed path
  73.                 return ConversionFactorUnit(weight: current.weight, destination: current.name, base: from)
  74.             }
  75.             for edge in graph[current.name] ?? [:] {
  76.                 if graph[current.name]?[edge.key]?.1 == 0 {
  77.                     let neighBorNode =  UnitNode(weight: edge.value.0 * current.weight, name: edge.key)
  78.                     graph[current.name]?[edge.key]?.1 = edge.value.0 * current.weight
  79.                     queue.enqueue(neighBorNode)
  80.                 }
  81.             }
  82.         }
  83.        
  84.         return nil
  85.     }
  86.    
  87.     public func convertFromPalle(to: String) -> ConversionFactorUnit? {
  88.         let kPalleName = "palle"
  89.         let kPalleNamePlural = "paller"
  90.         return convertUnits(from: kPalleName, to: to) ?? convertUnits(from: kPalleNamePlural, to: to)
  91.     }
  92. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement