arcgis_vrps 0.0.2.1 → 0.0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +18 -0
- data/lib/arcgis_vrps.rb +546 -7
- data/lib/arcgis_vrps/auth.rb +29 -0
- data/lib/arcgis_vrps/depots.rb +57 -0
- data/lib/arcgis_vrps/orders.rb +85 -0
- data/lib/arcgis_vrps/routes.rb +56 -0
- data/lib/test/data_load.rb +116 -0
- data/lib/test/sample_data/postcodes +129 -0
- metadata +37 -17
- data/lib/arcgis_vrps/sample.rb +0 -14
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: d3af625d3074f6f84386182d7b120aa4a57c0d99
         | 
| 4 | 
            +
              data.tar.gz: 2f2d8fd5876c98473a09c5ba532d4b3c81be802c
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 2c67e0d567464c17c154c44ec418ad0ff9fcf3ad9021ec9f8defd751005faaee6aed6a72fe3da0ef0ea927e284d5f17d27fb03a79e74fd54d628e3b70964d311
         | 
| 7 | 
            +
              data.tar.gz: 66e43e5f763b7b51399bb11c17e69b0486ad63be53d55e6e011072fc33527cb84e3057a123ae0aad2d0b6db37ae48c0e643999c057ee37205c983c1e7f15ecf8
         | 
    
        data/README.md
    ADDED
    
    | @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            # Overview #
         | 
