cloudfactory 0.4.4 → 0.4.5
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.
- data/CHANGELOG.md +7 -0
- data/lib/cf.rb +4 -1
- data/lib/cf/badge.rb +59 -0
- data/lib/cf/cli.rb +6 -0
- data/lib/cf/cli/line.rb +185 -132
- data/lib/cf/cli/line_yaml_validator.rb +7 -30
- data/lib/cf/cli/production.rb +63 -9
- data/lib/cf/gold_standard.rb +74 -0
- data/lib/cf/help.txt +67 -0
- data/lib/cf/human_worker.rb +45 -49
- data/lib/cf/line.rb +51 -1
- data/lib/cf/run.rb +10 -10
- data/lib/cf/station.rb +111 -29
- data/lib/cf/test_run.rb +66 -0
- data/lib/cf/version.rb +1 -1
- data/spec/account_spec.rb +1 -1
- data/spec/badges/station_1.html +135 -0
- data/spec/badges_spec.rb +288 -0
- data/spec/gold_standard_spec.rb +179 -0
- data/spec/gold_standards.csv +2 -0
- data/spec/google_translate_robot_spec.rb +1 -1
- data/spec/human_worker_spec.rb +1 -65
- data/spec/line_spec.rb +6 -39
- data/spec/robot_worker_spec.rb +1 -1
- data/spec/run_spec.rb +9 -7
- data/spec/stat_badge_spec.rb +45 -0
- data/spec/test_run_spec.rb +105 -0
- metadata +264 -218
- data/spec/badge_spec.rb +0 -88
data/lib/cf/line.rb
CHANGED
@@ -38,6 +38,7 @@ module CF
|
|
38
38
|
def initialize(title, department_name, options={})
|
39
39
|
@input_formats =[]
|
40
40
|
@stations =[]
|
41
|
+
@gold_standards = []
|
41
42
|
@title = title
|
42
43
|
@department_name = department_name
|
43
44
|
@public = options[:public].nil? ? true : options[:public]
|
@@ -222,10 +223,59 @@ module CF
|
|
222
223
|
@output_formats
|
223
224
|
end
|
224
225
|
end
|
225
|
-
|
226
|
+
|
226
227
|
def output_formats=(output_format) # :nodoc:
|
227
228
|
@output_formats = output_format
|
228
229
|
end
|
230
|
+
|
231
|
+
|
232
|
+
#specify the goldstandards for the line
|
233
|
+
# ===Usage Example:
|
234
|
+
# CF::GoldStandard.new({ :line => line,:name => "easy", :input => [{'image_url' =>"http://onwired.com/images/portfolio/linda-stanley-business-card.jpg"}],:expected_output => [{"first_name" => {"value" => "John"}, "last_name" => {"value" => "Lennon"}, "company" => {"value" => "Sprout"}}]})
|
235
|
+
def gold_standards gold_standard = nil
|
236
|
+
if gold_standard
|
237
|
+
line = self
|
238
|
+
gold_standard_options = gold_standard.settings
|
239
|
+
if !gold_standard_options.nil?
|
240
|
+
# check whether the gold standard is from a file or not(check for bulk assignment of goldstandards)
|
241
|
+
if gold_standard_options[:file]
|
242
|
+
puts gold_standard_options[:file]
|
243
|
+
if File.exist?(gold_standard_options[:file].to_s)
|
244
|
+
file_upload = File.new(gold_standard_options[:file], 'rb')
|
245
|
+
resp = self.class.post("/lines/#{CF.account_name}/#{line.title.downcase}/gold_standards.json", {:file => file_upload})
|
246
|
+
gold_standard = CF::GoldStandard.new()
|
247
|
+
resp.each do |gs|
|
248
|
+
gold_standard.settings.merge!(gs.to_hash)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
else
|
252
|
+
request =
|
253
|
+
{
|
254
|
+
:body =>
|
255
|
+
{
|
256
|
+
:api_key => CF.api_key,
|
257
|
+
:gold_standard => gold_standard_options
|
258
|
+
}
|
259
|
+
}
|
260
|
+
resp = HTTParty.post("#{CF.api_url}#{CF.api_version}/lines/#{CF.account_name}/#{line.title.downcase}/gold_standards.json",request)
|
261
|
+
gold_standard = CF::GoldStandard.new()
|
262
|
+
resp.parsed_response.first.delete("id")
|
263
|
+
gold_standard.settings.merge!(resp.parsed_response.first.symbolize_keys)
|
264
|
+
self.errors = resp.parsed_response['error']['message'] if resp.code != 200
|
265
|
+
end
|
266
|
+
@gold_standards << gold_standard
|
267
|
+
end
|
268
|
+
else
|
269
|
+
@gold_standards
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
|
274
|
+
def gold_standards=(gold_standard) # :nodoc:
|
275
|
+
@gold_standards << gold_standard
|
276
|
+
end
|
277
|
+
|
278
|
+
|
229
279
|
# ==Returns the content of a line by making an Api call
|
230
280
|
# ===Usage Example:
|
231
281
|
# CF::Line.info(line)
|
data/lib/cf/run.rb
CHANGED
@@ -168,38 +168,38 @@ module CF
|
|
168
168
|
return resp
|
169
169
|
end
|
170
170
|
end
|
171
|
-
|
171
|
+
|
172
172
|
# ==Returns progress of the production run
|
173
173
|
# ===Usage Example:
|
174
174
|
# progress = CF::Run.progress("run_title")
|
175
175
|
def self.progress(run_title)
|
176
176
|
get("/runs/#{CF.account_name}/#{run_title}/progress.json")
|
177
177
|
end
|
178
|
-
|
178
|
+
|
179
179
|
def progress # :nodoc:
|
180
180
|
self.class.get("/runs/#{CF.account_name}/#{self.title}/progress.json")
|
181
181
|
end
|
182
|
-
|
182
|
+
|
183
183
|
# ==Returns progress details of the production run
|
184
184
|
# ===Usage Example:
|
185
185
|
# progress = CF::Run.progress_details("run_title")
|
186
186
|
def self.progress_details(run_title)
|
187
|
-
resp = get("/runs/#{CF.account_name}/#{run_title}/
|
188
|
-
return resp['
|
187
|
+
resp = get("/runs/#{CF.account_name}/#{run_title}/progress.json")
|
188
|
+
return resp['progress']
|
189
189
|
end
|
190
|
-
|
190
|
+
|
191
191
|
def progress_details # :nodoc:
|
192
|
-
resp = self.class.get("/runs/#{CF.account_name}/#{self.title}/
|
193
|
-
return resp['
|
192
|
+
resp = self.class.get("/runs/#{CF.account_name}/#{self.title}/progress.json")
|
193
|
+
return resp['progress']
|
194
194
|
end
|
195
|
-
|
195
|
+
|
196
196
|
# ==Returns all runs of a line
|
197
197
|
# ===Usage Example:
|
198
198
|
# progress = CF::Run.all({:line_title => "line_title", :page => 1)
|
199
199
|
def self.all(options={})
|
200
200
|
page = options[:page].presence
|
201
201
|
line_title = options[:line_title].presence
|
202
|
-
|
202
|
+
|
203
203
|
if line_title.nil?
|
204
204
|
if page.nil?
|
205
205
|
resp = get("/runs/#{CF.account_name}.json")
|
data/lib/cf/station.rb
CHANGED
@@ -11,22 +11,22 @@ module CF
|
|
11
11
|
|
12
12
|
# Index number of station
|
13
13
|
attr_accessor :index
|
14
|
-
|
14
|
+
|
15
15
|
# Line attribute of the station with which station is associated
|
16
16
|
attr_accessor :line
|
17
|
-
|
17
|
+
|
18
18
|
# Manual input format settings for the station
|
19
19
|
attr_accessor :station_input_formats
|
20
|
-
|
20
|
+
|
21
21
|
# Jury worker settings for the Tournament Station
|
22
22
|
attr_accessor :jury_worker
|
23
|
-
|
23
|
+
|
24
24
|
# Auto Judge settings for the Tournament Station
|
25
25
|
attr_accessor :auto_judge
|
26
|
-
|
26
|
+
|
27
27
|
# Contains Error Message if any
|
28
28
|
attr_accessor :errors
|
29
|
-
|
29
|
+
|
30
30
|
# batch_size attribute, required for specifing size of batch
|
31
31
|
attr_accessor :batch_size
|
32
32
|
|
@@ -37,6 +37,7 @@ module CF
|
|
37
37
|
# line.stations station
|
38
38
|
def initialize(options={})
|
39
39
|
@input_formats =[]
|
40
|
+
@badges = []
|
40
41
|
@line_title = options[:line].nil? ? nil : options[:line].title
|
41
42
|
@type = options[:type].nil? ? nil : options[:type].camelize
|
42
43
|
@jury_worker = options[:jury_worker]
|
@@ -44,29 +45,30 @@ module CF
|
|
44
45
|
@station_input_formats = options[:input_formats]
|
45
46
|
@line_instance = options[:line]
|
46
47
|
@batch_size = options[:batch_size]
|
48
|
+
@gold_standards = []
|
47
49
|
@acceptance_ratio = options[:acceptance_ratio]
|
48
50
|
if @batch_size.nil?
|
49
|
-
request_general =
|
51
|
+
request_general =
|
50
52
|
{
|
51
|
-
:body =>
|
53
|
+
:body =>
|
52
54
|
{
|
53
55
|
:api_key => CF.api_key,
|
54
56
|
:station => {:type => @type, :input_formats => @station_input_formats}
|
55
57
|
}
|
56
58
|
}
|
57
59
|
if @acceptance_ratio.nil?
|
58
|
-
request_tournament =
|
60
|
+
request_tournament =
|
59
61
|
{
|
60
|
-
:body =>
|
62
|
+
:body =>
|
61
63
|
{
|
62
64
|
:api_key => CF.api_key,
|
63
65
|
:station => {:type => @type, :jury_worker => @jury_worker, :auto_judge => @auto_judge, :input_formats => @station_input_formats}
|
64
66
|
}
|
65
67
|
}
|
66
68
|
else
|
67
|
-
request_tournament =
|
69
|
+
request_tournament =
|
68
70
|
{
|
69
|
-
:body =>
|
71
|
+
:body =>
|
70
72
|
{
|
71
73
|
:api_key => CF.api_key,
|
72
74
|
:station => {:type => @type, :jury_worker => @jury_worker, :auto_judge => @auto_judge, :input_formats => @station_input_formats, :acceptance_ratio => @acceptance_ratio}
|
@@ -74,27 +76,27 @@ module CF
|
|
74
76
|
}
|
75
77
|
end
|
76
78
|
else
|
77
|
-
request_general =
|
79
|
+
request_general =
|
78
80
|
{
|
79
|
-
:body =>
|
81
|
+
:body =>
|
80
82
|
{
|
81
83
|
:api_key => CF.api_key,
|
82
84
|
:station => {:type => @type, :input_formats => @station_input_formats, :batch_size => @batch_size}
|
83
85
|
}
|
84
86
|
}
|
85
87
|
if @acceptance_ratio.nil?
|
86
|
-
request_tournament =
|
88
|
+
request_tournament =
|
87
89
|
{
|
88
|
-
:body =>
|
90
|
+
:body =>
|
89
91
|
{
|
90
92
|
:api_key => CF.api_key,
|
91
93
|
:station => {:type => @type, :jury_worker => @jury_worker, :auto_judge => @auto_judge, :input_formats => @station_input_formats, :batch_size => @batch_size}
|
92
94
|
}
|
93
95
|
}
|
94
96
|
else
|
95
|
-
request_tournament =
|
97
|
+
request_tournament =
|
96
98
|
{
|
97
|
-
:body =>
|
99
|
+
:body =>
|
98
100
|
{
|
99
101
|
:api_key => CF.api_key,
|
100
102
|
:station => {:type => @type, :jury_worker => @jury_worker, :auto_judge => @auto_judge, :input_formats => @station_input_formats, :batch_size => @batch_size, :acceptance_ratio => @acceptance_ratio}
|
@@ -172,25 +174,23 @@ module CF
|
|
172
174
|
else
|
173
175
|
number = worker_instance.number
|
174
176
|
reward = worker_instance.reward
|
175
|
-
badge = worker_instance.badge
|
176
177
|
stat_badge = worker_instance.stat_badge
|
177
|
-
if
|
178
|
-
request =
|
178
|
+
if stat_badge.nil?
|
179
|
+
request =
|
179
180
|
{
|
180
|
-
:body =>
|
181
|
+
:body =>
|
181
182
|
{
|
182
183
|
:api_key => CF.api_key,
|
183
184
|
:worker => {:number => number, :reward => reward, :type => "HumanWorker"}
|
184
185
|
}
|
185
186
|
}
|
186
187
|
else
|
187
|
-
request =
|
188
|
+
request =
|
188
189
|
{
|
189
|
-
:body =>
|
190
|
+
:body =>
|
190
191
|
{
|
191
192
|
:api_key => CF.api_key,
|
192
193
|
:worker => {:number => number, :reward => reward, :type => "HumanWorker"},
|
193
|
-
:skill_badge => badge,
|
194
194
|
:stat_badge => stat_badge
|
195
195
|
}
|
196
196
|
}
|
@@ -200,8 +200,7 @@ module CF
|
|
200
200
|
worker.id = resp.parsed_response['id']
|
201
201
|
worker.number = resp.parsed_response['number']
|
202
202
|
worker.reward = resp.parsed_response['reward']
|
203
|
-
worker.stat_badge = resp.parsed_response['stat_badge']
|
204
|
-
worker.skill_badges << resp.parsed_response['skill_badges']
|
203
|
+
worker.stat_badge = resp.parsed_response['stat_badge']
|
205
204
|
if resp.code != 200
|
206
205
|
worker.errors = resp.parsed_response['error']['message']
|
207
206
|
end
|
@@ -264,7 +263,7 @@ module CF
|
|
264
263
|
@html = @form.raw_html
|
265
264
|
@resp = CF::CustomTaskForm.post("/lines/#{CF.account_name}/#{self.line_title.downcase}/stations/#{self.index}/form.json", :form => {:title => @title, :instruction => @instruction, :_type => "CustomTaskForm", :raw_html => @html})
|
266
265
|
else
|
267
|
-
@resp = CF::TaskForm.post("/lines/#{CF.account_name}/#{self.line_title.downcase}/stations/#{self.index}/form.json", :form => {:title => @title, :instruction => @instruction, :_type => type})
|
266
|
+
@resp = CF::TaskForm.post("/lines/#{CF.account_name}/#{self.line_title.downcase}/stations/#{self.index}/form.json", :form => {:title => @title, :instruction => @instruction, :_type => type})
|
268
267
|
end
|
269
268
|
@resp.to_hash.each_pair do |k,v|
|
270
269
|
form.send("#{k}=",v) if form.respond_to?(k)
|
@@ -319,7 +318,7 @@ module CF
|
|
319
318
|
self.errors = resp.error.message if resp.code != 200
|
320
319
|
return resp
|
321
320
|
end
|
322
|
-
|
321
|
+
|
323
322
|
def to_s # :nodoc:
|
324
323
|
if self.type == "TournamentStation"
|
325
324
|
"{:type => #{self.type}, :index => #{self.index}, :line_title => #{self.line_title}, :station_input_formats => #{self.station_input_formats}, :jury_worker => #{self.jury_worker}, auto_judge => #{self.auto_judge}, :errors => #{self.errors}}"
|
@@ -327,5 +326,88 @@ module CF
|
|
327
326
|
"{:type => #{self.type}, :index => #{self.index}, :line_title => #{self.line_title}, :station_input_formats => #{self.station_input_formats}, :errors => #{self.errors}}"
|
328
327
|
end
|
329
328
|
end
|
329
|
+
|
330
|
+
#specify the goldstandards for the station
|
331
|
+
# ===Usage Example:
|
332
|
+
# CF::GoldStandard.new({ :station => station,:name => "easy",:input => [{'image_url' =>"http://onwired.com/images/portfolio/linda-stanley-business-card.jpg"}],:expected_output => [{"first_name" => {"value" => "John"}, "last_name" => {"value" => "Lennon"}, "company" => {"value" => "Sprout"}}]})
|
333
|
+
def gold_standards gold_standard = nil
|
334
|
+
if gold_standard
|
335
|
+
station = self
|
336
|
+
gold_standard_options = gold_standard.settings
|
337
|
+
if !gold_standard_options.nil?
|
338
|
+
if gold_standard_options[:file]
|
339
|
+
if File.exist?(gold_standard_options[:file].to_s)
|
340
|
+
file_upload = File.new(gold_standard_options[:file], 'rb')
|
341
|
+
resp = self.class.post("/lines/#{CF.account_name}/#{line.title.downcase}/gold_standards.json", {:file => file_upload})
|
342
|
+
gold_standard = CF::GoldStandard.new()
|
343
|
+
resp.each do |gs|
|
344
|
+
gold_standard.settings.merge!(gs.to_hash)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
else
|
348
|
+
request =
|
349
|
+
{
|
350
|
+
:body =>
|
351
|
+
{
|
352
|
+
:api_key => CF.api_key,
|
353
|
+
:gold_standard => gold_standard_options
|
354
|
+
}
|
355
|
+
}
|
356
|
+
resp = HTTParty.post("#{CF.api_url}#{CF.api_version}/lines/#{CF.account_name}/#{line.title.downcase}/stations/#{station.index.to_i}/gold_standards.json",request)
|
357
|
+
gold_standard = CF::GoldStandard.new()
|
358
|
+
resp.parsed_response.first.delete("id")
|
359
|
+
gold_standard.settings.merge!(resp.parsed_response.first.symbolize_keys)
|
360
|
+
self.errors = resp.parsed_response['error']['message'] if resp.code != 200
|
361
|
+
end
|
362
|
+
@gold_standards << gold_standard
|
363
|
+
end
|
364
|
+
else
|
365
|
+
@gold_standards
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
369
|
+
def gold_standards=(gold_standard) # :nodoc:
|
370
|
+
@gold_standards << gold_standard
|
371
|
+
end
|
372
|
+
|
373
|
+
#specify the badges for the station
|
374
|
+
# ===Usage Example:
|
375
|
+
# CF::Badge.new({:line => line, :station => s,:name => "Tomb Digitizer", :description => "This badge qualifies you to work on tomb digitization tasks.",:max_badges => 100,:gold_standards => ["#{@gold_standard.settings[:name]}"],:test_attributes =>{:type => "default",:retries => 10,:pass_percentage => 100,:check_manually => true}})
|
376
|
+
def badges badge = nil
|
377
|
+
line_title = line["title"] || line.title
|
378
|
+
if badge
|
379
|
+
if badge.settings[:test_attributes][:form_attributes].present?
|
380
|
+
form = badge.settings[:test_attributes][:form_attributes]
|
381
|
+
if( form[:type] == "CustomTaskForm" && form[:file])
|
382
|
+
raw_html = ""
|
383
|
+
File.open("#{form[:file]}").each_line do |line|
|
384
|
+
raw_html += line
|
385
|
+
end
|
386
|
+
badge.settings[:test_attributes][:form_attributes].merge!({:raw_html => raw_html,:_type =>"CustomTaskForm"})
|
387
|
+
end
|
388
|
+
badge.settings[:test_attributes][:form_attributes].merge!({:_type =>"TaskForm"}) if form[:type] == "TaskForm"
|
389
|
+
end
|
390
|
+
request =
|
391
|
+
{
|
392
|
+
:body =>
|
393
|
+
{
|
394
|
+
:api_key => CF.api_key,
|
395
|
+
:badge => badge.settings
|
396
|
+
}
|
397
|
+
}
|
398
|
+
resp = HTTParty.post("#{CF.api_url}#{CF.api_version}/lines/#{CF.account_name}/#{line_title.downcase}/stations/#{self.index}/badges.json",request)
|
399
|
+
badge = CF::Badge.new()
|
400
|
+
badge.settings.merge!(resp.to_hash)
|
401
|
+
self.errors = resp.parsed_response['error']['message'] if resp.code != 200
|
402
|
+
@badges << badge
|
403
|
+
else
|
404
|
+
@badges
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
def badges=(badge)
|
409
|
+
@badges << badge
|
410
|
+
end
|
411
|
+
|
330
412
|
end
|
331
413
|
end
|
data/lib/cf/test_run.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
module CF
|
2
|
+
class TestRun
|
3
|
+
require 'httparty'
|
4
|
+
include Client
|
5
|
+
|
6
|
+
# Title of the "run" object
|
7
|
+
attr_accessor :title
|
8
|
+
|
9
|
+
# Input to be passed for Production Run
|
10
|
+
attr_accessor :gold_standard_inputs
|
11
|
+
|
12
|
+
# Line attribute with which run is associated
|
13
|
+
attr_accessor :line
|
14
|
+
|
15
|
+
# Contains Error Message if any
|
16
|
+
attr_accessor :errors
|
17
|
+
|
18
|
+
# ==Initializes a new Run
|
19
|
+
# ===Usage Example:
|
20
|
+
#
|
21
|
+
# run = CF::Run.new("line_title", "run name", file_path)
|
22
|
+
#
|
23
|
+
# ==OR
|
24
|
+
# You can pass line object instead of passing line title:
|
25
|
+
# run = CF::Run.new(line_object, "run name", file_path)
|
26
|
+
def initialize(line, title, gold_standards_number)
|
27
|
+
@gold_standards_number = gold_standards_number # a number that denotes how many goldstandard form line should be included to create units
|
28
|
+
if line.class == CF::Line || line.class == Hashie::Mash
|
29
|
+
@line = line
|
30
|
+
@line_title = line.title
|
31
|
+
elsif line.class == String
|
32
|
+
if line.split("/").count == 2
|
33
|
+
@account = line.split("/").first
|
34
|
+
@line_title = line.split("/").last
|
35
|
+
elsif line.split("/").count == 1
|
36
|
+
@line_title = line
|
37
|
+
end
|
38
|
+
end
|
39
|
+
@title = title
|
40
|
+
if gold_standards_number
|
41
|
+
options =
|
42
|
+
{
|
43
|
+
:body =>
|
44
|
+
{
|
45
|
+
:api_key => CF.api_key,
|
46
|
+
:data =>{:run => { :title => @title ,:test =>"true"}, :gold_standard_inputs => @gold_standards_number}
|
47
|
+
}
|
48
|
+
}
|
49
|
+
if line.class == String && line.split("/").count == 2
|
50
|
+
run = HTTParty.post("#{CF.api_url}#{CF.api_version}/lines/#{@account}/#{@line_title.downcase}/runs.json",options)
|
51
|
+
else
|
52
|
+
run = HTTParty.post("#{CF.api_url}#{CF.api_version}/lines/#{CF.account_name}/#{@line_title.downcase}/runs.json",options)
|
53
|
+
end
|
54
|
+
if run.code != 200
|
55
|
+
self.errors = run.parsed_response['error']['message']
|
56
|
+
end
|
57
|
+
else
|
58
|
+
self.errors = "Number of GoldStandards to be used is not provided"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.create(line, title, input_number)
|
63
|
+
TestRun.new(line, title, input_number)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/lib/cf/version.rb
CHANGED