friends 0.18 → 0.19

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
2
  SHA1:
3
- metadata.gz: cafcf4ae0c7862e767cfa66d62f82358aa4427dd
4
- data.tar.gz: ce713e78e33183b58d1dfe8a0a4ee56434bef476
3
+ metadata.gz: 4ba2ca1e570ce12bae59bd92e45eed450b15859d
4
+ data.tar.gz: f29a32cae219ae83c7cbc925d1493894d76409cb
5
5
  SHA512:
6
- metadata.gz: abe895385b3b8fead89b0d05693b8c8ccce448a3a0af2af65bb0eb0441cc22e4b25d8de0d62b2318572053d5db977ec69dd33b90003017b89bd7349124baa0e1
7
- data.tar.gz: 26ccbf5fe8b0178a8473ed8c7b541bed990cc9d65644760cd21a642a00a4b840048c1a3cde58e87c619d3ee5554e660342b4fce81bc7a012ea29bdff3c631509
6
+ metadata.gz: 264af4e8b7d6956401c9a7e6babecb6a8e8b6dc154de383394aef7890c2262685ea90c24c1d525d03802ecb1a028ffbc445cd4306fa91c5badbf044389667d1e
7
+ data.tar.gz: 674aa75753fc7aedc6f50bbb54956ecd91f6df2d8930d886f5f018e08d9c89b0db2e4f5aa74c014b45b35c6d429809d6fbdb7982598b52b66b0636f377136d3a
@@ -1,5 +1,16 @@
1
1
  # Change Log
2
2
 