| 2 | 
            +
            A ruby gem as an interface for ArcGIS (platform of Esri) Vehicle Routing Problem service REST API
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            You can install this gem by:
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                gem install arcgis_vrps
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            If at any moment you get the error similar to:
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            Please follow the steps outlined [here](https://gist.github.com/fnichol/867550)
         | 
| 13 | 
            +
             | 
| 14 | 
            +
             | 
| 15 | 
            +
            To debug / test the gem do the following on the command line:
         | 
| 16 | 
            +
             | 
| 17 | 
            +
             - irb -Ilib -rarcgis_vrps
         | 
| 18 | 
            +
             - a=Arcgis_Vrps.new
         | 
    
        data/lib/arcgis_vrps.rb
    CHANGED
    
    | @@ -1,10 +1,549 @@ | |
| 1 | 
            +
            # This require has to be below cause the above is using it.
         | 
| 2 | 
            +
            # Else, you'll get error: Uninitialized constant
         | 
| 3 | 
            +
            require 'json'
         | 
| 4 | 
            +
            require 'net/http'
         | 
| 5 | 
            +
            require 'arcgis_vrps/orders'
         | 
| 6 | 
            +
            require 'arcgis_vrps/depots'
         | 
| 7 | 
            +
            require 'arcgis_vrps/routes'
         | 
| 8 | 
            +
            require 'arcgis_vrps/auth'
         | 
| 9 | 
            +
            require 'test/data_load'
         | 
| 10 | 
            +
             | 
| 1 11 | 
             
            class Arcgis_Vrps
         | 
| 2 | 
            -
            	 | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 12 | 
            +
            	# Use for testing for now
         | 
| 13 | 
            +
            	# def initialize()
         | 
| 14 | 
            +
            	# 	auth = Auth.new("rdvAIjUCEMegkoId", "a22acf9678c24b34960c320dddfe96cc")
         | 
| 15 | 
            +
            	# 	@token = auth.generateToken
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            	# 	puts
         | 
| 18 | 
            +
            	# 	puts "Token generated #{@token}"
         | 
| 19 | 
            +
            	# 	puts
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            	# 	loadSampleData(false) # This will get coordinates from MapSynq for all McD and write to /lib/test/sample_data/coordinateArray file. Change to true if the file don't exist
         | 
| 22 | 
            +
            	# 	# mockCase1() # Routes without any start & end time (Basic routing)
         | 
| 23 | 
            +
            	# 	mockCase2(5) # 9 locations with set times that vehicles must reach (no overlapping time)
         | 
| 24 | 
            +
            	# 	# mockCase3() # 8 locations with set times that vehicles must reach (with overlapping time)
         | 
| 25 | 
            +
            	# 	# mockCase4() # Same as use case 3 but with more overlapping times than routes available
         | 
| 26 | 
            +
            		
         | 
| 27 | 
            +
            	# 	# getOutputRoutes("jf163f4d4f7874fd69b4f6f90e2d5d9aa")
         | 
| 28 | 
            +
            	# 	# getOutputOrders("jf163f4d4f7874fd69b4f6f90e2d5d9aa")
         | 
| 29 | 
            +
            	# end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            	# def initialize(client_id, client_secret)
         | 
| 32 | 
            +
            		auth = Auth.new(client_id, client_secret)
         | 
| 33 | 
            +
            		@token = auth.generateToken
         | 
| 34 | 
            +
            		
         | 
| 35 | 
            +
            		# puts
         | 
| 36 | 
            +
            		# puts "Token generated #{@token}"
         | 
| 37 | 
            +
            		# puts
         | 
| 38 | 
            +
            		
         | 
| 5 39 | 
             
            	end
         | 
| 6 | 
            -
            end
         | 
| 7 40 |  | 
| 8 | 
            -
            #  | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 41 | 
            +
            	def submitJob(ordersObj, depotsObj, routesObj, timer) # TODO: Check to decide whether to use synchronous or async
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            		puts "Submitting job"
         | 
| 44 | 
            +
            		
         | 
| 45 | 
            +
            		jobStatusNoOfCalls = 0
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            		t1 = Time.now
         | 
| 48 | 
            +
             | 
| 49 | 
            +
            		submitJobUrl = 'https://logistics.arcgis.com/arcgis/rest/services/World/VehicleRoutingProblem/GPServer/SolveVehicleRoutingProblem/submitJob'
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            		params = {
         | 
| 52 | 
            +
            					orders: ordersObj.to_json,
         | 
| 53 | 
            +
            					depots: depotsObj.to_json,
         | 
| 54 | 
            +
            					routes: routesObj.to_json,
         | 
| 55 | 
            +
            					default_date: (Time.now.to_f * 1000).to_i,
         | 
| 56 | 
            +
            					# default_date: 1441933200000,
         | 
| 57 | 
            +
            					token: @token,
         | 
| 58 | 
            +
            					f: 'json',
         | 
| 59 | 
            +
            					time_units: 'Seconds',
         | 
| 60 | 
            +
            					distance_units: 'Meters'
         | 
| 61 | 
            +
            				}
         | 
| 62 | 
            +
             | 
| 63 | 
            +
            		res = Net::HTTP.post_form(URI(submitJobUrl), params)
         | 
| 64 | 
            +
             | 
| 65 | 
            +
            		@jobId = JSON.parse(res.body)["jobId"]
         | 
| 66 | 
            +
            		
         | 
| 67 | 
            +
             | 
| 68 | 
            +
            		if @jobId.nil?
         | 
| 69 | 
            +
            			raise "Error! #{res.body}"
         | 
| 70 | 
            +
            		else
         | 
| 71 | 
            +
            			puts "Received job ID: #{@jobId}"
         | 
| 72 | 
            +
            			print "Getting job status..."
         | 
| 73 | 
            +
             | 
| 74 | 
            +
            			if timer.nil?
         | 
| 75 | 
            +
            				timer = 1 # Timer of 500ms to constantly check for updates
         | 
| 76 | 
            +
            			end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
            			start_time = Time.now
         | 
| 79 | 
            +
            			end_time = start_time+timer
         | 
| 80 | 
            +
             | 
| 81 | 
            +
            			completed = false
         | 
| 82 | 
            +
             | 
| 83 | 
            +
            			begin
         | 
| 84 | 
            +
            				while completed == false
         | 
| 85 | 
            +
            					print "."
         | 
| 86 | 
            +
            					jobStatusNoOfCalls += 1
         | 
| 87 | 
            +
            					while Time.now < end_time
         | 
| 88 | 
            +
            					end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
            					completed = getJobStatus()
         | 
| 91 | 
            +
            				end
         | 
| 92 | 
            +
            				print "Completed!\n" 
         | 
| 93 | 
            +
            				puts
         | 
| 94 | 
            +
            				# puts completed.to_s
         | 
| 95 | 
            +
            				# puts
         | 
| 96 | 
            +
             | 
| 97 | 
            +
            				t2 = Time.now
         | 
| 98 | 
            +
             | 
| 99 | 
            +
            				time_jobStatusIsComplete = t2-t1
         | 
| 100 | 
            +
             | 
| 101 | 
            +
            				puts "Time taken for job to be completed: #{time_jobStatusIsComplete}"
         | 
| 102 | 
            +
            				puts
         | 
| 103 | 
            +
             | 
| 104 | 
            +
            				routesReceived = getOutputRoutes(nil).to_json
         | 
| 105 | 
            +
            				routesReceived = "Routes received: \n #{routesReceived}"
         | 
| 106 | 
            +
            				ordersReceived = getOutputOrders(nil).to_json
         | 
| 107 | 
            +
            				ordersReceived = "Orders received: \n #{ordersReceived}"
         | 
| 108 | 
            +
             | 
| 109 | 
            +
            				t3 = Time.now
         | 
| 110 | 
            +
             | 
| 111 | 
            +
            				time_fullJobComplete = t3-t1
         | 
| 112 | 
            +
             | 
| 113 | 
            +
            				extraContent = "Total time taken for getting routes and orders: #{time_fullJobComplete} \nNumber of calls to jobStatus: #{jobStatusNoOfCalls} \n\n"
         | 
| 114 | 
            +
            				
         | 
| 115 | 
            +
            				puts extraContent
         | 
| 116 | 
            +
            				puts
         | 
| 117 | 
            +
             | 
| 118 | 
            +
            				return extraContent, routesReceived, ordersReceived
         | 
| 119 | 
            +
            			rescue Exception => e 
         | 
| 120 | 
            +
            				puts 
         | 
| 121 | 
            +
            				puts e
         | 
| 122 | 
            +
            				puts
         | 
| 123 | 
            +
            			end
         | 
| 124 | 
            +
            		end
         | 
| 125 | 
            +
            	end
         | 
| 126 | 
            +
             | 
| 127 | 
            +
            	def getJobStatus
         | 
| 128 | 
            +
            		urlWithJobId = 'https://logistics.arcgis.com/arcgis/rest/services/World/VehicleRoutingProblem/GPServer/SolveVehicleRoutingProblem/jobs/'+@jobId
         | 
| 129 | 
            +
            		res = Net::HTTP.post_form URI(urlWithJobId),
         | 
| 130 | 
            +
            					token: @token,
         | 
| 131 | 
            +
            					returnMessages: true,
         | 
| 132 | 
            +
            					f: 'json'
         | 
| 133 | 
            +
             | 
| 134 | 
            +
            		status = JSON.parse(res.body)["jobStatus"]
         | 
| 135 | 
            +
            		# puts res.body
         | 
| 136 | 
            +
            		# puts
         | 
| 137 | 
            +
             | 
| 138 | 
            +
            		if status == "esriJobSucceeded"
         | 
| 139 | 
            +
            			return res.body
         | 
| 140 | 
            +
            		elsif status == "esriJobFailed"
         | 
| 141 | 
            +
            			raise "\nJob failed with the following message stack:\n #{res.body}"
         | 
| 142 | 
            +
            		else
         | 
| 143 | 
            +
            			return false
         | 
| 144 | 
            +
            		end
         | 
| 145 | 
            +
            	end
         | 
| 146 | 
            +
             | 
| 147 | 
            +
            	def getOutputRoutes(jobId)
         | 
| 148 | 
            +
            		unless jobId.nil?
         | 
| 149 | 
            +
            			@jobId = jobId
         | 
| 150 | 
            +
            		end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
            		urlWithJobId = 'https://logistics.arcgis.com/arcgis/rest/services/World/VehicleRoutingProblem/GPServer/SolveVehicleRoutingProblem/jobs/'+@jobId+'/results/out_routes'
         | 
| 153 | 
            +
            		
         | 
| 154 | 
            +
            		res = Net::HTTP.post_form URI(urlWithJobId),
         | 
| 155 | 
            +
            					token: @token,
         | 
| 156 | 
            +
            					f: 'json'
         | 
| 157 | 
            +
             | 
| 158 | 
            +
            		# We return the entire string is because it have meta data about the geometry type, spatial reference, etc
         | 
| 159 | 
            +
            		routesFeatures = JSON.parse(res.body)
         | 
| 160 | 
            +
            		# JSON.parse(res.body)["value"]["features"]["geometry"]["paths"] will return an array of coordinates in the following format: [longitude, latitude]
         | 
| 161 | 
            +
            		# routesFeatures = JSON.parse(res.body)["value"]["features"]
         | 
| 162 | 
            +
             | 
| 163 | 
            +
            		if routesFeatures.nil?
         | 
| 164 | 
            +
            			routesFeatures = res.body
         | 
| 165 | 
            +
            		end
         | 
| 166 | 
            +
             | 
| 167 | 
            +
            		return routesFeatures
         | 
| 168 | 
            +
            	end
         | 
| 169 | 
            +
             | 
| 170 | 
            +
            	def getOutputOrders(jobId)
         | 
| 171 | 
            +
            		unless jobId.nil?
         | 
| 172 | 
            +
            			@jobId = jobId
         | 
| 173 | 
            +
            		end
         | 
| 174 | 
            +
             | 
| 175 | 
            +
            		urlWithJobId = 'https://logistics.arcgis.com/arcgis/rest/services/World/VehicleRoutingProblem/GPServer/SolveVehicleRoutingProblem/jobs/'+@jobId+'/results/out_stops'
         | 
| 176 | 
            +
            		
         | 
| 177 | 
            +
            		res = Net::HTTP.post_form URI(urlWithJobId),
         | 
| 178 | 
            +
            					token: @token,
         | 
| 179 | 
            +
            					f: 'json'
         | 
| 180 | 
            +
             | 
| 181 | 
            +
            		# We return the entire string is because it have meta data about the geometry type, spatial reference, etc
         | 
| 182 | 
            +
            		ordersFeatures = JSON.parse(res.body)
         | 
| 183 | 
            +
            		# ordersFeatures = JSON.parse(res.body)["value"]["features"]
         | 
| 184 | 
            +
             | 
| 185 | 
            +
            		if ordersFeatures.nil?
         | 
| 186 | 
            +
            			ordersFeatures = res.body
         | 
| 187 | 
            +
            		end
         | 
| 188 | 
            +
             | 
| 189 | 
            +
            		return ordersFeatures
         | 
| 190 | 
            +
            	end
         | 
| 191 | 
            +
             | 
| 192 | 
            +
            	def loadSampleData(loadFromFile)
         | 
| 193 | 
            +
            		@loadData = Data_Load.new()
         | 
| 194 | 
            +
             | 
| 195 | 
            +
            		if loadFromFile
         | 
| 196 | 
            +
            			@loadData.getCoordinateFromMapSynq()
         | 
| 197 | 
            +
            			@loadData.writeCoordinateToFile()
         | 
| 198 | 
            +
            		end
         | 
| 199 | 
            +
            	end
         | 
| 200 | 
            +
             | 
| 201 | 
            +
            	def mockCase1(numberOfVehicles) # Routes without any start & end time (Basic routing)
         | 
| 202 | 
            +
             | 
| 203 | 
            +
            		puts "Setting up orders"
         | 
| 204 | 
            +
             | 
| 205 | 
            +
            		@loadData.getCoordinateFromFile()
         | 
| 206 | 
            +
            		coordinate = @loadData.coordinateArrayFromFile
         | 
| 207 | 
            +
             | 
| 208 | 
            +
            		ord = Orders.new()
         | 
| 209 | 
            +
             | 
| 210 | 
            +
            		i = 0
         | 
| 211 | 
            +
            		coordinate.each do |coor|
         | 
| 212 | 
            +
            			store_name = "Store_"+i.to_s
         | 
| 213 | 
            +
             | 
| 214 | 
            +
            			orderAttributeObj = ord.getBasicOrderAttributeObj(store_name)
         | 
| 215 | 
            +
            			ord.addOrders(coor[0], coor[1], orderAttributeObj)
         | 
| 216 | 
            +
             | 
| 217 | 
            +
            			if i == 50
         | 
| 218 | 
            +
            				break
         | 
| 219 | 
            +
            			end
         | 
| 220 | 
            +
             | 
| 221 | 
            +
            			i += 1
         | 
| 222 | 
            +
            		end
         | 
| 223 | 
            +
            		
         | 
| 224 | 
            +
            		ordersObj = ord.getOrderObj(nil)
         | 
| 225 | 
            +
             | 
| 226 | 
            +
            		puts "Setting up depots"
         | 
| 227 | 
            +
             | 
| 228 | 
            +
            		dep = Depots.new()
         | 
| 229 | 
            +
            		deportAttributeObj = dep.getDepotAttributeObj("depot_1")
         | 
| 230 | 
            +
            		dep.addDepots(103.848427, 1.277751, deportAttributeObj)
         | 
| 231 | 
            +
            		depotsObj = dep.getDepotObj(nil)
         | 
| 232 | 
            +
            		
         | 
| 233 | 
            +
            		puts "Setting up routes"
         | 
| 234 | 
            +
             | 
| 235 | 
            +
            		route = Routes.new()
         | 
| 236 | 
            +
            		
         | 
| 237 | 
            +
            		startDateTime = (Time.now.to_f * 1000).to_i
         | 
| 238 | 
            +
             | 
| 239 | 
            +
            		for i in 1..numberOfVehicles
         | 
| 240 | 
            +
            			truck_name = "Truck_#{i}"
         | 
| 241 | 
            +
            			route.addRoutes(truck_name, "depot_1", startDateTime, startDateTime)
         | 
| 242 | 
            +
            		end
         | 
| 243 | 
            +
            		
         | 
| 244 | 
            +
            		routesObj = route.getRouteObj()
         | 
| 245 | 
            +
             | 
| 246 | 
            +
            		begin
         | 
| 247 | 
            +
            			contents = submitJob(ordersObj, depotsObj, routesObj, nil)
         | 
| 248 | 
            +
             | 
| 249 | 
            +
            			writeToFile("Mock Case 1 - #{numberOfVehicles}.json", contents)
         | 
| 250 | 
            +
            		rescue Exception => e  
         | 
| 251 | 
            +
            			puts
         | 
| 252 | 
            +
            			puts e
         | 
| 253 | 
            +
            			puts
         | 
| 254 | 
            +
            		end
         | 
| 255 | 
            +
            	end
         | 
| 256 | 
            +
             | 
| 257 | 
            +
            	def mockCase2(numberOfVehicles) # 9 locations with set times that vehicles must reach (no overlapping time)
         | 
| 258 | 
            +
            		
         | 
| 259 | 
            +
            		puts "Setting up orders"
         | 
| 260 | 
            +
             | 
| 261 | 
            +
            		@loadData.getCoordinateFromFile()
         | 
| 262 | 
            +
            		coordinate = @loadData.coordinateArrayFromFile
         | 
| 263 | 
            +
             | 
| 264 | 
            +
            		ord = Orders.new()
         | 
| 265 | 
            +
             | 
| 266 | 
            +
            		i = 0
         | 
| 267 | 
            +
             | 
| 268 | 
            +
            		minutesInSeconds = 1800000 # 30 minutes in milliseconds
         | 
| 269 | 
            +
            		timeWindowStart1 = 1441933200000 # Default date time: 11th Sept 2015, 9:00:00 AM in milliseconds
         | 
| 270 | 
            +
            		timeWindowEnd1 = timeWindowStart1 + minutesInSeconds # Add 30 minutes every run
         | 
| 271 | 
            +
             | 
| 272 | 
            +
            		coordinate.each do |coor|
         | 
| 273 | 
            +
            			store_name = "Store_"+i.to_s
         | 
| 274 | 
            +
            			serviceTime = 30
         | 
| 275 | 
            +
             | 
| 276 | 
            +
            			if i < 9 && i >= 0
         | 
| 277 | 
            +
            				if i < 5 && i >= 1 # Can reach later than the set time here
         | 
| 278 | 
            +
            					timeWindowStart1 += (minutesInSeconds*2) # Add 1 hour every run
         | 
| 279 | 
            +
            					timeWindowEnd1 = timeWindowStart1 + minutesInSeconds # Add 30 minutes every run
         | 
| 280 | 
            +
            					maxViolationTime1 = nil
         | 
| 281 | 
            +
            				elsif i < 9 && i >= 5 # Can reach later than the set time based on the x minute set by MaxViolationTime1
         | 
| 282 | 
            +
            					timeWindowStart1 += (minutesInSeconds*2) # Add 1 hour every run
         | 
| 283 | 
            +
            					timeWindowEnd1 = timeWindowStart1 + minutesInSeconds # Add 30 minutes every run
         | 
| 284 | 
            +
            					maxViolationTime1 = 0
         | 
| 285 | 
            +
            				end
         | 
| 286 | 
            +
            				orderAttributeObj = ord.getOrderAttributeObj(store_name, serviceTime, timeWindowStart1, timeWindowEnd1, maxViolationTime1)
         | 
| 287 | 
            +
            			elsif i >= 9
         | 
| 288 | 
            +
            				timeWindowStart1 = nil
         | 
| 289 | 
            +
            				timeWindowEnd1 = nil
         | 
| 290 | 
            +
            				maxViolationTime1 = nil
         | 
| 291 | 
            +
            				orderAttributeObj = ord.getBasicOrderAttributeObj(store_name)
         | 
| 292 | 
            +
            			end		
         | 
| 293 | 
            +
             | 
| 294 | 
            +
            			ord.addOrders(coor[0], coor[1], orderAttributeObj)
         | 
| 295 | 
            +
             | 
| 296 | 
            +
            			if i == 49
         | 
| 297 | 
            +
            				break 
         | 
| 298 | 
            +
            			end
         | 
| 299 | 
            +
             | 
| 300 | 
            +
            			i += 1
         | 
| 301 | 
            +
            		end
         | 
| 302 | 
            +
            		
         | 
| 303 | 
            +
            		ordersObj = ord.getOrderObj(nil)
         | 
| 304 | 
            +
             | 
| 305 | 
            +
            		puts "Setting up depots"
         | 
| 306 | 
            +
             | 
| 307 | 
            +
            		dep = Depots.new()
         | 
| 308 | 
            +
            		deportAttributeObj = dep.getDepotAttributeObj("depot_1")
         | 
| 309 | 
            +
            		dep.addDepots(103.848427, 1.277751, deportAttributeObj)
         | 
| 310 | 
            +
            		depotsObj = dep.getDepotObj(nil)
         | 
| 311 | 
            +
            		
         | 
| 312 | 
            +
            		puts "Setting up routes"
         | 
| 313 | 
            +
             | 
| 314 | 
            +
            		route = Routes.new()
         | 
| 315 | 
            +
            		
         | 
| 316 | 
            +
            		startDateTime = 1441933200000
         | 
| 317 | 
            +
            		for i in 1..numberOfVehicles
         | 
| 318 | 
            +
            			truck_name = "Truck_#{i}"
         | 
| 319 | 
            +
            			route.addRoutes(truck_name, "depot_1", startDateTime, startDateTime)
         | 
| 320 | 
            +
            		end
         | 
| 321 | 
            +
            		
         | 
| 322 | 
            +
            		routesObj = route.getRouteObj()
         | 
| 323 | 
            +
             | 
| 324 | 
            +
            		# puts
         | 
| 325 | 
            +
            		# puts ordersObj.to_json
         | 
| 326 | 
            +
            		# puts
         | 
| 327 | 
            +
            		# puts depotsObj.to_json
         | 
| 328 | 
            +
            		# puts
         | 
| 329 | 
            +
            		# puts routesObj.to_json
         | 
| 330 | 
            +
            		# puts
         | 
| 331 | 
            +
             | 
| 332 | 
            +
            		begin
         | 
| 333 | 
            +
            			contents = submitJob(ordersObj, depotsObj, routesObj, nil)
         | 
| 334 | 
            +
             | 
| 335 | 
            +
            			writeToFile("Mock Case 2 - #{numberOfVehicles}.json", contents)
         | 
| 336 | 
            +
            		rescue Exception => e  
         | 
| 337 | 
            +
            			puts
         | 
| 338 | 
            +
            			puts e
         | 
| 339 | 
            +
            			puts
         | 
| 340 | 
            +
            		end
         | 
| 341 | 
            +
            	end
         | 
| 342 | 
            +
             | 
| 343 | 
            +
            	def mockCase3(numberOfVehicles) # 8 locations with set times that vehicles must reach (with overlapping time)
         | 
| 344 | 
            +
            		
         | 
| 345 | 
            +
            		puts "Setting up orders"
         | 
| 346 | 
            +
             | 
| 347 | 
            +
            		@loadData.getCoordinateFromFile()
         | 
| 348 | 
            +
            		coordinate = @loadData.coordinateArrayFromFile
         | 
| 349 | 
            +
             | 
| 350 | 
            +
            		ord = Orders.new()
         | 
| 351 | 
            +
             | 
| 352 | 
            +
            		i = 0
         | 
| 353 | 
            +
             | 
| 354 | 
            +
            		minutesInSeconds = 1800000 # 30 minutes in milliseconds
         | 
| 355 | 
            +
            		timeWindowStart1 = 1441933200000 # Default date time: 11th Sept 2015, 9:00:00 AM in milliseconds
         | 
| 356 | 
            +
            		timeWindowEnd1 = timeWindowStart1 + minutesInSeconds # Add 30 minutes every run
         | 
| 357 | 
            +
             | 
| 358 | 
            +
            		countThree = 0
         | 
| 359 | 
            +
            		countFive = 0
         | 
| 360 | 
            +
             | 
| 361 | 
            +
            		coordinate.each do |coor|
         | 
| 362 | 
            +
            			store_name = "Store_"+i.to_s
         | 
| 363 | 
            +
            			serviceTime = 30
         | 
| 364 | 
            +
             | 
| 365 | 
            +
            			if ((i%3 == 0 || i%5 == 0) && (countThree < 4 || countFive < 4))
         | 
| 366 | 
            +
            				if timeWindowStart1.nil? || timeWindowStart1 >= 1441944000000
         | 
| 367 | 
            +
            					timeWindowStart1 = 1441933200000
         | 
| 368 | 
            +
            				end
         | 
| 369 | 
            +
             | 
| 370 | 
            +
            				if i%3 == 0 && countThree < 4
         | 
| 371 | 
            +
            					timeWindowStart1 += (minutesInSeconds*2) # Add 1 hour every run
         | 
| 372 | 
            +
            					timeWindowEnd1 = timeWindowStart1 + minutesInSeconds # Add 30 minutes every run
         | 
| 373 | 
            +
            					maxViolationTime1 = nil
         | 
| 374 | 
            +
            					countThree += 1
         | 
| 375 | 
            +
            				elsif i%5 == 0 && countFive < 4
         | 
| 376 | 
            +
            					timeWindowStart1 += (minutesInSeconds*2) # Add 1 hour every run
         | 
| 377 | 
            +
            					timeWindowEnd1 = timeWindowStart1 + minutesInSeconds # Add 30 minutes every run
         | 
| 378 | 
            +
            					maxViolationTime1 = 0
         | 
| 379 | 
            +
            					countFive += 1
         | 
| 380 | 
            +
            				end
         | 
| 381 | 
            +
            				orderAttributeObj = ord.getOrderAttributeObj(store_name, serviceTime, timeWindowStart1, timeWindowEnd1, maxViolationTime1)
         | 
| 382 | 
            +
            			else
         | 
| 383 | 
            +
            				timeWindowStart1 = nil
         | 
| 384 | 
            +
            				timeWindowEnd1 = nil
         | 
| 385 | 
            +
            				maxViolationTime1 = nil
         | 
| 386 | 
            +
            				orderAttributeObj = ord.getBasicOrderAttributeObj(store_name)
         | 
| 387 | 
            +
            			end		
         | 
| 388 | 
            +
             | 
| 389 | 
            +
            			ord.addOrders(coor[0], coor[1], orderAttributeObj)
         | 
| 390 | 
            +
             | 
| 391 | 
            +
            			if i == 49
         | 
| 392 | 
            +
            				break 
         | 
| 393 | 
            +
            			end
         | 
| 394 | 
            +
             | 
| 395 | 
            +
            			i += 1
         | 
| 396 | 
            +
            		end
         | 
| 397 | 
            +
            		
         | 
| 398 | 
            +
            		ordersObj = ord.getOrderObj(nil)
         | 
| 399 | 
            +
             | 
| 400 | 
            +
            		puts "Setting up depots"
         | 
| 401 | 
            +
             | 
| 402 | 
            +
            		dep = Depots.new()
         | 
| 403 | 
            +
            		deportAttributeObj = dep.getDepotAttributeObj("depot_1")
         | 
| 404 | 
            +
            		dep.addDepots(103.848427, 1.277751, deportAttributeObj)
         | 
| 405 | 
            +
            		depotsObj = dep.getDepotObj(nil)
         | 
| 406 | 
            +
            		
         | 
| 407 | 
            +
            		puts "Setting up routes"
         | 
| 408 | 
            +
             | 
| 409 | 
            +
            		route = Routes.new()
         | 
| 410 | 
            +
            		
         | 
| 411 | 
            +
            		startDateTime = 1441933200000
         | 
| 412 | 
            +
            		for i in 1..numberOfVehicles
         | 
| 413 | 
            +
            			truck_name = "Truck_#{i}"
         | 
| 414 | 
            +
            			route.addRoutes(truck_name, "depot_1", startDateTime, startDateTime)
         | 
| 415 | 
            +
            		end
         | 
| 416 | 
            +
            		
         | 
| 417 | 
            +
            		routesObj = route.getRouteObj()
         | 
| 418 | 
            +
             | 
| 419 | 
            +
            		# puts
         | 
| 420 | 
            +
            		# puts ordersObj.to_json
         | 
| 421 | 
            +
            		# puts
         | 
| 422 | 
            +
            		# puts depotsObj.to_json
         | 
| 423 | 
            +
            		# puts
         | 
| 424 | 
            +
            		# puts routesObj.to_json
         | 
| 425 | 
            +
            		# puts
         | 
| 426 | 
            +
             | 
| 427 | 
            +
            		begin
         | 
| 428 | 
            +
            			contents = submitJob(ordersObj, depotsObj, routesObj, nil)
         | 
| 429 | 
            +
             | 
| 430 | 
            +
            			writeToFile("Mock Case 3 - #{numberOfVehicles}.json", contents)
         | 
| 431 | 
            +
            		rescue Exception => e  
         | 
| 432 | 
            +
            			puts
         | 
| 433 | 
            +
            			puts e
         | 
| 434 | 
            +
            			puts
         | 
| 435 | 
            +
            		end	
         | 
| 436 | 
            +
            	end
         | 
| 437 | 
            +
             | 
| 438 | 
            +
            	def mockCase4(numberOfVehicles) # Same as use case 3 but with more overlapping times than routes available
         | 
| 439 | 
            +
            		
         | 
| 440 | 
            +
            		puts "Setting up orders"
         | 
| 441 | 
            +
             | 
| 442 | 
            +
            		@loadData.getCoordinateFromFile()
         | 
| 443 | 
            +
            		coordinate = @loadData.coordinateArrayFromFile
         | 
| 444 | 
            +
             | 
| 445 | 
            +
            		ord = Orders.new()
         | 
| 446 | 
            +
             | 
| 447 | 
            +
            		i = 0
         | 
| 448 | 
            +
             | 
| 449 | 
            +
            		minutesInSeconds = 1800000 # 30 minutes in milliseconds
         | 
| 450 | 
            +
            		timeWindowStart1 = 1441933200000 # Default date time: 11th Sept 2015, 9:00:00 AM in milliseconds
         | 
| 451 | 
            +
            		timeWindowEnd1 = timeWindowStart1 + minutesInSeconds # Add 30 minutes every run
         | 
| 452 | 
            +
             | 
| 453 | 
            +
            		countThree = 0
         | 
| 454 | 
            +
            		countFive = 0
         | 
| 455 | 
            +
             | 
| 456 | 
            +
            		coordinate.each do |coor|
         | 
| 457 | 
            +
            			store_name = "Store_"+i.to_s
         | 
| 458 | 
            +
            			serviceTime = 30
         | 
| 459 | 
            +
             | 
| 460 | 
            +
            			if i < 6
         | 
| 461 | 
            +
            				# This if block is to set 3 with MaxViolationTime1 and 3 without
         | 
| 462 | 
            +
            				# if i < 3 && i >= 0
         | 
| 463 | 
            +
            				# 	maxViolationTime1 = nil
         | 
| 464 | 
            +
            				# elsif i < 6 && i >= 3
         | 
| 465 | 
            +
            				# 	maxViolationTime1 = 0
         | 
| 466 | 
            +
            				# end
         | 
| 467 | 
            +
            				maxViolationTime1 = 0 # This is to set all 6 with MaxViolationTime1
         | 
| 468 | 
            +
            				orderAttributeObj = ord.getOrderAttributeObj(store_name, serviceTime, timeWindowStart1, timeWindowEnd1, maxViolationTime1)
         | 
| 469 | 
            +
            			else
         | 
| 470 | 
            +
            				timeWindowStart1 = nil
         | 
| 471 | 
            +
            				timeWindowEnd1 = nil
         | 
| 472 | 
            +
            				maxViolationTime1 = nil
         | 
| 473 | 
            +
            				orderAttributeObj = ord.getBasicOrderAttributeObj(store_name)
         | 
| 474 | 
            +
            			end		
         | 
| 475 | 
            +
             | 
| 476 | 
            +
            			ord.addOrders(coor[0], coor[1], orderAttributeObj)
         | 
| 477 | 
            +
             | 
| 478 | 
            +
            			if i == 49
         | 
| 479 | 
            +
            				break 
         | 
| 480 | 
            +
            			end
         | 
| 481 | 
            +
             | 
| 482 | 
            +
            			i += 1
         | 
| 483 | 
            +
            		end
         | 
| 484 | 
            +
            		
         | 
| 485 | 
            +
            		ordersObj = ord.getOrderObj(nil)
         | 
| 486 | 
            +
             | 
| 487 | 
            +
            		puts "Setting up depots"
         | 
| 488 | 
            +
             | 
| 489 | 
            +
            		dep = Depots.new()
         | 
| 490 | 
            +
            		deportAttributeObj = dep.getDepotAttributeObj("depot_1")
         | 
| 491 | 
            +
            		dep.addDepots(103.848427, 1.277751, deportAttributeObj)
         | 
| 492 | 
            +
            		depotsObj = dep.getDepotObj(nil)
         | 
| 493 | 
            +
            		
         | 
| 494 | 
            +
            		puts "Setting up routes"
         | 
| 495 | 
            +
             | 
| 496 | 
            +
            		route = Routes.new()
         | 
| 497 | 
            +
            		
         | 
| 498 | 
            +
            		startDateTime = 1441933200000
         | 
| 499 | 
            +
            		for i in 1..numberOfVehicles
         | 
| 500 | 
            +
            			truck_name = "Truck_#{i}"
         | 
| 501 | 
            +
            			route.addRoutes(truck_name, "depot_1", startDateTime, startDateTime)
         | 
| 502 | 
            +
            		end
         | 
| 503 | 
            +
            		
         | 
| 504 | 
            +
            		routesObj = route.getRouteObj()
         | 
| 505 | 
            +
             | 
| 506 | 
            +
            		# puts
         | 
| 507 | 
            +
            		# puts ordersObj.to_json
         | 
| 508 | 
            +
            		# puts
         | 
| 509 | 
            +
            		# puts depotsObj.to_json
         | 
| 510 | 
            +
            		# puts
         | 
| 511 | 
            +
            		# puts routesObj.to_json
         | 
| 512 | 
            +
            		# puts
         | 
| 513 | 
            +
             | 
| 514 | 
            +
            		begin
         | 
| 515 | 
            +
            			contents = submitJob(ordersObj, depotsObj, routesObj, nil)
         | 
| 516 | 
            +
             | 
| 517 | 
            +
            			writeToFile("Mock Case 4 - location - 6.json", contents)
         | 
| 518 | 
            +
            		rescue Exception => e  
         | 
| 519 | 
            +
            			puts
         | 
| 520 | 
            +
            			puts e
         | 
| 521 | 
            +
            			puts
         | 
| 522 | 
            +
            		end	
         | 
| 523 | 
            +
            	end
         | 
| 524 | 
            +
             | 
| 525 | 
            +
            	def writeCoordinateToFile
         | 
| 526 | 
            +
            		@loadData.getCoordinateFromFile(true)
         | 
| 527 | 
            +
            		coordinate = @loadData.coordinateArrayFromFile
         | 
| 528 | 
            +
            		writeToFile("coordinateArray", coordinate.to_json);
         | 
| 529 | 
            +
            	end
         | 
| 530 | 
            +
             | 
| 531 | 
            +
            	def writeToFile(filename, contents)
         | 
| 532 | 
            +
            		puts "Writing to file #{filename}"
         | 
| 533 | 
            +
             | 
| 534 | 
            +
            		File.open("lib/test/sample_data/#{filename}", "w") do |file|
         | 
| 535 | 
            +
            			if contents.kind_of?(Array)
         | 
| 536 | 
            +
            				contents.each do |content|
         | 
| 537 | 
            +
            					file.puts content
         | 
| 538 | 
            +
            					file.puts
         | 
| 539 | 
            +
            				end
         | 
| 540 | 
            +
            			else
         | 
| 541 | 
            +
            				file.puts contents
         | 
| 542 | 
            +
            				file.puts
         | 
| 543 | 
            +
            			end
         | 
| 544 | 
            +
            		end
         | 
| 545 | 
            +
             | 
| 546 | 
            +
            		puts "Done writing to file #{filename}"
         | 
| 547 | 
            +
            		puts
         | 
| 548 | 
            +
            	end
         | 
| 549 | 
            +
            end
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            require 'json'
         | 
| 2 | 
            +
            require 'net/http'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            class Auth
         | 
| 5 | 
            +
            	def initialize(client_id, client_secret)
         | 
| 6 | 
            +
            		if client_id.nil? || client_id.empty? || client_secret.nil? || client_secret.empty?
         | 
| 7 | 
            +
            	        raise ArgumentError, "Both Client ID & Client Secret has to be set"
         | 
| 8 | 
            +
            	    end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            		@client_id = client_id
         | 
| 11 | 
            +
            		@client_secret = client_secret
         | 
| 12 | 
            +
            	end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            	def generateToken
         | 
| 15 | 
            +
            	    begin
         | 
| 16 | 
            +
            		    res = Net::HTTP.post_form URI('https://www.arcgis.com/sharing/rest/oauth2/token'),
         | 
| 17 | 
            +
            						f: 'json',
         | 
| 18 | 
            +
            						client_id: @client_id,
         | 
| 19 | 
            +
            						client_secret: @client_secret,
         | 
| 20 | 
            +
            						grant_type: 'client_credentials'
         | 
| 21 | 
            +
            			
         | 
| 22 | 
            +
            			token = JSON.parse(res.body)['access_token']
         | 
| 23 | 
            +
            			# puts "\n"+res.body
         | 
| 24 | 
            +
            			return token
         | 
| 25 | 
            +
            		rescue => e
         | 
| 26 | 
            +
            			puts e
         | 
| 27 | 
            +
            		end
         | 
| 28 | 
            +
            	end
         | 
| 29 | 
            +
            end
         | 
| @@ -0,0 +1,57 @@ | |
| 1 | 
            +
            class Depots
         | 
| 2 | 
            +
            	# Longitude => xCoordinate, Latitude => yCoordinate
         | 
| 3 | 
            +
            	def addDepots (xCoordinate, yCoordinate, depotAttributeObj)
         | 
| 4 | 
            +
            		my_depot = {
         | 
| 5 | 
            +
            					:geometry => {
         | 
| 6 | 
            +
            			          :x => xCoordinate,
         | 
| 7 | 
            +
            			          :y => yCoordinate
         | 
| 8 | 
            +
            			        },
         | 
| 9 | 
            +
            			        :attributes => depotAttributeObj
         | 
| 10 | 
            +
            		    	}
         | 
| 11 | 
            +
            		if @depotArr.nil?
         | 
| 12 | 
            +
            			@depotArr = []
         | 
| 13 | 
            +
            		end
         | 
| 14 | 
            +
            		
         | 
| 15 | 
            +
            		@depotArr.push(my_depot)
         | 
| 16 | 
            +
            	end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            	def getDepotArr
         | 
| 19 | 
            +
            		return @depotArr
         | 
| 20 | 
            +
            	end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            	def getDepotAttributeObj(depotName)
         | 
| 23 | 
            +
            		depotAttributeObj =	{
         | 
| 24 | 
            +
            			:Name => depotName
         | 
| 25 | 
            +
            		}
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            		return depotAttributeObj
         | 
| 28 | 
            +
            	end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            	# Get the Orders Attribute Object from the param passed in
         | 
| 31 | 
            +
            	# def getDepotAttributeObj(depotName, timeStart1, timeEnd1)
         | 
| 32 | 
            +
            	# 	depotAttributeObj =	{
         | 
| 33 | 
            +
            	# 		:Name => depotName,
         | 
| 34 | 
            +
            	# 		:TimeWindowStart1 => timeStart1,
         | 
| 35 | 
            +
            	# 		:TimeWindowEnd1 => timeEnd1
         | 
| 36 | 
            +
            	# 	}
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            	# 	return depotAttributeObj
         | 
| 39 | 
            +
            	# end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            	def getDepotObj (wkid)
         | 
| 42 | 
            +
            		if wkid.nil?
         | 
| 43 | 
            +
            			depotObj = {
         | 
| 44 | 
            +
            				:features => @depotArr
         | 
| 45 | 
            +
            			}
         | 
| 46 | 
            +
            		else
         | 
| 47 | 
            +
            			depotObj = {
         | 
| 48 | 
            +
            				:spatialReference => {
         | 
| 49 | 
            +
            					:wkid => wkid
         | 
| 50 | 
            +
            				},
         | 
| 51 | 
            +
            				:features => @depotArr
         | 
| 52 | 
            +
            			}
         | 
| 53 | 
            +
            		end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
            		return depotObj
         | 
| 56 | 
            +
            	end
         | 
| 57 | 
            +
            end
         | 
| @@ -0,0 +1,85 @@ | |
| 1 | 
            +
            class Orders
         | 
| 2 | 
            +
            	# Longitude => xCoordinate, Latitude => yCoordinate
         | 
| 3 | 
            +
            	def addOrders (xCoordinate, yCoordinate, orderAttributeObj)
         | 
| 4 | 
            +
            		my_order = {
         | 
| 5 | 
            +
            					:geometry => {
         | 
| 6 | 
            +
            			          :x => xCoordinate,
         | 
| 7 | 
            +
            			          :y => yCoordinate
         | 
| 8 | 
            +
            			        },
         | 
| 9 | 
            +
            			        :attributes => orderAttributeObj
         | 
| 10 | 
            +
            		    	}
         | 
| 11 | 
            +
            		if @orderArr.nil?
         | 
| 12 | 
            +
            			@orderArr = []
         | 
| 13 | 
            +
            		end
         | 
| 14 | 
            +
            		
         | 
| 15 | 
            +
            		@orderArr.push(my_order)
         | 
| 16 | 
            +
            	end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            	def getOrderArr
         | 
| 19 | 
            +
            		return @orderArr
         | 
| 20 | 
            +
            	end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            	# Get basic Orders Attribute Object from the param passed in
         | 
| 23 | 
            +
            	def getBasicOrderAttributeObj (orderName)
         | 
| 24 | 
            +
            		orderAttributeObj =	{
         | 
| 25 | 
            +
            			:Name => orderName
         | 
| 26 | 
            +
            		}
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            		return orderAttributeObj
         | 
| 29 | 
            +
            	end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            	# Get orders attribute object from the param passed in
         | 
| 32 | 
            +
            	# timeWindow* refers to the time that the service
         | 
| 33 | 
            +
            	def getOrderAttributeObj (orderName, serviceTime, timeWindowStart1, timeWindowEnd1, maxViolationTime1)
         | 
| 34 | 
            +
            		if maxViolationTime1.nil?
         | 
| 35 | 
            +
            			orderAttributeObj =	{
         | 
| 36 | 
            +
            				:Name => orderName,
         | 
| 37 | 
            +
            				:ServiceTime => serviceTime,
         | 
| 38 | 
            +
            				:TimeWindowStart1 => timeWindowStart1,
         | 
| 39 | 
            +
            				:TimeWindowEnd1 => timeWindowEnd1
         | 
| 40 | 
            +
            			}
         | 
| 41 | 
            +
            		else
         | 
| 42 | 
            +
            			orderAttributeObj =	{
         | 
| 43 | 
            +
            				:Name => orderName,
         | 
| 44 | 
            +
            				:ServiceTime => serviceTime,
         | 
| 45 | 
            +
            				:TimeWindowStart1 => timeWindowStart1,
         | 
| 46 | 
            +
            				:TimeWindowEnd1 => timeWindowEnd1,
         | 
| 47 | 
            +
            				:MaxViolationTime1 => maxViolationTime1
         | 
| 48 | 
            +
            			}
         | 
| 49 | 
            +
            		end
         | 
| 50 | 
            +
            		
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            		return orderAttributeObj
         | 
| 53 | 
            +
            	end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
            	# Get the Orders Attribute Object from the param passed in
         | 
| 56 | 
            +
            	# def getOrderAttributeObj (orderName, deliveryQty, serviceTime, timeStart1, timeEnd1, maxViolationTime)
         | 
| 57 | 
            +
            	# 	orderAttributeObj =	{
         | 
| 58 | 
            +
            	# 		:Name => orderName,
         | 
| 59 | 
            +
            	# 		:DeliveryQuantities => deliveryQty,
         | 
| 60 | 
            +
            	# 		:ServiceTime => serviceTime,
         | 
| 61 | 
            +
            	# 		:TimeWindowStart1 => timeStart1,
         | 
| 62 | 
            +
            	# 		:TimeWindowEnd1 => timeEnd1,
         | 
| 63 | 
            +
            	# 		:MaxViolationTime1 => maxViolationTime
         | 
| 64 | 
            +
            	# 	}
         | 
| 65 | 
            +
             | 
| 66 | 
            +
            	# 	return orderAttributeObj
         | 
| 67 | 
            +
            	# end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
            	def getOrderObj (wkid)
         | 
| 70 | 
            +
            		if wkid.nil?
         | 
| 71 | 
            +
            			orderObj = {
         | 
| 72 | 
            +
            				:features => @orderArr
         | 
| 73 | 
            +
            			}
         | 
| 74 | 
            +
            		else
         | 
| 75 | 
            +
            			orderObj = {
         | 
| 76 | 
            +
            				:spatialReference => {
         | 
| 77 | 
            +
            					:wkid => wkid
         | 
| 78 | 
            +
            				},
         | 
| 79 | 
            +
            				:features => @orderArr
         | 
| 80 | 
            +
            			}
         | 
| 81 | 
            +
            		end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
            		return orderObj
         | 
| 84 | 
            +
            	end
         | 
| 85 | 
            +
            end
         | 
| @@ -0,0 +1,56 @@ | |
| 1 | 
            +
            class Routes
         | 
| 2 | 
            +
            	def addRoutes (routeName, startDepotName, earliestStartTime, latestStartTime)
         | 
| 3 | 
            +
            		my_route = {
         | 
| 4 | 
            +
            			        :attributes => {
         | 
| 5 | 
            +
            			          :Name => routeName,
         | 
| 6 | 
            +
            			          :StartDepotName => startDepotName, # Either this or EndDepotName must be present. This is a foreign key to the "Name" attribute in the depots param. Thus, the values MUST match
         | 
| 7 | 
            +
            			          :EarliestStartTime  => earliestStartTime,
         | 
| 8 | 
            +
            			          :LatestStartTime => latestStartTime
         | 
| 9 | 
            +
            			        }
         | 
| 10 | 
            +
            		    	}
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            		if @routeArr.nil?
         | 
| 13 | 
            +
            			@routeArr = []
         | 
| 14 | 
            +
            		end
         | 
| 15 | 
            +
            		
         | 
| 16 | 
            +
            		@routeArr.push(my_route)
         | 
| 17 | 
            +
            	end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            	# def addRoutes (routeName, startDepotName, endDepotName, startDepotServiceTime, earliestStartTime, latestStartTime, capacities, costPerUnitTime, costPerUnitDistance, maxOrderCount, maxTotalTime, maxTotalTravelTime, maxTotalDistance)
         | 
| 20 | 
            +
            	# 	my_route = {
         | 
| 21 | 
            +
            	# 		        :attributes => {
         | 
| 22 | 
            +
            	# 		          :Name => routeName,
         | 
| 23 | 
            +
            	# 		          :StartDepotName => startDepotName, # Either this or EndDepotName must be present. This is a foreign key to the "Name" attribute in the depots param. Thus, the values MUST match
         | 
| 24 | 
            +
            	# 		          :EndDepotName => endDepotName,
         | 
| 25 | 
            +
            	# 		          :StartDepotServiceTime => startDepotServiceTime,
         | 
| 26 | 
            +
            	# 		          :EarliestStartTime => earliestStartTime,
         | 
| 27 | 
            +
            	# 		          :LatestStartTime => latestStartTime,
         | 
| 28 | 
            +
            	# 		          :Capacities => capacities,
         | 
| 29 | 
            +
            	# 		          :CostPerUnitTime => costPerUnitTime,
         | 
| 30 | 
            +
            	# 		          :CostPerUnitDistance => costPerUnitDistance,
         | 
| 31 | 
            +
            	# 		          :MaxOrderCount => maxOrderCount,
         | 
| 32 | 
            +
            	# 		          :MaxTotalTime => maxTotalTime,
         | 
| 33 | 
            +
            	# 		          :MaxTotalTravelTime => maxTotalTravelTime,
         | 
| 34 | 
            +
            	# 		          :MaxTotalDistance => maxTotalDistance
         | 
| 35 | 
            +
            	# 		        }
         | 
| 36 | 
            +
            	# 	    	}
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            	# 	if @routeArr.nil?
         | 
| 39 | 
            +
            	# 		@routeArr = []
         | 
| 40 | 
            +
            	# 	end
         | 
| 41 | 
            +
            		
         | 
| 42 | 
            +
            	# 	@routeArr.push(my_route)
         | 
| 43 | 
            +
            	# end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            	def getRouteArr
         | 
| 46 | 
            +
            		return @routeArr
         | 
| 47 | 
            +
            	end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
            	def getRouteObj
         | 
| 50 | 
            +
            		routeObj = {
         | 
| 51 | 
            +
            			:features => @routeArr
         | 
| 52 | 
            +
            		}
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            		return routeObj
         | 
| 55 | 
            +
            	end
         | 
| 56 | 
            +
            end
         | 
| @@ -0,0 +1,116 @@ | |
| 1 | 
            +
            require 'net/http'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class Data_Load
         | 
| 4 | 
            +
            	attr_accessor :coordinateArrayFromFile, :postcodeArrayFromFile, :coordinateArrayFromServer
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            	def initialize
         | 
| 7 | 
            +
            		# Will there be an instance where @postcodeArrayFromFile is nil?
         | 
| 8 | 
            +
            		if @postcodeArrayFromFile.nil?
         | 
| 9 | 
            +
            				@postcodeArrayFromFile = []
         | 
| 10 | 
            +
            		end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            		if @coordinateArrayFromServer.nil?
         | 
| 13 | 
            +
            			@coordinateArrayFromServer = []
         | 
| 14 | 
            +
            		end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            		if @coordinateArrayFromFile.nil?
         | 
| 17 | 
            +
            			@coordinateArrayFromFile = []
         | 
| 18 | 
            +
            		end
         | 
| 19 | 
            +
            	end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            	def getCoordinateFromMapSynq
         | 
| 22 | 
            +
            		puts "Getting postcodes from file..."
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            		getPostcodeFromFile()
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            		print "Requesting coordinates from server..."
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            		@postcodeArrayFromFile.each do |postcode|
         | 
| 29 | 
            +
            			print "."
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            			mapsynqUrl = "http://www.mapsynq.com/home/search1?q=#{postcode}&lat=&lon=&page=1"
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            			begin
         | 
| 34 | 
            +
            				url = URI.parse(mapsynqUrl)
         | 
| 35 | 
            +
            				req = Net::HTTP::Get.new(url.to_s)
         | 
| 36 | 
            +
            				res = Net::HTTP.start(url.host, url.port) {|http|
         | 
| 37 | 
            +
            				  http.request(req)
         | 
| 38 | 
            +
            				}
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            				result = JSON.parse(res.body)["result"]
         | 
| 41 | 
            +
            				
         | 
| 42 | 
            +
            				unless result.empty?
         | 
| 43 | 
            +
            					yCoordinate = result[0]["true_latitude"]
         | 
| 44 | 
            +
            					xCoordinate = result[0]["true_longitude"]
         | 
| 45 | 
            +
            					coordinate = "#{xCoordinate}-#{yCoordinate}"
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            					coordinateArrayFromServer.push(coordinate)
         | 
| 48 | 
            +
            				end
         | 
| 49 | 
            +
            			rescue
         | 
| 50 | 
            +
            				puts $!, $@
         | 
| 51 | 
            +
            				puts
         | 
| 52 | 
            +
            				next
         | 
| 53 | 
            +
            			end
         | 
| 54 | 
            +
            		end
         | 
| 55 | 
            +
            		print "\n"
         | 
| 56 | 
            +
            		puts "Done requesting coordinates from server"
         | 
| 57 | 
            +
            		puts
         | 
| 58 | 
            +
            	end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            	def getPostcodeFromFile
         | 
| 61 | 
            +
            		puts "Getting postcodes from file"
         | 
| 62 | 
            +
             | 
| 63 | 
            +
            		File.open("lib/test/sample_data/postcodes", "r") do |file|
         | 
| 64 | 
            +
            			while line = file.gets
         | 
| 65 | 
            +
            				@postcodeArrayFromFile.push(line.strip)
         | 
| 66 | 
            +
            			end
         | 
| 67 | 
            +
            		end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
            		puts "Done getting postcodes from file"
         | 
| 70 | 
            +
            		puts
         | 
| 71 | 
            +
            	end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
            	def getCoordinateFromFile(convertToNumbers = nil)
         | 
| 74 | 
            +
            		puts "Getting coordinates from file"
         | 
| 75 | 
            +
            		if convertToNumbers.nil?
         | 
| 76 | 
            +
            			convertToNumbers = false
         | 
| 77 | 
            +
            		end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
            		File.open("lib/test/sample_data/coordinates", "r") do |file|
         | 
| 80 | 
            +
            			while line = file.gets
         | 
| 81 | 
            +
            				coordinate = line.strip.split("-")
         | 
| 82 | 
            +
            				if convertToNumbers == true
         | 
| 83 | 
            +
            					if coordinate[0].is_number? && coordinate[1].is_number?
         | 
| 84 | 
            +
            						coordinate[0] = coordinate[0].to_f
         | 
| 85 | 
            +
            						coordinate[1] = coordinate[1].to_f
         | 
| 86 | 
            +
            					else
         | 
| 87 | 
            +
            						raise "Error! #{coordinate[0]} & #{coordinate[1]} is not a number!"
         | 
| 88 | 
            +
            					end
         | 
| 89 | 
            +
            				end
         | 
| 90 | 
            +
            				@coordinateArrayFromFile.push(coordinate)
         | 
| 91 | 
            +
            			end
         | 
| 92 | 
            +
            		end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
            		puts "Done getting coordinates from file"
         | 
| 95 | 
            +
            		puts
         | 
| 96 | 
            +
            	end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
            	def writeCoordinateToFile
         | 
| 99 | 
            +
            		puts "Writing coordinates to file"
         | 
| 100 | 
            +
             | 
| 101 | 
            +
            		File.open("lib/test/sample_data/coordinates", "w") do |file|
         | 
| 102 | 
            +
            			@coordinateArrayFromServer.each do |coordinate|
         | 
| 103 | 
            +
            				file.puts coordinate
         | 
| 104 | 
            +
            			end
         | 
| 105 | 
            +
            		end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
            		puts "Done writing coordinates to file"
         | 
| 108 | 
            +
            		puts
         | 
| 109 | 
            +
            	end
         | 
| 110 | 
            +
            end
         | 
| 111 | 
            +
             | 
| 112 | 
            +
            class String
         | 
| 113 | 
            +
              def is_number?
         | 
| 114 | 
            +
                true if Float(self) rescue false
         | 
| 115 | 
            +
              end
         | 
| 116 | 
            +
            end
         | 
| @@ -0,0 +1,129 @@ | |
| 1 | 
            +
            018954
         | 
| 2 | 
            +
            237978
         | 
| 3 | 
            +
            098138
         | 
| 4 | 
            +
            731678
         | 
| 5 | 
            +
            259727
         | 
| 6 | 
            +
            569922
         | 
| 7 | 
            +
            560163
         | 
| 8 | 
            +
            560448
         | 
| 9 | 
            +
            567740
         | 
| 10 | 
            +
            329783
         | 
| 11 | 
            +
            588177
         | 
| 12 | 
            +
            469661
         | 
| 13 | 
            +
            467360
         | 
| 14 | 
            +
            460539
         | 
| 15 | 
            +
            470632
         | 
| 16 | 
            +
            470744
         | 
| 17 | 
            +
            330022
         | 
| 18 | 
            +
            579837
         | 
| 19 | 
            +
            569981
         | 
| 20 | 
            +
            048508
         | 
| 21 | 
            +
            188024
         | 
| 22 | 
            +
            188426
         | 
| 23 | 
            +
            650632
         | 
| 24 | 
            +
            659841
         | 
| 25 | 
            +
            650152
         | 
| 26 | 
            +
            650374
         | 
| 27 | 
            +
            677743
         | 
| 28 | 
            +
            738099
         | 
| 29 | 
            +
            819643
         | 
| 30 | 
            +
            819633
         | 
| 31 | 
            +
            486038
         | 
| 32 | 
            +
            680624
         | 
| 33 | 
            +
            680623
         | 
| 34 | 
            +
            689812
         | 
| 35 | 
            +
            689810
         | 
| 36 | 
            +
            680533
         | 
| 37 | 
            +
            768677
         | 
| 38 | 
            +
            688892
         | 
| 39 | 
            +
            208539
         | 
| 40 | 
            +
            120451
         | 
| 41 | 
            +
            129588
         | 
| 42 | 
            +
            545078
         | 
| 43 | 
            +
            528833
         | 
| 44 | 
            +
            519498
         | 
| 45 | 
            +
            629117
         | 
| 46 | 
            +
            670445
         | 
| 47 | 
            +
            258748
         | 
| 48 | 
            +
            238884
         | 
| 49 | 
            +
            179097
         | 
| 50 | 
            +
            640762
         | 
| 51 | 
            +
            380113
         | 
| 52 | 
            +
            237994
         | 
| 53 | 
            +
            099253
         | 
| 54 | 
            +
            530208
         | 
| 55 | 
            +
            538692
         | 
| 56 | 
            +
            530684
         | 
| 57 | 
            +
            538766
         | 
| 58 | 
            +
            099010
         | 
| 59 | 
            +
            188067
         | 
| 60 | 
            +
            609601
         | 
| 61 | 
            +
            209037
         | 
| 62 | 
            +
            609731
         | 
| 63 | 
            +
            608549
         | 
| 64 | 
            +
            618640
         | 
| 65 | 
            +
            649849
         | 
| 66 | 
            +
            600256
         | 
| 67 | 
            +
            649520
         | 
| 68 | 
            +
            648886
         | 
| 69 | 
            +
            649296
         | 
| 70 | 
            +
            397726
         | 
| 71 | 
            +
            760846
         | 
| 72 | 
            +
            229899
         | 
| 73 | 
            +
            179030
         | 
| 74 | 
            +
            238868
         | 
| 75 | 
            +
            510258
         | 
| 76 | 
            +
            238863
         | 
| 77 | 
            +
            039594
         | 
| 78 | 
            +
            138588
         | 
| 79 | 
            +
            569830
         | 
| 80 | 
            +
            637331
         | 
| 81 | 
            +
            117587
         | 
| 82 | 
            +
            556083
         | 
| 83 | 
            +
            188721
         | 
| 84 | 
            +
            769098
         | 
| 85 | 
            +
            188307
         | 
| 86 | 
            +
            449408
         | 
| 87 | 
            +
            519640
         | 
| 88 | 
            +
            059108
         | 
| 89 | 
            +
            640638
         | 
| 90 | 
            +
            238839
         | 
| 91 | 
            +
            350148
         | 
| 92 | 
            +
            119963
         | 
| 93 | 
            +
            828815
         | 
| 94 | 
            +
            149066
         | 
| 95 | 
            +
            149053
         | 
| 96 | 
            +
            179103
         | 
| 97 | 
            +
            159460
         | 
| 98 | 
            +
            545082
         | 
| 99 | 
            +
            797653
         | 
| 100 | 
            +
            540118
         | 
| 101 | 
            +
            544964
         | 
| 102 | 
            +
            550267
         | 
| 103 | 
            +
            555951
         | 
| 104 | 
            +
            455871
         | 
| 105 | 
            +
            138651
         | 
| 106 | 
            +
            609081
         | 
| 107 | 
            +
            757713
         | 
| 108 | 
            +
            520513
         | 
| 109 | 
            +
            520512
         | 
| 110 | 
            +
            529341
         | 
| 111 | 
            +
            529510
         | 
| 112 | 
            +
            529284
         | 
| 113 | 
            +
            529705
         | 
| 114 | 
            +
            529757
         | 
| 115 | 
            +
            168732
         | 
| 116 | 
            +
            319515
         | 
| 117 | 
            +
            310490
         | 
| 118 | 
            +
            310109
         | 
| 119 | 
            +
            319387
         | 
| 120 | 
            +
            609971
         | 
| 121 | 
            +
            307591
         | 
| 122 | 
            +
            208767
         | 
| 123 | 
            +
            126844
         | 
| 124 | 
            +
            738931
         | 
| 125 | 
            +
            730900
         | 
| 126 | 
            +
            730768
         | 
| 127 | 
            +
            758382
         | 
| 128 | 
            +
            760293
         | 
| 129 | 
            +
            769027
         | 
    
        metadata
    CHANGED
    
    | @@ -1,47 +1,67 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: arcgis_vrps
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0.2. | 
| 4 | 
            +
              version: 0.0.2.2
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Kiong
         | 
| 8 | 
            -
            autorequire: | 
| 8 | 
            +
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 11 | 
             
            date: 2015-09-08 00:00:00.000000000 Z
         | 
| 12 | 
            -
            dependencies: | 
| 13 | 
            -
             | 
| 14 | 
            -
               | 
| 15 | 
            -
             | 
| 12 | 
            +
            dependencies:
         | 
| 13 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 15 | 
            +
                requirements:
         | 
| 16 | 
            +
                - - ~>
         | 
| 17 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 18 | 
            +
                    version: '1.8'
         | 
| 19 | 
            +
              name: json
         | 
| 20 | 
            +
              prerelease: false
         | 
| 21 | 
            +
              type: :runtime
         | 
| 22 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            +
                requirements:
         | 
| 24 | 
            +
                - - ~>
         | 
| 25 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            +
                    version: '1.8'
         | 
| 27 | 
            +
            description: A ruby gem interface for ArcGIS (platform of Esri) Vehicle Routing Problem service REST API
         | 
| 16 28 | 
             
            email: kiong90@gmail.com
         | 
| 17 29 | 
             
            executables: []
         | 
| 18 30 | 
             
            extensions: []
         | 
| 19 | 
            -
            extra_rdoc_files: | 
| 31 | 
            +
            extra_rdoc_files:
         | 
| 32 | 
            +
            - README.md
         | 
| 20 33 | 
             
            files:
         | 
| 21 | 
            -
            - lib/arcgis_vrps.rb
         | 
| 22 | 
            -
            - lib/arcgis_vrps/ | 
| 34 | 
            +
            - ./lib/arcgis_vrps.rb
         | 
| 35 | 
            +
            - ./lib/arcgis_vrps/auth.rb
         | 
| 36 | 
            +
            - ./lib/arcgis_vrps/depots.rb
         | 
| 37 | 
            +
            - ./lib/arcgis_vrps/orders.rb
         | 
| 38 | 
            +
            - ./lib/arcgis_vrps/routes.rb
         | 
| 39 | 
            +
            - ./lib/test/data_load.rb
         | 
| 40 | 
            +
            - ./lib/test/sample_data/postcodes
         | 
| 41 | 
            +
            - README.md
         | 
| 23 42 | 
             
            homepage: http://rubygems.org/gems/arcgis_vrps
         | 
| 24 43 | 
             
            licenses:
         | 
| 25 44 | 
             
            - MIT
         | 
| 26 | 
            -
            metadata: | 
| 27 | 
            -
             | 
| 45 | 
            +
            metadata:
         | 
| 46 | 
            +
              source_code: https://github.com/tlkiong/arcgis_vrps
         | 
| 47 | 
            +
            post_install_message:
         | 
| 28 48 | 
             
            rdoc_options: []
         | 
| 29 49 | 
             
            require_paths:
         | 
| 30 50 | 
             
            - lib
         | 
| 31 51 | 
             
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 32 52 | 
             
              requirements:
         | 
| 33 | 
            -
              - -  | 
| 53 | 
            +
              - - '>='
         | 
| 34 54 | 
             
                - !ruby/object:Gem::Version
         | 
| 35 55 | 
             
                  version: '0'
         | 
| 36 56 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 37 57 | 
             
              requirements:
         | 
| 38 | 
            -
              - -  | 
| 58 | 
            +
              - - '>='
         | 
| 39 59 | 
             
                - !ruby/object:Gem::Version
         | 
| 40 60 | 
             
                  version: '0'
         | 
| 41 61 | 
             
            requirements: []
         | 
| 42 | 
            -
            rubyforge_project: | 
| 43 | 
            -
            rubygems_version: 2. | 
| 44 | 
            -
            signing_key: | 
| 62 | 
            +
            rubyforge_project:
         | 
| 63 | 
            +
            rubygems_version: 2.1.9
         | 
| 64 | 
            +
            signing_key:
         | 
| 45 65 | 
             
            specification_version: 4
         | 
| 46 | 
            -
            summary:  | 
| 66 | 
            +
            summary: ArcGIS Vehicle Routing Problem service API
         | 
| 47 67 | 
             
            test_files: []
         |