papercall 0.13.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: fd0a857b50d9ee99575ffa9448af55f9bd5f625e
4
- data.tar.gz: 8737113738cf9fcf63f6f0839257d2f6322a7e2c
2
+ SHA256:
3
+ metadata.gz: c01ac69e7a39cce23602d48764e3973e8dfe4df1b6b9c78c49ef139a90a84ae8
4
+ data.tar.gz: 1a860bcc822007737378bab9f97877acc07e443188b3f2ee345e77e1b84a46b2
5
5
  SHA512:
6
- metadata.gz: 6d9b97722e818baf0d5672b0d1f70036f1c0abe3ffde28dd2ec2792d203a3b292524bd11bf3b74d1ada3b1ee8b29f074b02bb35aa11df2287d15e395898218c8
7
- data.tar.gz: 65e1a23e97123bb37c7dc533b93bb0c6f9b04be850561bcf2197ca7b0b82c059f267d46f39c766e8406224dce7bc21b597be20a3f3eb28f6fc341b916a13826d
6
+ metadata.gz: 6ba6af36d0f36b604069bbb4012dc5a33177fb2dfe1e2a530ef824395a82967c7285f5349c28d0844133d5aadd7d330b9ce48ed6327e5f317fedaa201bf9b92b
7
+ data.tar.gz: 04d62a8dc0acee34c079920467623276a16d60c6d8976dab00887bf7ef1805dd0fdee55c41372510ce1ef5208155e8c7d86cbaeaafcbd27c248b36ffc9c57fa7
data/.gitignore CHANGED
@@ -10,3 +10,5 @@
10
10
  /*.json
11
11
  /*.rb
12
12
  /*.gem
13
+ /*.idea
14
+ /*.txt
@@ -55,7 +55,7 @@ further defined and clarified by project maintainers.
55
55
  ## Enforcement
56
56
 
57
57
  Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
- reported by contacting the project team at joe@statoil.com. All
58
+ reported by contacting the project team at joe@equinor.com. All
59
59
  complaints will be reviewed and investigated and will result in a response that
60
60
  is deemed necessary and appropriate to the circumstances. The project team is
61
61
  obligated to maintain confidentiality with regard to the reporter of an incident.
data/Guardfile CHANGED
@@ -39,32 +39,8 @@ guard :rspec, cmd: 'bundle exec rspec' do
39
39
  # Ruby files
40
40
  ruby = dsl.ruby
41
41
  dsl.watch_spec_files_for(ruby.lib_files)
42
+ #watch(/^lib\/(.+)\.rb$/) { | m | "spec/#{m[1]}_test.rb" }
43
+ #watch(/^lib\/papercall\/(.+)\.rb$/) { | m | "spec/#{m[1]}_test.rb" }
44
+ #watch(/^lib\/papercall\/models\/(.+)\.rb$/) { | m | "spec/#{m[1]}_test.rb" }
42
45
 
43
- # Rails files
44
- rails = dsl.rails(view_extensions: %w(erb haml slim))
45
- dsl.watch_spec_files_for(rails.app_files)
46
- dsl.watch_spec_files_for(rails.views)
47
-
48
- watch(rails.controllers) do |m|
49
- [
50
- rspec.spec.call("routing/#{m[1]}_routing"),
51
- rspec.spec.call("controllers/#{m[1]}_controller"),
52
- rspec.spec.call("acceptance/#{m[1]}")
53
- ]
54
- end
55
-
56
- # Rails config changes
57
- watch(rails.spec_helper) { rspec.spec_dir }
58
- watch(rails.routes) { "#{rspec.spec_dir}/routing" }
59
- watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }
60
-
61
- # Capybara features specs
62
- watch(rails.view_dirs) { |m| rspec.spec.call("features/#{m[1]}") }
63
- watch(rails.layouts) { |m| rspec.spec.call("features/#{m[1]}") }
64
-
65
- # Turnip features and steps
66
- watch(%r{^spec/acceptance/(.+)\.feature$})
67
- watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m|
68
- Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance'
69
- end
70
46
  end
data/README.md CHANGED
@@ -31,26 +31,54 @@ The following code will fetch all the submissions from your event and print a su
31
31
  ```ruby
32
32
  require 'papercall'
33
33
 
34
- Papercall.fetch(:from_papercall, "<your api key>", :submitted, :accepted, :rejected, :waitlist, :declined)
34
+ Papercall.configure do |config|
35
+ config.API_KEY = "<your api key>"
36
+ end
37
+ Papercall.fetch(:from_papercall, :submitted, :accepted, :rejected, :waitlist, :declined)
35
38
  Papercall.summary
36
39
  ```
37
40
 
38
41
  The Papercall gem also allows you to fetch individual states, or just the ones you care about:
39
42
 
40
43
  ```ruby
41
- Papercall.fetch(:from_papercall, "<your api key", :submitted, :accepted)
44
+ Papercall.configure do |config|
45
+ config.API_KEY = "<your api key>"
46
+ end
47
+ Papercall.fetch(:from_papercall, :submitted, :accepted)
42
48
  ```
43
49
  or
44
50
  ```ruby
45
- Papercall.fetch(:from_papercall, "<your api key", :rejected, :declined, :waitelist)
51
+ Papercall.configure do |config|
52
+ config.API_KEY = "<your api key>"
53
+ end
54
+ Papercall.fetch(:from_papercall, :rejected, :declined, :waitelist)
46
55
  ```
47
56
  The order does not matter.
48
57
 
49
58
  You can also use this shortcut if you want to fetch all:
50
59
  ```ruby
51
- Papercall.fetch(:from_papercall, "<your api key", :all)
60
+ Papercall.configure do |config|
61
+ config.API_KEY = "<your api key>"
62
+ end
63
+ Papercall.fetch(:from_papercall, :all)
52
64
  ```
53
65
 
66
+ ## Other configuration options
67
+ You can configure the following attributes:
68
+ * API key
69
+ * Turning output on or off (default is on)
70
+ * Input file - used for reading from submissions from file (default: submissions.json)
71
+ * Number of threads - number of parallel threads used to fetch ratings and feedback (default 150)
72
+
73
+ Example:
74
+ ```ruby
75
+ Papercall.configure do |config|
76
+ config.API_KEY = "<your api key>"
77
+ config.output = false
78
+ config.threads = 200
79
+ config.input_file = "my_subscription.txt"
80
+ end
81
+ ```
54
82
 
55
83
  ## Development
56
84
 
File without changes
data/bin/setup CHANGED
File without changes
@@ -1,6 +1,7 @@
1
1
  require 'papercall/version'
2
2
  require 'papercall/core'
3
3
  require 'papercall/fetcher'
4
+ require 'papercall/configuration'
4
5
  require 'papercall/file_fetcher'
5
6
  require 'papercall/rest_fetcher'
6
7
  require 'papercall/analysis'
@@ -1,101 +1,142 @@
1
1
  module Papercall
2
2
  class Analysis
3
+ attr_reader :submissions,
4
+ :reviewers,
5
+ :talks_without_reviews,
6
+ :talks_missing_reviews,
7
+ :talks_with_many_reviews,
8
+ :talks_without_feedback,
9
+ :highly_rated,
10
+ :low_rated,
11
+ :maybe,
12
+ :accepted,
13
+ :waitlisted,
14
+ :rejected,
15
+ :confirmed,
16
+ :summary
17
+
3
18
  def initialize submissions
4
- @analysis = {}
5
- @analysis['submissions'] = submissions
6
- @analysis['reviewers'] = {}
7
- @analysis['talksWithoutReviews'] = []
8
- @analysis['talksWithLessThanThreeReviews'] = []
9
- @analysis['talksWithFourOrMoreReviews'] = []
10
- @analysis['talksWithoutFeedback'] = []
11
- @analysis['highlyRated'] = []
12
- @analysis['lowRated'] = []
13
- @analysis['maybe'] = []
14
- @analysis['accepted'] = []
15
- @analysis['waitlist'] = []
16
- @analysis['rejected'] = []
17
- @analysis['confirmed'] = []
19
+ @output = Papercall.configuration.output
20
+ @submissions = submissions
21
+ @reviewers = {}
22
+ @talks_without_reviews = []
23
+ @talks_missing_reviews = []
24
+ @talks_with_many_reviews = []
25
+ @talks_without_feedback = []
26
+ @highly_rated = []
27
+ @low_rated = []
28
+ @maybe = []
29
+ @accepted = []
30
+ @waitlisted = []
31
+ @rejected = []
32
+ @confirmed = []
33
+ analyze
18
34
  end
19
35
 
20
- def analyze
21
- startTime = Time.now
22
- print "Performing analysis..."
23
- @analysis['submissions'].each do |submission|
24
- submission["ratings"].each do |rating|
25
- unless(@analysis['reviewers'].include?(rating["user"]["name"]))
26
- @analysis['reviewers'][rating["user"]["name"]] = [{:id => rating["submission_id"]}]
27
- else
28
- @analysis['reviewers'][rating['user']['name']] << {:id => rating["submission_id"]}
29
- end
30
- end
31
- @analysis['talksWithoutReviews'] << {:id => submission["id"]} if submission["ratings"].empty?
32
- @analysis['talksWithFourOrMoreReviews'] << {:id => submission["id"]} if submission["ratings"].size >= 4
33
- @analysis['talksWithLessThanThreeReviews'] << {:id => submission["id"]} if submission["ratings"].size < 3
34
- @analysis['talksWithoutFeedback'] << {:id => submission["id"]} if submission["feedback"].empty?
35
- @analysis['highlyRated'] << {:id => submission["id"], :submission => submission} if highlyRated? submission
36
- @analysis['lowRated'] << {:id => submission["id"], :submission => submission} if lowRated? submission
37
- @analysis['maybe'] << {:id => submission["id"], :submission => submission} if maybe? submission
38
- @analysis['accepted'] << {:id => submission["id"], :submission => submission} if accepted? submission
39
- @analysis['waitlist'] << {:id => submission["id"], :submission => submission} if waitlisted? submission
40
- @analysis['rejected'] << {:id => submission["id"], :submission => submission} if rejected? submission
41
- @analysis['confirmed'] << {:id => submission["id"], :submission => submission} if confirmed? submission
42
- end
43
- @analysis['summary'] = summary
44
- puts "finished in #{Time.now - startTime} seconds."
45
- @analysis
36
+ def number_of_submissions
37
+ @submissions.size
46
38
  end
47
39
 
48
- private
40
+ def number_of_active_reviewers
41
+ @reviewers.size
42
+ end
43
+
44
+ def number_without_feedback
45
+ @talks_without_feedback.size
46
+ end
47
+
48
+ def number_completed
49
+ @submissions.size - @talks_missing_reviews.size
50
+ end
51
+
52
+ def number_of_highly_rated
53
+ @highly_rated.size
54
+ end
49
55
 
50
- def highlyRated?(submission)
51
- submission["rating"] >= 75 && review_complete?(submission)
56
+ def number_of_low_rated
57
+ @low_rated.size
52
58
  end
53
59
 
54
- def lowRated?(submission)
55
- submission["rating"] <= 25 && review_complete?(submission)
60
+ def number_of_maybes
61
+ @maybe.size
56
62
  end
57
63
 
58
- def maybe?(submission)
59
- !accepted?(submission) && !rejected?(submission) && review_complete?(submission)
64
+ def number_with_few_reviews
65
+ @talks_missing_reviews.size
60
66
  end
61
67
 
62
- def review_complete?(submission)
63
- submission["ratings"].size >= 3
68
+ def number_with_many_reviews
69
+ @talks_with_many_reviews.size
64
70
  end
65
71
 
66
- def accepted?(submission)
67
- submission["state"] == "accepted"
72
+ def number_without_reviews
73
+ @talks_without_reviews.size
68
74
  end
69
75
 
70
- def rejected?(submission)
71
- submission["state"] == "rejected"
76
+ def number_accepted
77
+ @accepted.size
72
78
  end
73
79
 
74
- def waitlisted?(submission)
75
- submission["state"] == "waitlist"
80
+ def number_of_waitlisted
81
+ @waitlisted.size
76
82
  end
77
83
 
78
- def confirmed?(submission)
79
- accepted?(submission) && submission["confirmed"] == true
84
+ def number_rejected
85
+ @rejected.size
80
86
  end
81
87
 
82
- def summary
88
+ def number_confirmed
89
+ @confirmed.size
90
+ end
91
+
92
+
93
+ private
94
+
95
+ def analyze
96
+ start_time = Time.now
97
+ print 'Performing analysis...' if @output
98
+ @submissions.each do |submission|
99
+ submission.ratings.each do |rating|
100
+ if !(@reviewers.include? rating.user.name)
101
+ @reviewers[rating.user.name] = [{ id: rating.submission_id }]
102
+ else
103
+ @reviewers[rating.user.name] << { id: rating.submission_id }
104
+ end
105
+ end
106
+ @talks_without_reviews << { id: submission.id, submission: submission } if submission.no_reviews?
107
+ @talks_with_many_reviews << { id: submission.id, submission: submission } if submission.too_many_reviews?
108
+ @talks_missing_reviews << {id: submission.id, submission: submission} unless submission.enough_reviews?
109
+ @talks_without_feedback << { id: submission.id, submission: submission } if submission.no_feedback?
110
+ @highly_rated << { id: submission.id, submission: submission } if submission.highly_rated?
111
+ @low_rated << { id: submission.id, submission: submission } if submission.low_rated?
112
+ @maybe << { id: submission.id, submission: submission } if submission.maybe?
113
+ @accepted << { id: submission.id, submission: submission } if submission.accepted?
114
+ @waitlisted << { id: submission.id, submission: submission } if submission.waitlisted?
115
+ @rejected << { id: submission.id, submission: submission } if submission.rejected?
116
+ @confirmed << { id: submission.id, submission: submission } if submission.confirmed?
117
+ end
118
+ @summary = build_summary
119
+ puts "finished in #{Time.now - start_time} seconds." if @output
120
+ end
121
+
122
+ def build_summary
83
123
  summary = {}
84
- summary['numSubmissions'] = @analysis['submissions'].size
85
- summary['numActiveReviewers'] = @analysis['reviewers'].size
86
- summary['numWithoutFeedback'] = @analysis['talksWithoutFeedback'].size
87
- summary['numCompleted'] = @analysis['submissions'].size - @analysis['talksWithLessThanThreeReviews'].size
88
- summary['numHighlyRated'] = @analysis['highlyRated'].size
89
- summary['numLowRated'] = @analysis['lowRated'].size
90
- summary['numMaybe'] = @analysis['maybe'].size
91
- summary['numLessThanThreeReviews'] = @analysis['talksWithLessThanThreeReviews'].size
92
- summary['numWithFourOrMoreReviews'] = @analysis['talksWithFourOrMoreReviews'].size
93
- summary['numWithoutReviews'] = @analysis['talksWithoutReviews'].size
94
- summary['numAccepted'] = @analysis['accepted'].size
95
- summary['numWaitlisted'] = @analysis['waitlist'].size
96
- summary['numRejected'] = @analysis['rejected'].size
97
- summary['numConfirmed'] = @analysis['confirmed'].size
124
+ summary['numSubmissions'] = @submissions.size
125
+ summary['numActiveReviewers'] = @reviewers.size
126
+ summary['numWithoutFeedback'] = @talks_without_feedback.size
127
+ summary['numCompleted'] = @submissions.size - @talks_missing_reviews.size
128
+ summary['numHighlyRated'] = @highly_rated.size
129
+ summary['numLowRated'] = @low_rated.size
130
+ summary['numMaybe'] = @maybe.size
131
+ summary['numLessThanThreeReviews'] = @talks_missing_reviews.size
132
+ summary['numWithFourOrMoreReviews'] = @talks_with_many_reviews.size
133
+ summary['numWithoutReviews'] = @talks_without_reviews.size
134
+ summary['numAccepted'] = @accepted.size
135
+ summary['numWaitlisted'] = @waitlisted.size
136
+ summary['numRejected'] = @rejected.size
137
+ summary['numConfirmed'] = @confirmed.size
98
138
  summary
99
139
  end
140
+
100
141
  end
101
142
  end
@@ -0,0 +1,11 @@
1
+ module Papercall
2
+ class Configuration
3
+ attr_accessor :API_KEY, :input_file, :threads, :output
4
+
5
+ def initialize
6
+ @input_file = 'submissions.json'
7
+ @threads = 150
8
+ @output = true
9
+ end
10
+ end
11
+ end
@@ -2,16 +2,27 @@
2
2
  # Also providing some analytics
3
3
  module Papercall
4
4
  METHOD_REGEX = /(.*)_talks$/
5
+ class << self
6
+ attr_writer :configuration
7
+ end
8
+
9
+ def self.configuration
10
+ @configuration ||= Configuration.new
11
+ end
5
12
 
6
- def self.fetch(from, api_key='', *states)
13
+ def self.configure
14
+ yield(configuration)
15
+ end
16
+
17
+ def self.fetch(from, *states)
7
18
  if from == :from_file
8
- @submissions = Papercall::FileFetcher.new('submissions.json')
19
+ @submissions = Papercall::FileFetcher.new
9
20
  elsif from == :from_papercall
10
- @submissions = Papercall::RestFetcher.new(api_key)
21
+ @submissions = Papercall::RestFetcher.new
11
22
  end
12
23
  @submissions.fetch(states)
24
+ #puts @submissions.analysis
13
25
  @analysis = Papercall::Analysis.new(@submissions.analysis)
14
- @analysis = @analysis.analyze
15
26
  end
16
27
 
17
28
  def self.all
@@ -20,7 +31,7 @@ module Papercall
20
31
 
21
32
  def self.save_to_file(filename)
22
33
  ff = File.open(filename, 'w') { |f| f.write(@submissions.all.to_json) }
23
- puts "All submissions written to file #{filename}." if ff
34
+ puts "All submissions written to file #{filename}." if ff && configuration.output
24
35
  end
25
36
 
26
37
  def self.number_of_submissions
@@ -29,20 +40,20 @@ module Papercall
29
40
 
30
41
  def self.confirmed_talks
31
42
  @submissions.accepted.select do |s|
32
- s['confirmed'] == true
43
+ s.confirmed?
33
44
  end
34
45
  end
35
46
 
36
47
  def self.active_reviewers
37
- @analysis['reviewers']
48
+ @analysis.reviewers
38
49
  end
39
50
 
40
51
  def self.submissions_without_feedback
41
- @analysis['talksWithoutFeedback']
52
+ @analysis.talks_without_feedback
42
53
  end
43
54
 
44
55
  def self.submissions_with_enough_reviews
45
- @analysis['talksWithLessThanThreeReviews']
56
+ @analysis.submissions - @analysis.talks_missing_reviews
46
57
  end
47
58
 
48
59
  def self.analysis
@@ -50,22 +61,24 @@ module Papercall
50
61
  end
51
62
 
52
63
  def self.summary
53
- s = @analysis['summary']
54
- puts "Number of submissions: #{s['numSubmissions']}"
55
- puts "Number of active reviewers: #{s['numActiveReviewers']}"
56
- puts "Number of submitted talks without feedback: #{s['numWithoutFeedback']}"
57
- puts "Number of talks with three or more reviews: #{s['numCompleted']}"
58
- puts "Number of highly rated talks: #{s['numHighlyRated']}"
59
- puts "Number of low rated talks: #{s['numLowRated']}"
60
- puts "Number of middle rated talks: #{s['numMaybe']}"
61
- puts "Number of talks with less than three reviews: #{s['numLessThanThreeReviews']}"
62
- puts "Number of talks with four or more reviews: #{s['numWithFourOrMoreReviews']}"
63
- puts "Number of talks without reviews: #{s['numWithoutReviews']}"
64
- puts "Number of accepted talks: #{s['numAccepted']}"
65
- puts "Number of waitlisted talks: #{s['numWaitlisted']}"
66
- puts "Number of rejected talks: #{s['numRejected']}"
67
- puts "Number of confirmed talks: #{s['numConfirmed']}"
68
- s
64
+ a = @analysis
65
+ if configuration.output
66
+ puts "Number of submissions: #{a.number_of_submissions}"
67
+ puts "Number of active reviewers: #{a.number_of_active_reviewers}"
68
+ puts "Number of submitted talks without feedback: #{a.number_without_feedback}"
69
+ puts "Number of talks with three or more reviews: #{a.number_completed}"
70
+ puts "Number of highly rated talks: #{a.number_of_highly_rated}"
71
+ puts "Number of low rated talks: #{a.number_of_low_rated}"
72
+ puts "Number of middle rated talks: #{a.number_of_maybes}"
73
+ puts "Number of talks with less than three reviews: #{a.number_with_few_reviews}"
74
+ puts "Number of talks with four or more reviews: #{a.number_with_many_reviews}"
75
+ puts "Number of talks without reviews: #{a.number_without_reviews}"
76
+ puts "Number of accepted talks: #{a.number_accepted}"
77
+ puts "Number of waitlisted talks: #{a.number_of_waitlisted}"
78
+ puts "Number of rejected talks: #{a.number_rejected}"
79
+ puts "Number of confirmed talks: #{a.number_confirmed}"
80
+ end
81
+ a
69
82
  end
70
83
 
71
84
  def self.respond_to_missing?(method_name, _include_private = false)
@@ -1,12 +1,15 @@
1
1
  require 'json'
2
+ require 'papercall/models/submission'
3
+ require 'active_support/core_ext/hash/indifferent_access'
2
4
 
3
5
  module Papercall
4
6
  # Fetches submissions from file.
5
7
  # Params:
6
8
  # +filename+:: File with submissions. JSON format.
7
9
  class FileFetcher < Fetcher
8
- def initialize(filename)
9
- @filename = filename
10
+ def initialize()
11
+ @output = Papercall.configuration.output
12
+ @filename = Papercall.configuration.input_file
10
13
  @submitted = []
11
14
  @accepted = []
12
15
  @rejected = []
@@ -16,12 +19,12 @@ module Papercall
16
19
 
17
20
  def fetch(_)
18
21
  file = File.new(@filename, 'r')
19
- puts "Reading from file (#{file.path})..."
20
- submissions = JSON.parse file.read if file
21
- @submitted = submissions['submitted']
22
- @accepted = submissions['accepted']
23
- @rejected = submissions['rejected']
24
- @waitlist = submissions['waitlist']
22
+ puts 'Reading from file (#{file.path})...' if @output
23
+ submissions = JSON.parse(file.read).with_indifferent_access if file
24
+ @submitted = submissions[:submitted].map {|s| Submission.new(s)}
25
+ @accepted = submissions[:accepted].map {|s| Submission.new(s)}
26
+ @rejected = submissions[:rejected].map {|s| Submission.new(s)}
27
+ @waitlist = submissions[:waitlist].map {|s| Submission.new(s)}
25
28
  end
26
29
  end
27
30
  end
@@ -0,0 +1,15 @@
1
+ require_relative 'user'
2
+
3
+ class Feedback
4
+ attr_reader :id, :submission_id, :talk_id, :user, :body, :created_at, :updated_at
5
+
6
+ def initialize(json_hash)
7
+ @id = json_hash[:id]
8
+ @submission_id = json_hash[:submission_id]
9
+ @talk_id = json_hash[:talk_id]
10
+ @user = User.new(json_hash[:user])
11
+ @body = json_hash[:body]
12
+ @created_at = Time.parse(json_hash[:created_at])
13
+ @updated_at = Time.parse(json_hash[:updated_at])
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+
2
+ class PresenterProfile
3
+ attr_reader :name, :bio, :twitter, :company, :url, :shirt_size, :email, :location, :avatar
4
+
5
+ def initialize(json_hash = {})
6
+ @name = json_hash[:name]
7
+ @bio = json_hash[:bio]
8
+ @twitter = json_hash[:twitter]
9
+ @company = json_hash[:company]
10
+ @url = json_hash[:url]
11
+ @shirt_size = json_hash[:shirt_size]
12
+ @email = json_hash[:email]
13
+ @location = json_hash[:location]
14
+ @avatar = json_hash[:avatar]
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ require_relative 'user'
2
+
3
+ class Rating
4
+ attr_reader :id, :submission_id, :value, :comments, :created_at, :updated_at, :user
5
+
6
+ def initialize(json_hash)
7
+ @id = json_hash[:id]
8
+ @submission_id = json_hash[:submission_id]
9
+ @value = json_hash[:value]
10
+ @comments = json_hash[:comments]
11
+ @created_at = Time.parse(json_hash[:created_at])
12
+ @updated_at = Time.parse(json_hash[:updated_at])
13
+ @user = User.new(json_hash[:user])
14
+ end
15
+ end
@@ -0,0 +1,78 @@
1
+ require_relative 'presenter_profile'
2
+ require_relative 'talk'
3
+
4
+ class Submission
5
+ attr_reader :id, :state, :confirmed, :created_at, :updated_at, :additional_info, :rating, :trust, :tags,
6
+ :co_presenter_profiles, :presenter_profile, :talk, :cfp_additional_answers
7
+ attr_accessor :ratings, :feedback
8
+
9
+ def initialize(json_hash)
10
+ @id = json_hash[:id]
11
+ @state = json_hash[:state]
12
+ @confirmed = json_hash[:confirmed]
13
+ @created_at = Time.parse(json_hash[:created_at])
14
+ @updated_at = Time.parse(json_hash[:updated_at])
15
+ @additional_info = json_hash[:additional_info]
16
+ @rating = json_hash[:rating]
17
+ @trust = json_hash[:trust]
18
+ @tags = json_hash[:tags]
19
+ @co_presenter_profiles = json_hash[:co_presenter_profiles]
20
+ @presenter_profile = PresenterProfile.new(json_hash[:profile])
21
+ @talk = Talk.new(json_hash[:talk])
22
+ @cfp_additional_answers = json_hash[:cfp_additional_question_answers]
23
+ @ratings = []
24
+ @feedback = []
25
+ end
26
+
27
+ def no_reviews?
28
+ @ratings.empty?
29
+ end
30
+
31
+ def enough_reviews?
32
+ @ratings.size >= 3
33
+ end
34
+
35
+ def too_many_reviews?
36
+ @ratings.size >= 4
37
+ end
38
+
39
+ def highly_rated?
40
+ @rating >= 75 && enough_reviews?
41
+ end
42
+
43
+ def low_rated?
44
+ @rating <= 25 && enough_reviews?
45
+ end
46
+
47
+ def maybe?
48
+ !accepted? && !rejected? && enough_reviews?
49
+ end
50
+
51
+ def accepted?
52
+ @state == 'accepted'
53
+ end
54
+
55
+ def rejected?
56
+ @state == 'rejected'
57
+ end
58
+
59
+ def waitlisted?
60
+ @state == 'waitlist'
61
+ end
62
+
63
+ def confirmed?
64
+ accepted? && @confirmed == true
65
+ end
66
+
67
+ def no_feedback?
68
+ @feedback.empty?
69
+ end
70
+
71
+ def to_s
72
+ puts "Submission: #{@id}, #{@talk.title}, #{@presenter_profile.name}. Number of reviews: #{@ratings.size}. Number of feedback: #{@feedback.size}"
73
+ end
74
+
75
+ def to_json
76
+ this.to_h.to_json
77
+ end
78
+ end
@@ -0,0 +1,13 @@
1
+
2
+ class Talk
3
+ attr_reader :title, :description, :notes, :abstract, :audience_level, :talk_format
4
+
5
+ def initialize(json_hash)
6
+ @title = json_hash[:title]
7
+ @description = json_hash[:description]
8
+ @notes = json_hash[:notes]
9
+ @abstract = json_hash[:abstract]
10
+ @audience_level = json_hash[:audience_level]
11
+ @talk_format = json_hash[:talk_format]
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+
2
+ class User
3
+ attr_reader :name, :avatar, :email
4
+
5
+ def initialize(json_hash)
6
+ @name = json_hash[:name]
7
+ @avatar = json_hash[:avatar]
8
+ @email = json_hash[:email]
9
+ end
10
+ end
@@ -1,13 +1,21 @@
1
1
  require 'json'
2
2
  require 'rest-client'
3
+ require 'parallel'
4
+ require 'active_support/core_ext/hash/indifferent_access'
5
+ require 'papercall/models/submission'
6
+ require 'papercall/models/rating'
7
+ require 'papercall/models/feedback'
3
8
 
4
9
  module Papercall
5
- #Fetches submissions from Papercall REST API
10
+ # Fetches submissions from Papercall REST API
6
11
  # Params:
7
12
  class RestFetcher < Fetcher
8
13
  SUBMISSIONS_URL = 'https://www.papercall.io/api/v1/submissions'.freeze
9
14
 
10
- def initialize(api_key)
15
+ def initialize()
16
+ @output = Papercall.configuration.output
17
+ api_key = Papercall.configuration.API_KEY
18
+ raise ArgumentError, 'Missing API_KEY for access to Papercall. Please refer to documentation for instructions on setting this value.' unless api_key
11
19
  @auth_hash = { Authorization: api_key }
12
20
  @submitted = []
13
21
  @accepted = []
@@ -25,45 +33,54 @@ module Papercall
25
33
  RestClient::Request.execute(method: :get,
26
34
  url: papercall_url,
27
35
  headers: @auth_hash) # :timeout => 120
28
- JSON.parse raw_results
36
+ if raw_results
37
+ JSON.parse(raw_results).map {|r| r.with_indifferent_access}
38
+ else
39
+ []
40
+ end
29
41
  end
30
42
 
31
43
  def fetch(*states)
32
- states = [[:submitted, :accepted, :rejected, :waitlist, :declined]] if states == [[:all]]
44
+ states = [%i[submitted accepted rejected waitlist declined]] if states == [[:all]]
33
45
  states.flatten.each do |state|
34
- if state
35
- startTime = Time.now
36
- print "Fetching #{state} submissions from PaperCall API..."
37
- instance_variable_set("@#{state}", papercall(submission_url(state.to_s)))
38
- puts "finished in #{Time.now - startTime} seconds."
39
- end
46
+ next unless state
47
+ start_time = Time.now
48
+ print "Fetching #{state} submissions from PaperCall API..." if @output
49
+ submissions = papercall(submission_url(state.to_s))
50
+ instance_variable_set("@#{state}_raw", submissions)
51
+ instance_variable_set("@#{state}", submissions.map {|s| Submission.new(s)})
52
+ puts "finished in #{Time.now - start_time} seconds." if @output
40
53
  end
41
54
  fetch_ratings
42
55
  fetch_feedback
43
56
  end
44
57
 
45
58
  def fetch_ratings
46
- startTime = Time.now
47
- print "Fetching ratings for all submissions from Papercall API..."
48
- analysis.each do |submission|
49
- unless submission['ratings']
50
- ratings_url = "#{SUBMISSIONS_URL}/#{submission['id']}/ratings"
51
- submission['ratings'] = papercall(ratings_url)
59
+ start_time = Time.now
60
+ print 'Fetching ratings for all submissions from Papercall API...' if @output
61
+
62
+ Parallel.each(analysis, in_threads: 128) do |submission|
63
+ if submission.ratings.empty?
64
+ ratings_url = "#{SUBMISSIONS_URL}/#{submission.id}/ratings"
65
+ ratings = papercall(ratings_url).map {|r| Rating.new(r)}
66
+ submission.ratings = ratings
52
67
  end
68
+ #submission.ratings = [] unless submission.ratings
53
69
  end
54
- puts "finished in #{Time.now - startTime} seconds."
70
+ puts "finished in #{Time.now - start_time} seconds." if @output
55
71
  end
56
72
 
57
73
  def fetch_feedback
58
- startTime = Time.now
59
- print "Fetching feedback for all submissions from Papercall API..."
60
- analysis.each do |submission|
61
- unless submission['feedback']
62
- feedback_url = "#{SUBMISSIONS_URL}/#{submission['id']}/feedback"
63
- submission['feedback'] = papercall(feedback_url)
74
+ start_time = Time.now
75
+ print 'Fetching feedback for all submissions from Papercall API...' if @output
76
+ Parallel.each(analysis, in_threads: 128) do |submission|
77
+ if submission.feedback.empty?
78
+ feedback_url = "#{SUBMISSIONS_URL}/#{submission.id}/feedback"
79
+ submission.feedback = papercall(feedback_url).map {|f| Feedback.new(f)}
64
80
  end
81
+ #submission.feedback = [] unless submission.feedback
65
82
  end
66
- puts "finished in #{Time.now - startTime} seconds."
83
+ puts "finished in #{Time.now - start_time} seconds." if @output
67
84
  end
68
85
  end
69
86
  end
@@ -1,3 +1,3 @@
1
1
  module Papercall
2
- VERSION = '0.13.0'.freeze
2
+ VERSION = '1.0.0'.freeze
3
3
  end
@@ -21,16 +21,17 @@ Gem::Specification.new do |spec|
21
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
22
  spec.require_paths = ["lib"]
23
23
 
24
- spec.add_development_dependency "bundler", "~> 1.13"
25
- spec.add_development_dependency "rake", "~> 10.0"
26
- spec.add_development_dependency "rspec", "~> 3.0"
27
- spec.add_development_dependency "guard", "~> 2.13"
24
+ spec.add_development_dependency "bundler", "~> 2.1.4"
25
+ spec.add_development_dependency "rake", "~> 13.0.1"
26
+ spec.add_development_dependency "rspec", "~> 3.9.0"
27
+ spec.add_development_dependency "guard", "~> 2.16.2"
28
28
  spec.add_development_dependency "guard-rspec", "~> 4.7", ">= 4.7.3"
29
- spec.add_development_dependency "pry", "~> 0.11.2"
30
- spec.add_development_dependency "rubocop", "~> 0.51.0"
29
+ spec.add_development_dependency "pry", "~> 0.13.1"
30
+ spec.add_development_dependency "rubocop", "~> 0.90.0"
31
31
 
32
- spec.add_dependency "json", "~> 2.1"
33
- spec.add_dependency "rest-client", "~> 2.0", ">= 2.0.2"
34
- spec.add_dependency "activesupport", "~> 5.0"
35
- spec.add_dependency "i18n", "~> 0.9.1"
32
+ spec.add_dependency "json", "~> 2.3.1"
33
+ spec.add_dependency "rest-client", "~> 2.1", ">= 2.1.0"
34
+ spec.add_dependency "activesupport", "~> 6.0"
35
+ spec.add_dependency "i18n", "~> 1.8.5"
36
+ spec.add_dependency "parallel", "~> 1.12.1"
36
37
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: papercall
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jørn Ølmheim
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-01-28 00:00:00.000000000 Z
11
+ date: 2020-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,56 +16,56 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.13'
19
+ version: 2.1.4
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.13'
26
+ version: 2.1.4
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: 13.0.1
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: 13.0.1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '3.0'
47
+ version: 3.9.0
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '3.0'
54
+ version: 3.9.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: guard
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '2.13'
61
+ version: 2.16.2
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '2.13'
68
+ version: 2.16.2
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: guard-rspec
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -92,90 +92,104 @@ dependencies:
92
92
  requirements:
93
93
  - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: 0.11.2
95
+ version: 0.13.1
96
96
  type: :development
97
97
  prerelease: false
98
98
  version_requirements: !ruby/object:Gem::Requirement
99
99
  requirements:
100
100
  - - "~>"
101
101
  - !ruby/object:Gem::Version
102
- version: 0.11.2
102
+ version: 0.13.1
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: rubocop
105
105
  requirement: !ruby/object:Gem::Requirement
106
106
  requirements:
107
107
  - - "~>"
108
108
  - !ruby/object:Gem::Version
109
- version: 0.51.0
109
+ version: 0.90.0
110
110
  type: :development
111
111
  prerelease: false
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - "~>"
115
115
  - !ruby/object:Gem::Version
116
- version: 0.51.0
116
+ version: 0.90.0
117
117
  - !ruby/object:Gem::Dependency
118
118
  name: json
119
119
  requirement: !ruby/object:Gem::Requirement
120
120
  requirements:
121
121
  - - "~>"
122
122
  - !ruby/object:Gem::Version
123
- version: '2.1'
123
+ version: 2.3.1
124
124
  type: :runtime
125
125
  prerelease: false
126
126
  version_requirements: !ruby/object:Gem::Requirement
127
127
  requirements:
128
128
  - - "~>"
129
129
  - !ruby/object:Gem::Version
130
- version: '2.1'
130
+ version: 2.3.1
131
131
  - !ruby/object:Gem::Dependency
132
132
  name: rest-client
133
133
  requirement: !ruby/object:Gem::Requirement
134
134
  requirements:
135
135
  - - "~>"
136
136
  - !ruby/object:Gem::Version
137
- version: '2.0'
137
+ version: '2.1'
138
138
  - - ">="
139
139
  - !ruby/object:Gem::Version
140
- version: 2.0.2
140
+ version: 2.1.0
141
141
  type: :runtime
142
142
  prerelease: false
143
143
  version_requirements: !ruby/object:Gem::Requirement
144
144
  requirements:
145
145
  - - "~>"
146
146
  - !ruby/object:Gem::Version
147
- version: '2.0'
147
+ version: '2.1'
148
148
  - - ">="
149
149
  - !ruby/object:Gem::Version
150
- version: 2.0.2
150
+ version: 2.1.0
151
151
  - !ruby/object:Gem::Dependency
152
152
  name: activesupport
153
153
  requirement: !ruby/object:Gem::Requirement
154
154
  requirements:
155
155
  - - "~>"
156
156
  - !ruby/object:Gem::Version
157
- version: '5.0'
157
+ version: '6.0'
158
158
  type: :runtime
159
159
  prerelease: false
160
160
  version_requirements: !ruby/object:Gem::Requirement
161
161
  requirements:
162
162
  - - "~>"
163
163
  - !ruby/object:Gem::Version
164
- version: '5.0'
164
+ version: '6.0'
165
165
  - !ruby/object:Gem::Dependency
166
166
  name: i18n
167
167
  requirement: !ruby/object:Gem::Requirement
168
168
  requirements:
169
169
  - - "~>"
170
170
  - !ruby/object:Gem::Version
171
- version: 0.9.1
171
+ version: 1.8.5
172
+ type: :runtime
173
+ prerelease: false
174
+ version_requirements: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - "~>"
177
+ - !ruby/object:Gem::Version
178
+ version: 1.8.5
179
+ - !ruby/object:Gem::Dependency
180
+ name: parallel
181
+ requirement: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - "~>"
184
+ - !ruby/object:Gem::Version
185
+ version: 1.12.1
172
186
  type: :runtime
173
187
  prerelease: false
174
188
  version_requirements: !ruby/object:Gem::Requirement
175
189
  requirements:
176
190
  - - "~>"
177
191
  - !ruby/object:Gem::Version
178
- version: 0.9.1
192
+ version: 1.12.1
179
193
  description: Small client library for the PaperCall API. With some analytics for the
180
194
  submissions.
181
195
  email:
@@ -197,9 +211,17 @@ files:
197
211
  - bin/setup
198
212
  - lib/papercall.rb
199
213
  - lib/papercall/analysis.rb
214
+ - lib/papercall/configuration.rb
200
215
  - lib/papercall/core.rb
201
216
  - lib/papercall/fetcher.rb
202
217
  - lib/papercall/file_fetcher.rb
218
+ - lib/papercall/models/feedback.rb
219
+ - lib/papercall/models/presenter_profile.rb
220
+ - lib/papercall/models/presenter_profle.rb
221
+ - lib/papercall/models/rating.rb
222
+ - lib/papercall/models/submission.rb
223
+ - lib/papercall/models/talk.rb
224
+ - lib/papercall/models/user.rb
203
225
  - lib/papercall/rest_fetcher.rb
204
226
  - lib/papercall/version.rb
205
227
  - papercall.gemspec
@@ -224,8 +246,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
224
246
  - !ruby/object:Gem::Version
225
247
  version: '0'
226
248
  requirements: []
227
- rubyforge_project:
228
- rubygems_version: 2.6.12
249
+ rubygems_version: 3.1.2
229
250
  signing_key:
230
251
  specification_version: 4
231
252
  summary: Small client library for the PaperCall API