autumn 3.1.8

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.
Files changed (111) hide show
  1. data/AUTHORS +11 -0
  2. data/CHANGELOG +567 -0
  3. data/MANIFEST +110 -0
  4. data/README +1114 -0
  5. data/README.textile +1153 -0
  6. data/Rakefile +75 -0
  7. data/autumn.gemspec +44 -0
  8. data/bin/autumn +11 -0
  9. data/lib/autumn.rb +8 -0
  10. data/lib/autumn/authentication.rb +238 -0
  11. data/lib/autumn/channel_leaf.rb +107 -0
  12. data/lib/autumn/coder.rb +166 -0
  13. data/lib/autumn/console_boot.rb +10 -0
  14. data/lib/autumn/ctcp.rb +250 -0
  15. data/lib/autumn/daemon.rb +207 -0
  16. data/lib/autumn/datamapper_hacks.rb +290 -0
  17. data/lib/autumn/foliater.rb +231 -0
  18. data/lib/autumn/formatting.rb +236 -0
  19. data/lib/autumn/generator.rb +231 -0
  20. data/lib/autumn/genesis.rb +190 -0
  21. data/lib/autumn/inheritable_attributes.rb +162 -0
  22. data/lib/autumn/leaf.rb +738 -0
  23. data/lib/autumn/log_facade.rb +49 -0
  24. data/lib/autumn/misc.rb +87 -0
  25. data/lib/autumn/resources/daemons/Anothernet.yml +3 -0
  26. data/lib/autumn/resources/daemons/AustHex.yml +29 -0
  27. data/lib/autumn/resources/daemons/Bahamut.yml +67 -0
  28. data/lib/autumn/resources/daemons/Dancer.yml +3 -0
  29. data/lib/autumn/resources/daemons/GameSurge.yml +3 -0
  30. data/lib/autumn/resources/daemons/IRCnet.yml +3 -0
  31. data/lib/autumn/resources/daemons/Ithildin.yml +7 -0
  32. data/lib/autumn/resources/daemons/KineIRCd.yml +56 -0
  33. data/lib/autumn/resources/daemons/PTlink.yml +6 -0
  34. data/lib/autumn/resources/daemons/QuakeNet.yml +20 -0
  35. data/lib/autumn/resources/daemons/RFC1459.yml +158 -0
  36. data/lib/autumn/resources/daemons/RFC2811.yml +16 -0
  37. data/lib/autumn/resources/daemons/RFC2812.yml +36 -0
  38. data/lib/autumn/resources/daemons/RatBox.yml +25 -0
  39. data/lib/autumn/resources/daemons/Ultimate.yml +24 -0
  40. data/lib/autumn/resources/daemons/Undernet.yml +6 -0
  41. data/lib/autumn/resources/daemons/Unreal.yml +110 -0
  42. data/lib/autumn/resources/daemons/_Other.yml +7 -0
  43. data/lib/autumn/resources/daemons/aircd.yml +33 -0
  44. data/lib/autumn/resources/daemons/bdq-ircd.yml +3 -0
  45. data/lib/autumn/resources/daemons/hybrid.yml +38 -0
  46. data/lib/autumn/resources/daemons/ircu.yml +67 -0
  47. data/lib/autumn/resources/daemons/tr-ircd.yml +8 -0
  48. data/lib/autumn/script.rb +74 -0
  49. data/lib/autumn/speciator.rb +165 -0
  50. data/lib/autumn/stem.rb +919 -0
  51. data/lib/autumn/stem_facade.rb +176 -0
  52. data/lib/autumn/tool/bin.rb +301 -0
  53. data/lib/autumn/tool/create.rb +48 -0
  54. data/lib/autumn/tool/project_creator.rb +110 -0
  55. data/lib/autumn/version.rb +3 -0
  56. data/lib/skel/Rakefile +163 -0
  57. data/lib/skel/config/global.yml +2 -0
  58. data/lib/skel/config/seasons/testing/database.yml +4 -0
  59. data/lib/skel/config/seasons/testing/leaves.yml +9 -0
  60. data/lib/skel/config/seasons/testing/season.yml +2 -0
  61. data/lib/skel/config/seasons/testing/stems.yml +10 -0
  62. data/lib/skel/leaves/administrator/README +20 -0
  63. data/lib/skel/leaves/administrator/controller.rb +67 -0
  64. data/lib/skel/leaves/administrator/views/autumn.txt.erb +1 -0
  65. data/lib/skel/leaves/administrator/views/reload.txt.erb +11 -0
  66. data/lib/skel/leaves/insulter/README +17 -0
  67. data/lib/skel/leaves/insulter/controller.rb +65 -0
  68. data/lib/skel/leaves/insulter/views/about.txt.erb +1 -0
  69. data/lib/skel/leaves/insulter/views/help.txt.erb +1 -0
  70. data/lib/skel/leaves/insulter/views/insult.txt.erb +1 -0
  71. data/lib/skel/leaves/scorekeeper/README +34 -0
  72. data/lib/skel/leaves/scorekeeper/config.yml +2 -0
  73. data/lib/skel/leaves/scorekeeper/controller.rb +104 -0
  74. data/lib/skel/leaves/scorekeeper/helpers/general.rb +64 -0
  75. data/lib/skel/leaves/scorekeeper/models/channel.rb +12 -0
  76. data/lib/skel/leaves/scorekeeper/models/person.rb +14 -0
  77. data/lib/skel/leaves/scorekeeper/models/pseudonym.rb +11 -0
  78. data/lib/skel/leaves/scorekeeper/models/score.rb +14 -0
  79. data/lib/skel/leaves/scorekeeper/tasks/stats.rake +17 -0
  80. data/lib/skel/leaves/scorekeeper/views/about.txt.erb +1 -0
  81. data/lib/skel/leaves/scorekeeper/views/change.txt.erb +5 -0
  82. data/lib/skel/leaves/scorekeeper/views/history.txt.erb +11 -0
  83. data/lib/skel/leaves/scorekeeper/views/points.txt.erb +5 -0
  84. data/lib/skel/leaves/scorekeeper/views/usage.txt.erb +1 -0
  85. data/lib/skel/log/README +1 -0
  86. data/lib/skel/script/console +28 -0
  87. data/lib/skel/script/destroy +48 -0
  88. data/lib/skel/script/generate +48 -0
  89. data/lib/skel/shared/README +1 -0
  90. data/lib/skel/tmp/README +1 -0
  91. data/spec/authentication_spec.rb +328 -0
  92. data/spec/channel_leaf_spec.rb +142 -0
  93. data/spec/coder_spec.rb +146 -0
  94. data/spec/ctcp_spec.rb +222 -0
  95. data/spec/daemon_spec.rb +202 -0
  96. data/spec/datamapper_hacks_spec.rb +164 -0
  97. data/tasks/authors.rake +30 -0
  98. data/tasks/changelog.rake +18 -0
  99. data/tasks/copyright.rake +21 -0
  100. data/tasks/doc.rake +7 -0
  101. data/tasks/gem.rake +23 -0
  102. data/tasks/gem_installer.rake +76 -0
  103. data/tasks/install_dependencies.rake +6 -0
  104. data/tasks/manifest.rake +4 -0
  105. data/tasks/rcov.rake +23 -0
  106. data/tasks/release.rake +52 -0
  107. data/tasks/reversion.rake +8 -0
  108. data/tasks/setup.rake +24 -0
  109. data/tasks/spec.rake +7 -0
  110. data/tasks/yard.rake +4 -0
  111. metadata +188 -0
