nora 0.9 → 0.10

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 575265c4cadad14393ba8736a3973ed7704d2e59
4
- data.tar.gz: 97fc379e85cf8793ec121f4d3eccf33f07905ecc
2
+ SHA256:
3
+ metadata.gz: eba54fcfe1ba7880878b3fb8f22a0a357d81ad08d1a037c162526d2989be84d2
4
+ data.tar.gz: 45314bb6328729955beed198f3606584d8275649b2352b835d1c9096b909ff3c
5
5
  SHA512:
6
- metadata.gz: 714cdab8af8e284c2458ff1de4a55035be2f8fce1f80af89d51486364506846bf25eb5cef794051aacb043c79884ca87686be55fbc671d69f133088d3f0c1eb6
7
- data.tar.gz: c1b39413b22b5e18247dc6cf1e2fb69165e6049ff484d4a98a964a901839f6f232179e1256a281f46b72dddf6e57e951a618c506b9aaf1d4f437b846cf594b22
6
+ metadata.gz: 9cf57358ca8f4a5f9a73b9dee65ade7f92627a87617c13a0b8ef1594540baf8ace3f2df01dc3c30104782f80fb3135b68a7cf0b197b129af39794b1cfbade4d3
7
+ data.tar.gz: 57df09cc016e551cc3d0c1b974e2208be62bc147647ba3194faa1086c0c794a978c0dba59209849b4dea929b7cf70fd1543d64a48ff451a6bf828f038022f9ae
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.3.0
1
+ 2.5
data/lib/nora/core.rb CHANGED
@@ -25,6 +25,7 @@ module Nora
25
25
  CREDENTIALS_PATH = "calendar-ruby-quickstart.yaml"
26
26
  SCOPE = Google::Apis::CalendarV3::AUTH_CALENDAR
27
27
 
28
+ CALENDAR_BATCH_SIZE = 250 # The maximum Google Calendar allows
28
29
  FREE_BUSY_QUERY_BATCH_SIZE = 5
29
30
 
30
31
  CONFIGURATION = JSON.parse(File.read("nora_configuration.json"))
@@ -65,13 +66,7 @@ module Nora
65
66
  def run!
66
67
  load_history! # Populate @history for load_calendars!
67
68
  load_calendars! # Outside the loop to reduce calls to Google API.
68
- begin
69
- shuffle_emails!
70
- create_groups!
71
- rescue SystemStackError
72
- remove_oldest_pair!
73
- retry
74
- end
69
+ create_groups!
75
70
 