3
+ ## [v0.19](https://github.com/JacobEvelyn/friends/tree/v0.19) (2016-05-02)
4
+ [Full Changelog](https://github.com/JacobEvelyn/friends/compare/v0.18...v0.19)
5
+
6
+ **Implemented enhancements:**
7
+
8
+ - Add command to list favorite locations [\#108](https://github.com/JacobEvelyn/friends/issues/108)
9
+
10
+ **Merged pull requests:**
11
+
12
+ - Add `list favorite locations` command [\#115](https://github.com/JacobEvelyn/friends/pull/115) ([JacobEvelyn](https://github.com/JacobEvelyn))
13
+
3
14
  ## [v0.18](https://github.com/JacobEvelyn/friends/tree/v0.18) (2016-05-02)
4
15
  [Full Changelog](https://github.com/JacobEvelyn/friends/compare/v0.17...v0.18)
5
16
 
data/README.md CHANGED
@@ -14,7 +14,7 @@ Extrovert-approved.
14
14
  - [Global flags](#global-flags)
15
15
  - [Syncing across multiple machines](#syncing-across-multiple-machines)
16
16
  - [Command reference](#command-reference)
17
- - [`add`](#add)
17
+ - `add`
18
18
  - [`add activity`](#add-activity)
19
19
  - [`add friend`](#add-friend)
20
20
  - [`add location`](#add-location)
@@ -22,13 +22,15 @@ Extrovert-approved.
22
22
  - [`clean`](#clean)
23
23
  - [`graph`](#graph)
24
24
  - [`help`](#help)
25
- - [`list`](#list)
25
+ - `list`
26
26
  - [`list activities`](#list-activities)
27
- - [`list favorites`](#list-favorites)
27
+ - `list favorite`
28
+ - [`list favorite friends`](#list-favorite-friends)
29
+ - [`list favorite locations`](#list-favorite-locations)
28
30
  - [`list friends`](#list-friends)
29
31
  - [`list locations`](#list-locations)
30
32
  - [`remove nickname`](#remove-nickname)
31
- - [`rename`](#rename)
33
+ - `rename`
32
34
  - [`rename friend`](#rename-friend)
33
35
  - [`rename location`](#rename-location)
34
36
  - [`set location`](#set)
@@ -177,9 +179,7 @@ alias friends="friends --filename '~/Dropbox/friends.md'"
177
179
 
178
180
  *Note that the command-line output is colored, which this README cannot show.
179
181
 
180
- #### `add`
181
-
182
- ##### `add activity`
182
+ #### `add activity`
183
183
 
184
184
  ```bash
185
185
  $ friends add activity "Got lunch with Grace and George."
@@ -240,21 +240,21 @@ $ friends add activity "2015-11-01: Grace and I went to \Marie's Diner. \George
240
240
  Activity added: "2015-11-01: Grace Hopper and I went to Marie's Diner. George had to cancel at the last minute."
241
241
  ```
242
242
 
243
- ##### `add friend`
243
+ #### `add friend`
244
244
 
245
245
  ```bash
246
246
  $ friends add friend "Grace Hopper"
247
247
  Friend added: "Grace Hopper"
248
248
  ```
249
249
 
250
- ##### `add location`
250
+ #### `add location`
251
251
 
252
252
  ```
253
253
  $ friends add location Atlantis
254
254
  Location added: "Atlantis"
255
255
  ```
256
256
 
257
- ##### `add nickname`
257
+ #### `add nickname`
258
258
 
259
259
  ```bash
260
260
  $ friends add nickname "Grace Hopper" "The Admiral"
@@ -344,9 +344,7 @@ $ friends help list
344
344
  $ friends help list activities
345
345
  ```
346
346
 
347
- #### `list`
348
-
349
- ##### `list activities`
347
+ #### `list activities`
350
348
 
351
349
  Lists recent activities:
352
350
 
@@ -380,12 +378,12 @@ $ friends list activities --in "New York"
380
378
  2014-12-31: Celebrated the new year with Marie Curie in New York City.
381
379
  ```
382
380
 
383
- ##### `list favorites`
381
+ #### `list favorite friends`
384
382
 
385
383
  Lists your "favorite" friends (by total number of activities):
386
384
 
387
385
  ```bash
388
- $ friends list favorites
386
+ $ friends list favorite friends
389
387
  Your favorite friends:
390
388
  1. George Washington Carver (2 activities)
391
389
  2. Grace Hopper (1)
@@ -395,13 +393,34 @@ Your favorite friends:
395
393
  You can specify a number of favorites to show:
396
394
 
397
395
  ```bash
398
- $ friends list favorites --limit 2
396
+ $ friends list favorite friends --limit 2
399
397
  Your favorite friends:
400
398
  1. George Washington Carver (2 activities)
401
399
  2. Grace Hopper (1)
402
400
  ```
403
401
 
404
- ##### `list friends`
402
+ #### `list favorite locations`
403
+
404
+ Lists your "favorite" locations (by total number of activities):
405
+
406
+ ```bash
407
+ $ friends list favorite locations
408
+ Your favorite locations:
409
+ 1. Atlantis (2 activities)
410
+ 2. Paris (1)
411
+ 3. London (1)
412
+ ```
413
+
414
+ You can specify a number of favorites to show:
415
+
416
+ ```bash
417
+ $ friends list favorite locations --limit 2
418
+ Your favorite locations:
419
+ 1. Atlantis (2 activities)
420
+ 2. Paris (1)
421
+ ```
422
+
423
+ #### `list friends`
405
424
 
406
425
  Lists all of your friends:
407
426
 
@@ -419,7 +438,7 @@ $ friends list friends --in Paris
419
438
  Marie Curie
420
439
  ```
421
440
 
422
- ##### `list locations`
441
+ #### `list locations`
423
442
 
424
443
  Lists all of the locations you've added:
425
444
 
@@ -439,16 +458,14 @@ $ friends remove nickname "Grace Hopper" "The Admiral"
439
458
  Nickname removed: "Grace Hopper (a.k.a. Amazing Grace)"
440
459
  ```
441
460
 
442
- #### `rename`
443
-
444
- ##### `rename friend`
461
+ #### `rename friend`
445
462
 
446
463
  ```bash
447
464
  $ friends rename friend "Grace Hopper" "Grace Brewster Murray Hopper"
448
465
  Name changed: "Grace Brewster Murray Hopper (a.k.a. Amazing Grace)"
449
466
  ```
450
467
 
451
- ##### `rename location`
468
+ #### `rename location`
452
469
 
453
470
  ```bash
454
471
  $ friends rename location Paris "Paris, France"
@@ -79,25 +79,52 @@ command :list do |list|
79
79
  end
80
80
  end
81
81
 
82
- list.desc "List favorite friends"
83
- list.command :favorites do |list_favorites|
84
- list_favorites.flag [:limit],
85
- arg_name: "NUMBER",
86
- default_value: 10,
87
- desc: "The number of friends to return"
88
-
89
- list_favorites.action do |_, options|
90
- limit = options[:limit].to_i
91
- favorites = @introvert.list_favorites(limit: limit)
82
+ list.desc "List favorite friends and locations"
83
+ list.command :favorite do |list_favorite|
84
+ list_favorite.desc "List favorite friends"
85
+ list_favorite.command :friends do |list_favorite_friends|
86
+ list_favorite_friends.flag [:limit],
87
+ arg_name: "NUMBER",
88
+ default_value: 10,
89
+ desc: "The number of friends to return"
90
+
91
+ list_favorite_friends.action do |_, options|
92
+ limit = options[:limit].to_i
93
+ favorites = @introvert.list_favorite_friends(limit: limit)
94
+
95
+ if limit == 1
96
+ puts "Your best friend is #{favorites.first}"
97
+ else
98
+ puts "Your favorite friends:"
92
99
 
93
- if limit == 1
94
- puts "Your best friend is #{favorites.first}"
95
- else
96
- puts "Your favorite friends:"
100
+ num_str_size = favorites.size.to_s.size + 1
101
+ favorites.each.with_index(1) do |name, rank|
102
+ puts "#{"#{rank}.".ljust(num_str_size)} #{name}"
103
+ end
104
+ end
105
+ end
106
+ end
107
+
108
+ list_favorite.desc "List favorite locations"
109
+ list_favorite.command :locations do |list_favorite_locations|
110
+ list_favorite_locations.flag [:limit],
111
+ arg_name: "NUMBER",
112
+ default_value: 10,
113
+ desc: "The number of locations to return"
114
+
115
+ list_favorite_locations.action do |_, options|
116
+ limit = options[:limit].to_i
117
+ favorites = @introvert.list_favorite_locations(limit: limit)
118
+
119
+ if limit == 1
120
+ puts "Your favorite location is #{favorites.first}"
121
+ else
122
+ puts "Your favorite locations:"
97
123
 
98
- num_str_size = favorites.size.to_s.size + 1
99
- favorites.each.with_index(1) do |name, rank|
100
- puts "#{"#{rank}.".ljust(num_str_size)} #{name}"
124
+ num_str_size = favorites.size.to_s.size + 1
125
+ favorites.each.with_index(1) do |name, rank|
126
+ puts "#{"#{rank}.".ljust(num_str_size)} #{name}"
127
+ end
101
128
  end
102
129
  end
103
130
  end
@@ -127,6 +127,13 @@ module Friends
127
127
  end
128
128
  memoize :friend_names
129
129
 
130
+ # Find the names of all locations in this description.
131
+ # @return [Array] list of all location names in the description
132
+ def location_names
133
+ @description.scan(/(?<=_)\w[^_]*(?=_)/).uniq
134
+ end
135
+ memoize :location_names
136
+
130
137
  private
131
138
 
132
139
  # Modify the description to turn inputted location names (e.g. "Atlantis")
@@ -184,7 +191,7 @@ module Friends
184
191
  end
185
192
 
186
193
  # Now, we compute the likelihood of each friend in the possible-match set.
187
- introvert.set_n_activities!
194
+ introvert.set_friend_n_activities!
188
195
  introvert.set_likelihood_score!(
189
196
  matches: matched_friends,
190
197
  possible_matches: possible_matched_friends
@@ -192,29 +192,19 @@ module Friends
192
192
  end
193
193
 
194
194
  # List your favorite friends.
195
- # @param limit [Integer] the number of favorite friends to return, or nil
196
- # for no limit
195
+ # @param limit [Integer] the number of favorite friends to return
197
196
  # @return [Array] a list of the favorite friends' names and activity
198
197
  # counts
199
- def list_favorites(limit:)
200
- if !limit.nil? && limit < 1
201
- raise FriendsError, "Favorites limit must be positive or unlimited"
202
- end
203
-
204
- set_n_activities! # Set n_activities for all friends.
205
-
206
- # Sort the results, with the most favorite friend first.
207
- results = @friends.sort_by { |friend| -friend.n_activities }
208
-
209
- # If we need to, trim the list.
210
- results = results.take(limit) unless limit.nil?
198
+ def list_favorite_friends(limit:)
199
+ list_favorite_things(:friend, limit: limit)
200
+ end
211
201
 
212
- max_str_size = results.map(&:name).map(&:size).max
213
- results.map.with_index(0) do |friend, index|
214
- name = friend.name.ljust(max_str_size)
215
- parenthetical = "(#{friend.n_activities}#{' activities' if index == 0})"
216
- "#{name} #{parenthetical}"
217
- end
202
+ # List your favorite friends.
203
+ # @param limit [Integer] the number of favorite locations to return
204
+ # @return [Array] a list of the favorite locations' names and activity
205
+ # counts
206
+ def list_favorite_locations(limit:)
207
+ list_favorite_things(:location, limit: limit)
218
208
  end
219
209
 
220
210
  # List all activity details.
@@ -306,7 +296,7 @@ module Friends
306
296
  # for unfiltered
307
297
  # @return [Hash{String => Array<String>}]
308
298
  def suggest(location_name:)
309
- set_n_activities! # Set n_activities for all friends.
299
+ set_friend_n_activities! # Set n_activities for all friends.
310
300
 
311
301
  # Filter our friends by location if necessary.
312
302
  fs = @friends
@@ -338,20 +328,8 @@ module Friends
338
328
  ###################################################################
339
329
 
340
330
  # Sets the n_activities field on each friend.
341
- def set_n_activities!
342
- # Construct a hash of friend name to frequency of appearance.
343
- freq_table = Hash.new { |h, k| h[k] = 0 }
344
- @activities.each do |activity|
345
- activity.friend_names.each do |friend_name|
346
- freq_table[friend_name] += 1
347
- end
348
- end
349
-
350
- # Remove names that are not in the friends list.
351
- freq_table.each do |name, count|
352
- friend = friend_with_exact_name(name)
353
- friend.n_activities = count if friend # Do nothing if name not valid.
354
- end
331
+ def set_friend_n_activities!
332
+ set_n_activities!(:friend)
355
333
  end
356
334
 
357
335
  # Get a regex friend map.
@@ -445,6 +423,59 @@ module Friends
445
423
 
446
424
  private
447
425
 
426
+ # @param type [Symbol] one of: [:friend, :location]
427
+ # @param limit [Integer] the number of favorite things to return
428
+ # @return [Array] a list of the favorite things' names and activity counts
429
+ def list_favorite_things(type, limit:)
430
+ unless [:friend, :location].include? type
431
+ raise FriendsError, "Type must be either :friend or :location"
432
+ end
433
+
434
+ if limit < 1
435
+ raise FriendsError, "Favorites limit must be positive"
436
+ end
437
+
438
+ send("set_n_activities!", type) # Set n_activities for all things.
439
+
440
+ # Sort the results, with the most favorite thing first.
441
+ results = instance_variable_get("@#{type}s").sort_by do |thing|
442
+ -thing.n_activities
443
+ end.take(limit) # Trim the list.
444
+
445
+ max_str_size = results.map(&:name).map(&:size).max
446
+ results.map.with_index(0) do |thing, index|
447
+ name = thing.name.ljust(max_str_size)
448
+ n = thing.n_activities
449
+ if index == 0
450
+ label = n == 1 ? " activity" : " activities"
451
+ end
452
+ parenthetical = "(#{n}#{label})"
453
+ "#{name} #{parenthetical}"
454
+ end
455
+ end
456
+
457
+ # Sets the n_activities field on each thing.
458
+ # @param type [Symbol] one of: [:friend, :location]
459
+ def set_n_activities!(type)
460
+ unless [:friend, :location].include? type
461
+ raise FriendsError, "Type must be either :friend or :location"
462
+ end
463
+
464
+ # Construct a hash of location name to frequency of appearance.
465
+ freq_table = Hash.new { |h, k| h[k] = 0 }
466
+ @activities.each do |activity|
467
+ activity.send("#{type}_names").each do |thing_name|
468
+ freq_table[thing_name] += 1
469
+ end
470
+ end
471
+
472
+ # Remove names that are not in the locations list.
473
+ freq_table.each do |name, count|
474
+ thing = send("#{type}_with_exact_name", name)
475
+ thing.n_activities = count if thing # Do nothing if name isn't valid.
476
+ end
477
+ end
478
+
448
479
  # Process the friends.md file and store its contents in internal data
449
480
  # structures.
450
481
  def read_file
@@ -541,6 +572,19 @@ module Friends
541
572
  end
542
573
  end
543
574
 
575
+ # @param name [String] the name of the location to search for
576
+ # @return [Location] the location whose name exactly matches the argument
577
+ # @raise [FriendsError] if more than one location has the given name
578
+ def location_with_exact_name(name)
579
+ results = @locations.select { |location| location.name == name }
580
+
581
+ case results.size
582
+ when 0 then nil
583
+ when 1 then results.first
584
+ else raise FriendsError, "More than one location named #{name}"
585
+ end
586
+ end
587
+
544
588
  # @param text [String] the name (or substring) of the location to search for
545
589
  # @return [Location] the location that matches
546
590
  # @raise [FriendsError] if 0 or 2+ location match the given text
@@ -39,6 +39,13 @@ module Friends
39
39
  Friends::RegexBuilder.regex(@name)
40
40
  end
41
41
 
42
+ # The number of activities this location is in. This is for internal use
43
+ # only and is set by the Introvert as needed.
44
+ attr_writer :n_activities
45
+ def n_activities
46
+ @n_activities || 0
47
+ end
48
+
42
49
  private
43
50
 
44
51
  # Default sorting for an array of locations is alphabetical.
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Friends
3
- VERSION = "0.18".freeze
3
+ VERSION = "0.19".freeze
4
4
  end
@@ -562,31 +562,34 @@ describe Friends::Introvert do
562
562
  end
563
563
  end
564
564
 
565
- describe "#list_favorites" do
566
- subject { introvert.list_favorites(limit: limit) }
565
+ describe "#list_favorite_friends" do
566
+ subject { introvert.list_favorite_friends(limit: limit) }
567
567
 
568
- describe "when limit is nil" do
569
- let(:limit) { nil }
568
+ describe "when there are more friends than favorites requested" do
569
+ let(:limit) { 1 }
570
570
 
571
- it "returns all friends in order of favoritism with activity counts" do
571
+ it "returns the number of favorites requested" do
572
572
  stub_friends(friends) do
573
573
  stub_activities(activities) do
574
- subject.must_equal [
575
- "Betsy Ross (2 activities)",
576
- "George Washington Carver (1)"
577
- ]
574
+ subject.must_equal ["Betsy Ross (2 activities)"]
578
575
  end
579
576
  end
580
577
  end
581
578
  end
579
+ end
582
580
 
583
- describe "when there are more friends than favorites requested" do
581
+ describe "#list_favorite_locations" do
582
+ subject { introvert.list_favorite_locations(limit: limit) }
583
+
584
+ describe "when there are more locations than favorites requested" do
584
585
  let(:limit) { 1 }
585
586
 
586
587
  it "returns the number of favorites requested" do
587
- stub_friends(friends) do
588
- stub_activities(activities) do
589
- subject.must_equal ["Betsy Ross (2 activities)"]
588
+ stub_locations(locations) do
589
+ stub_activities(
590
+ [Friends::Activity.new(str: "Swimming in _Atlantis_.")]
591
+ ) do
592
+ subject.must_equal ["Atlantis (1 activity)"]
590
593
  end
591
594
  end
592
595
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: friends
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.18'
4
+ version: '0.19'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jacob Evelyn