@@ -0,0 +1 @@
1
+ Autumn version <%= var :version %>, an IRC bot framework for Ruby (http://github.com/RISCfuture/autumn).
@@ -0,0 +1,11 @@
1
+ <% if var(:not_found) %>
2
+ There is no leaf named <%= var :not_found %>.
3
+ <% else %>
4
+ <% var(:leaves).each do |leaf, error| %>
5
+ <% if error %>
6
+ <%= leaf %> couldn't be reloaded: <%= error %>
7
+ <% else %>
8
+ <%= leaf %> was reloaded successfully.
9
+ <% end %>
10
+ <% end %>
11
+ <% end %>
@@ -0,0 +1,17 @@
1
+ = Insulter: An Autumn Leaf
2
+
3
+ <b>Version 1.0 (Jul 4, 2008)</b>
4
+
5
+ Author:: Tim Morgan (mailto:riscfuture@gmail.com)
6
+ Copyright:: Copyright (c)2008 Tim Morgan
7
+ License:: Distributed under the same terms as Ruby. Portions of this content
8
+ are copyright (c)1996 Main Strike Telecommunications, Inc.
9
+
10
+ A simple Autumn Leaf that generates faux-Shakespearean insults. This leaf
11
+ required no database and no additional gems beyond that of a normal Autumn
12
+ install.
13
+
14
+ == Usage
15
+
16
+ !insult [name]:: The bot lets fly a barbarous insult against [name], whose very
17
+ spirit will thenceforth be crushed into a negligible pulp.
@@ -0,0 +1,65 @@
1
+ # Controller and model for the Insulter leaf; maintains the list of insult
2
+ # substrings and chooses from them randomly.
3
+
4
+ class Controller < Autumn::Leaf
5
+
6
+ # Insults the unfortunate argument of this command.
7
+
8
+ def insult_command(stem, sender, reply_to, msg)
9
+ if msg.nil? then render :help
10
+ else insult msg.capitalize end
11
+ end
12
+
13
+ # Displays information about the leaf.
14
+
15
+ def about_command(stem, sender, reply_to, msg)
16
+ end
17
+
18
+ private
19
+
20
+ ADJECTIVES = [
21
+ 'an artless', 'a bawdy', 'a beslubbering', 'a bootless', 'a churlish',
22
+ 'a clouted', 'a cockered', 'a craven', 'a currish', 'a dankish',
23
+ 'a dissembling', 'a droning', 'an errant', 'a fawning', 'a fobbing',
24
+ 'a frothy', 'a froward', 'a gleeking', 'a goatish', 'a gorbellied',
25
+ 'an impertinent', 'an infectious', 'a jarring', 'a loggerheaded',
26
+ 'a lumpish', 'a mammering', 'a mangled', 'a mewling', 'a paunchy',
27
+ 'a pribbling', 'a puking', 'a puny', 'a qualling', 'a rank', 'a reeky',
28
+ 'a roguish', 'a ruttish', 'a saucy', 'a spleeny', 'a spongy', 'a surly',
29
+ 'a tottering', 'an unmuzzled', 'a vain', 'a venomed', 'a villainous',
30
+ 'a warped', 'a wayward', 'a weedy', 'a yeasty'
31
+ ]
32
+
33
+ PARTICIPLES = [
34
+ 'base-court', 'bat-fowling', 'beef-witted', 'beetle-headed', 'boil-brained',
35
+ 'clapper-clawed', 'clay-brained', 'common-kissing', 'crook-pated',
36
+ 'dismal-dreaming', 'dizzy-eyed', 'doghearted', 'dread-bolted',
37
+ 'earth-vexing', 'elf-skinned', 'fat-kidneyed', 'fen-sucked', 'flap-mouthed',
38
+ 'fly-bitten', 'folly-fallen', 'fool-born', 'full-gorged', 'guts-griping',
39
+ 'half-faced', 'hasty-witted', 'hedge-born', 'hell-hated', 'idle-headed',
40
+ 'ill-breeding', 'ill-nurtured', 'knotty-pated', 'milk-livered',
41
+ 'motley-minded', 'onion-eyed', 'plume-plucked', 'pottle-deep', 'pox-marked',
42
+ 'reeling-ripe', 'rough-hewn', 'rude-growing', 'rump-fed', 'shard-borne',
43
+ 'sheep-biting', 'spur-galled', 'swag-bellied', 'tardy-gaited',
44
+ 'tickle-brained', 'toad-spotted', 'urchin-snouted', 'weather-bitten'
45
+ ]
46
+
47
+ NOUNS = [
48
+ 'apple-john', 'baggage', 'barnacle', 'bladder', 'boar-pig', 'bugbear',
49
+ 'bum-bailey', 'canker-blossom', 'clack-dish', 'clotpole', 'codpiece',
50
+ 'coxcomb', 'death-token', 'dewberry', 'flap-dragon', 'flax-wench',
51
+ 'flirt-gill', 'foot-licker', 'fustilarian', 'giglet', 'gudgeon', 'haggard',
52
+ 'harpy', 'hedge-pig', 'horn-beast', 'hugger-mugger', 'joithead', 'lewdster',
53
+ 'lout', 'maggot-pie', 'malt-worm', 'mammet', 'measle', 'minnow',
54
+ 'miscreant', 'moldwarp', 'mumble-news', 'nut-hook', 'pigeon-egg', 'pignut',
55
+ 'pumpion', 'puttock', 'ratsbane', 'scut', 'skainsmate', 'strumpet',
56
+ 'varlet', 'vassal', 'wagtail', 'whey-face'
57
+ ]
58
+
59
+ def insult(victim)
60
+ var :adjective => ADJECTIVES.pick
61
+ var :participle => PARTICIPLES.pick
62
+ var :noun => NOUNS.pick
63
+ var :victim => victim
64
+ end
65
+ end
@@ -0,0 +1 @@
1
+ Insulter version 1.0 (7-4-08) by Tim Morgan: An Autumn Leaf. Insults copyright (c)1996 Main Strike Telecommunications, Inc.
@@ -0,0 +1 @@
1
+ Type "!insult Ted" to crush Ted's spirit with a devastating insult.
@@ -0,0 +1 @@
1
+ <%= var :victim %>, thou art <%= var :adjective %> <%= var :participle %> <%= var :noun %>!
@@ -0,0 +1,34 @@
1
+ = Scorekeeper: An Autumn Leaf
2
+
3
+ <b>Version 3.0 (Jul 4, 2008)</b>
4
+
5
+ Author:: Tim Morgan (mailto:riscfuture@gmail.com)
6
+ Copyright:: Copyright (c)2007-2008 Tim Morgan
7
+ License:: Distributed under the same terms as Ruby.
8
+
9
+ An Autumn Leaf used for an in-channel scorekeeping system. This can operate both
10
+ as an open or closed score system. (In the former, new members are automatically
11
+ added when they receive points; in the latter, only authorized members can give
12
+ and receive points.)
13
+
14
+ Scorekeeper is a database-backed leaf. It requires the DataMapper gem
15
+ (http://www.datamapper.org) in order to run. The database stores channels and
16
+ their members, and each member's point history.
17
+
18
+ Scorekeeper supports pseudonyms. Entries in the +pseudonyms+ table can be used
19
+ to help ensure that the correct person's points are changed even when the sender
20
+ uses a nickname or abbreviation.
21
+
22
+ Scorekeeper takes one custom configuration option, +scoring+, which can be
23
+ either "open" or "closed". A closed system only allows a specified set of users
24
+ to receive and give points. An open system allows anyone to award points to
25
+ anyone.
26
+
27
+ == Usage
28
+
29
+ !points [name]:: Get a person's score
30
+ !points [name] [+|-][number] [reason]:: Change a person's score (you must have a
31
+ "+" or a "-"). A reason is optional.
32
+ !points [name] history:: Return some recent history of that person's score.
33
+ !points [name] history [time period]:: Selects history from a time period.
34
+ !points [name] history [sender]:: Selects point changes from a sender.
@@ -0,0 +1,2 @@
1
+ ---
2
+ scoring: open
@@ -0,0 +1,104 @@
1
+ require 'dm-ar-finders'
2
+
3
+ begin
4
+ gem 'chronic'
5
+ require 'chronic'
6
+ rescue Gem::LoadError
7
+ # Install the "chronic" gem for more robust date parsing
8
+ end
9
+
10
+ # Controller for the Scorekeeper leaf. This class contains only the methods
11
+ # directly relating to IRC. Other methods are stored in the helper and model
12
+ # classes.
13
+
14
+ class Controller < Autumn::Leaf
15
+
16
+ # Displays an about message.
17
+
18
+ def about_command(stem, sender, reply_to, msg)
19
+ end
20
+
21
+ # Displays the current point totals, or modifies someone's score, depending on
22
+ # the message provided with the command.
23
+
24
+ def points_command(stem, sender, reply_to, msg)
25
+ if msg.nil? or msg.empty? then
26
+ var :totals => totals(stem, reply_to)
27
+ elsif msg =~ /^(\w+)\s+history\s*(.*)$/ then
28
+ parse_history stem, reply_to, $1, $2
29
+ render :history
30
+ elsif msg =~ /^(\w+)\s+([\+\-]\d+)\s*(.*)$/ then
31
+ parse_change stem, reply_to, sender, $1, $2.to_i, $3
32
+ render :change
33
+ else
34
+ render :usage
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def points(stem, channel)
41
+ chan = Channel.find_or_create :server => server_identifier(stem), :name => channel
42
+ scores = chan.scores.all
43
+ scores.inject(Hash.new(0)) { |hsh, score| hsh[score.receiver.name] += score.change; hsh }
44
+ end
45
+
46
+ def totals(stem, channel)
47
+ points(stem, channel).sort { |a,b| b.last <=> a.last }
48
+ end
49
+
50
+ def parse_change(stem, channel, sender, victim, delta, note)
51
+ giver = find_person(stem, sender[:nick])
52
+ receiver = find_person(stem, victim)
53
+ if giver.nil? and options[:scoring] == 'open' then
54
+ giver ||= Person.create :server => server_identifier(stem), :name => sender[:nick]
55
+ end
56
+ if receiver.nil? and options[:scoring] == 'open' then
57
+ receiver ||= Person.create :server => server_identifier(stem), :name => find_in_channel(stem, channel, victim)
58
+ end
59
+ unless authorized?(giver, receiver)
60
+ var :unauthorized => true
61
+ var :receiver => receiver.nil? ? victim : receiver.name
62
+ return
63
+ end
64
+ change_points stem, channel, giver, receiver, delta, note
65
+ var :giver => giver
66
+ var :receiver => receiver
67
+ var :delta => delta
68
+ end
69
+
70
+ def parse_history(stem, channel, subject, argument)
71
+ date = argument.empty? ? nil : parse_date(argument)
72
+ scores = Array.new
73
+
74
+ chan = Channel.first(:name => channel)
75
+ person = find_person(stem, subject)
76
+ if person.nil? then
77
+ var :person => subject
78
+ var :no_history => true
79
+ return
80
+ end
81
+
82
+ if date then
83
+ start, stop = find_range(date)
84
+ scores = chan.scores.all(:conditions => [ "receiver_id = ? AND created_at >= ? AND created_at < ?", person.id, start, stop ], :order => [ :created_at.desc ], :limit => 5)
85
+ #TODO is there a way to scope by both channel and receiver?
86
+ elsif argument.empty? then
87
+ scores = chan.scores.all(:conditions => [ "receiver_id = ?", person.id ], :order => [ :created_at.desc ], :limit => 5)
88
+ #TODO is there a way to scope by both channel and receiver?
89
+ else
90
+ giver = find_person(stem, argument)
91
+ if giver.nil? then
92
+ var :giver => argument
93
+ var :receiver => person
94
+ var :no_giver_history => true
95
+ return
96
+ end
97
+ scores = chan.scores.all(:conditions => [ "receiver_id = ? AND giver_id = ?", person.id, giver.id ], :order => [ :created_at.desc ], :limit => 5)
98
+ #TODO is there a way to scope by channel, receiver, and giver?
99
+ end
100
+ var :receiver => person
101
+ var :giver => giver
102
+ var :scores => scores
103
+ end
104
+ end
@@ -0,0 +1,64 @@
1
+ # Utility methods used by Scorekeeper.
2
+
3
+ module GeneralHelper
4
+ def parse_date(str)
5
+ date = nil
6
+ begin
7
+ date = Chronic.parse(str, :context => :past, :guess => false)
8
+ rescue NameError
9
+ begin
10
+ date = Date.parse(str)
11
+ rescue ArgumentError
12
+ end
13
+ end
14
+ return date
15
+ end
16
+
17
+ def find_range(date)
18
+ start = nil
19
+ stop = nil
20
+ if date.kind_of? Range then
21
+ start = date.first
22
+ stop = date.last
23
+ elsif date.kind_of? Time then
24
+ start = date.to_date
25
+ stop = date.to_date + 1
26
+ else
27
+ start = date
28
+ stop = date + 1
29
+ end
30
+ return start, stop
31
+ end
32
+
33
+ def find_person(stem, nick)
34
+ Person.all(:server => server_identifier(stem)).each do |person|
35
+ return person if person.name.downcase == normalize(nick) or person.pseudonyms.collect { |pn| pn.name.downcase }.include? normalize(nick)
36
+ end
37
+ return nil
38
+ end
39
+
40
+ def find_in_channel(stem, channel, victim)
41
+ stem.channel_members[channel].each do |name, privilege|
42
+ return normalize(name, false) if normalize(name) == normalize(victim)
43
+ end
44
+ return victim
45
+ end
46
+
47
+ def normalize(nick, dc=true)
48
+ dc ? nick.downcase.split(/\|/)[0] : nick.split(/\|/)[0]
49
+ end
50
+
51
+ def authorized?(giver, receiver)
52
+ giver and receiver and giver.authorized? and giver.name != receiver.name
53
+ end
54
+
55
+ def change_points(stem, channel, giver, receiver, delta, note=nil)
56
+ return if delta.zero?
57
+ chan = Channel.find_or_create :server => server_identifier(stem), :name => channel
58
+ chan.scores.create :giver => giver, :receiver => receiver, :change => delta, :note => note
59
+ end
60
+
61
+ def server_identifier(stem)
62
+ "#{stem.server}:#{stem.port}"
63
+ end
64
+ end
@@ -0,0 +1,12 @@
1
+ # An IRC server and channel. The server property is of the form
2
+ # "[address]:[port]".
3
+
4
+ class Channel
5
+ include DataMapper::Resource
6
+
7
+ property :id, Integer, :serial => true
8
+ property :server, String, :nullable => false
9
+ property :name, String, :nullable => false
10
+
11
+ has n, :scores
12
+ end
@@ -0,0 +1,14 @@
1
+ # An IRC member who can give or receive points.
2
+
3
+ class Person
4
+ include DataMapper::Resource
5
+
6
+ property :id, Integer, :serial => true
7
+ property :server, String, :nullable => false
8
+ property :name, String, :nullable => false
9
+ property :authorized, Boolean, :nullable => false, :default => true
10
+
11
+ has n, :scores, :child_key => [ :receiver_id ]
12
+ has n, :scores_awarded, :class_name => 'Score', :child_key => [ :giver_id ]
13
+ has n, :pseudonyms
14
+ end
@@ -0,0 +1,11 @@
1
+ # A person's nickname. If someone changes a person's points using this nickname,
2
+ # the correct Person instance has their points changed.
3
+
4
+ class Pseudonym
5
+ include DataMapper::Resource
6
+
7
+ property :id, Integer, :serial => true
8
+ property :name, String, :nullable => false
9
+
10
+ belongs_to :person
11
+ end
@@ -0,0 +1,14 @@
1
+ # A change to a person's score.
2
+
3
+ class Score
4
+ include DataMapper::Resource
5
+
6
+ property :id, Integer, :serial => true
7
+ property :change, Integer, :nullable => false, :default => 0
8
+ property :note, String
9
+ property :created_at, DateTime, :default => 'NOW()'
10
+
11
+ belongs_to :giver, :class_name => 'Person', :child_key => [ :giver_id ]
12
+ belongs_to :receiver, :class_name => 'Person', :child_key => [ :receiver_id ]
13
+ belongs_to :channel
14
+ end
@@ -0,0 +1,17 @@
1
+ desc "Display the current scores of every channel"
2
+ task :scores => :boot do
3
+ Autumn::Foliater.instance.leaves.select { |name, leaf| leaf.kind_of? Scorekeeper::Controller }.each do |name, leaf|
4
+ puts "Leaf #{name}"
5
+ leaf.database do
6
+ Scorekeeper::Channel.all.group_by { |chan| chan.server }.each do |server, channels|
7
+ puts " #{server}"
8
+ channels.each do |channel|
9
+ scores = channel.scores
10
+ vals = scores.inject(Hash.new(0)) { |hsh, score| hsh[score.receiver.name] += score.change; hsh }
11
+ print_scores = vals.sort { |a,b| b.last <=> a.last }.collect { |n,p| "#{n}: #{p}" }.join(', ')
12
+ puts " #{channel.name} - #{print_scores}"
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1 @@
1
+ Scorekeeper version 3.0 (7-4-08) by Tim Morgan: An Autumn Leaf.
@@ -0,0 +1,5 @@
1
+ <% if var(:unauthorized) %>
2
+ You can't change <%= var :receiver %>'s points.
3
+ <% else %>
4
+ <%= var(:giver).name %> <%= var(:delta) > 0 ? 'gave' : 'docked' %> <%= var(:receiver).name %> <%= var(:delta).abs.pluralize('point') %>.
5
+ <% end %>
@@ -0,0 +1,11 @@
1
+ <% if var(:no_history) %>
2
+ <%= var :person %> is not a part of the scoring system.
3
+ <% elsif var(:no_giver_history) %>
4
+ <%= var :giver %> has not awarded any points to <%= var(:receiver).name %>.
5
+ <% elsif var(:scores).empty? %>
6
+ <%= var(:receiver).name %> has no points history.
7
+ <% else %>
8
+ <% var(:scores).each do |score| %>
9
+ [<%= score.created_at.strftime '%m/%d %I:%M %p' %>] <%= score.giver.name %> <%= score.change > 0 ? 'gave' : 'docked' %> <%= score.receiver.name %> <%= score.change.abs.pluralize('point') %><% if score.note %>: <%= score.note %><% end %>
10
+ <% end %>
11
+ <% end %>
@@ -0,0 +1,5 @@
1
+ <% if var(:totals).empty? %>
2
+ No one has any points yet.
3
+ <% else %>
4
+ <%= var(:totals).collect { |person, score| "#{person}: #{score}" }.join(', ') %>
5
+ <% end %>
@@ -0,0 +1 @@
1
+ Examples: "!points", "!points Sancho +5", "!points Smith history", "!points Sancho history 2/27/08", "!points Sancho history Smith"
@@ -0,0 +1 @@
1
+ logs go in this directory
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Launches an IRb console with the Autumn environment loaded.
4
+
5
+ AL_ROOT = File.expand_path("#{File.dirname(__FILE__)}/..")
6
+ Dir.chdir AL_ROOT
7
+
8
+ # Some code below is from Ruby on Rails and copyright (c) David Heinemeier
9
+ # Hansson.
10
+
11
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
12
+
13
+ require 'optparse'
14
+ options = { :irb => irb }
15
+ OptionParser.new do |opt|
16
+ opt.banner = "Usage: #{File.basename(__FILE__)} [options]"
17
+ opt.on("--irb=[#{irb}]", 'Invoke a different irb.') { |v| options[:irb] = v }
18
+ opt.parse!(ARGV)
19
+ end
20
+
21
+ libs = " -r irb/completion"
22
+ libs << " -r autumn"
23
+ libs << " -r autumn/console_boot"
24
+
25
+ require "autumn"
26
+ ENV["AUTUMN_ROOT"] = AL_ROOT
27
+ puts "Loading Autumn #{Autumn::Version} in #{AL_ROOT} ..."
28
+ exec "#{options[:irb]} #{libs}"