76
71
  send_emails(
77
72
  template_emails_for(
@@ -92,15 +87,8 @@ module Nora
92
87
  puts "Loading calendars..."
93
88
  @emails = CONFIGURATION["people"].map { |p| p["email"] }
94
89
 
95
- emails_in_history = []
96
- File.open(PAIRINGS_FILE).each do |line|
97
- line.split(PAIRINGS_FILE_SEPARATOR).each do |email|
98
- emails_in_history << email
99
- end
100
- end
101
-
102
90
  # Load all calendars that aren't in our history.
103
- (@emails - emails_in_history).each do |email|
91
+ (Set.new(@emails) - @previously_loaded_emails).each do |email|
104
92
  puts "Loading calendar: #{email}"
105
93
  @service.insert_calendar_list(
106
94
  Google::Apis::CalendarV3::CalendarListEntry.new(id: email)
@@ -109,35 +97,39 @@ module Nora
109
97
  end
110
98
  end
111
99
 
112
- def shuffle_emails!
113
- puts "Shuffling emails..."
114
- @emails = @emails.shuffle
115
- end
116
-
117
- def remove_oldest_pair!
118
- puts "Removing oldest pair and retrying..."
119
- File.open("past_pairings_tmp.txt", "w") do |file|
120
- File.open(PAIRINGS_FILE).each.with_index(1) do |line, line_num|
121
- file.puts(line) unless line_num == 1
122
- end
123
- end
124
- FileUtils.mv("past_pairings_tmp.txt", PAIRINGS_FILE)
125
- end
126
-
127
100
  def load_history!
128
101
  puts "Loading history..."
129
- @history = Set.new
102
+ @past_pairing_counts = Hash.new { |h, k| h[k] = 0 }
103
+ @previously_loaded_emails = Set.new
130
104
  File.open(PAIRINGS_FILE).each do |line|
131
- line.split(PAIRINGS_FILE_SEPARATOR).permutation.each do |emails|
132
- @history << emails
105
+ line.split(PAIRINGS_FILE_SEPARATOR).each do |email|
106
+ @previously_loaded_emails << email
107
+ end.permutation.each do |emails|
108
+ @past_pairing_counts[group_key(emails: emails)] += 1
133
109
  end
134
110
  end
135
111
  end
136
112
 
113
+ def group_key(emails:)
114
+ emails.sort.join(",")
115
+ end
116
+
137
117
  def create_groups!
138
118
  puts "Creating groups..."
139
- @emails.each_slice(group_size).each do |emails|
140
- return create_groups! unless (@history & emails.combination(2)).empty?
119
+ unmatched_emails = Set.new(@emails)
120
+ @groups = []
121
+
122
+ while unmatched_emails.size >= group_size
123
+ @emails.shuffle.combination(group_size).each do |emails|
124
+ next unless emails.all? { |email| unmatched_emails.include?(email) }
125
+ key = group_key(emails: emails)
126
+ if @past_pairing_counts[key].zero?
127
+ @groups << emails
128
+ unmatched_emails.subtract(emails)
129
+ else
130
+ @past_pairing_counts[key] -= 1
131
+ end
132
+ end
141
133
  end
142
134
  end
143
135
 
@@ -148,7 +140,7 @@ module Nora
148
140
 
149
141
  meetings = []
150
142
 
151
- @emails.each_slice(group_size) do |emails|
143
+ @groups.each do |emails|
152
144
  if emails.size < group_size
153
145
  puts "\nNot enough people in group: #{emails}\n"
154
146
  meetings << {
@@ -161,6 +153,14 @@ module Nora
161
153
  next
162
154
  end
163
155
 
156
+ unless @test
157
+ File.open(PAIRINGS_FILE, "a") do |file|
158
+ emails.combination(2) do |email_pair|
159
+ file.puts email_pair.join(PAIRINGS_FILE_SEPARATOR)
160
+ end
161
+ end
162
+ end
163
+
164
164
  time = availability_schedule.select do |_, ids|
165
165
  ids.superset? Set.new(emails)
166
166
  end.keys.sample
@@ -178,14 +178,6 @@ module Nora
178
178
  puts "#{time} => #{emails}"
179
179
  add_meeting(time: time, attendee_ids: emails)
180
180
 
181
- unless @test
182
- File.open(PAIRINGS_FILE, "a") do |file|
183
- emails.combination(2) do |email_pair|
184
- file.puts email_pair.join(PAIRINGS_FILE_SEPARATOR)
185
- end
186
- end
187
- end
188
-
189
181
  meetings << {
190
182
  on: time,
191
183
  who: emails.map do |email|
@@ -342,9 +334,22 @@ module Nora
342
334
  memoize :email_name_map
343
335
 
344
336
  def calendars
345
- @service.list_calendar_lists.items.select do |calendar|
346
- @emails.include? calendar.id
337
+ output = []
338
+ lists = @service.list_calendar_lists(max_results: CALENDAR_BATCH_SIZE)
339
+ lists.items.each do |calendar|
340
+ output << calendar if @emails.include? calendar.id
341
+ end
342
+
343
+ while lists.next_page_token
344
+ lists = @service.list_calendar_lists(
345
+ max_results: CALENDAR_BATCH_SIZE,
346
+ page_token: lists.next_page_token
347
+ )
348
+ lists.items.each do |calendar|
349
+ output << calendar if @emails.include? calendar.id
350
+ end
347
351
  end
352
+ output
348
353
  end
349
354
  memoize :calendars
350
355
 
data/lib/nora/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nora
4
- VERSION = "0.9"
4
+ VERSION = "0.10"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nora
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.9'
4
+ version: '0.10'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jacob Evelyn
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-08-27 00:00:00.000000000 Z
11
+ date: 2019-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -151,7 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
151
151
  version: '0'
152
152
  requirements: []
153
153
  rubyforge_project:
154
- rubygems_version: 2.5.1
154
+ rubygems_version: 2.7.6
155
155
  signing_key:
156
156
  specification_version: 4
157
157
  summary: Bringing P-A-NORA-M-A together.