stacked 0.5.0
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/.document +5 -0
- data/.gitignore +6 -0
- data/Gemfile +1 -0
- data/LICENSE +20 -0
- data/README.markdown +37 -0
- data/README.rdoc +18 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/cleaner.rb +29 -0
- data/doc/Stacked.html +155 -0
- data/doc/Stacked/Answer.html +1394 -0
- data/doc/Stacked/Badge.html +480 -0
- data/doc/Stacked/Base.html +1124 -0
- data/doc/Stacked/Comment.html +1037 -0
- data/doc/Stacked/NotImplemented.html +162 -0
- data/doc/Stacked/Posttimeline.html +543 -0
- data/doc/Stacked/Question.html +1763 -0
- data/doc/Stacked/Reputation.html +606 -0
- data/doc/Stacked/Tag.html +267 -0
- data/doc/Stacked/User.html +2787 -0
- data/doc/Stacked/Usertimeline.html +630 -0
- data/doc/_index.html +246 -0
- data/doc/file.README.html +54 -0
- data/doc/index.html +54 -0
- data/doc/method_list.html +1203 -0
- data/doc/top-level-namespace.html +87 -0
- data/genddoc.sh +12 -0
- data/lib/stacked.rb +46 -0
- data/lib/stacked/answer.rb +43 -0
- data/lib/stacked/badge.rb +18 -0
- data/lib/stacked/base.rb +159 -0
- data/lib/stacked/comment.rb +37 -0
- data/lib/stacked/posttimeline.rb +10 -0
- data/lib/stacked/question.rb +85 -0
- data/lib/stacked/reputation.rb +15 -0
- data/lib/stacked/tag.rb +9 -0
- data/lib/stacked/user.rb +195 -0
- data/lib/stacked/usertimeline.rb +14 -0
- data/spec/sorted_by_spec.rb +24 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/stacked/answer_spec.rb +31 -0
- data/spec/stacked/badge_spec.rb +17 -0
- data/spec/stacked/base_spec.rb +27 -0
- data/spec/stacked/comment_spec.rb +41 -0
- data/spec/stacked/question_spec.rb +110 -0
- data/spec/stacked/reputation_spec.rb +18 -0
- data/spec/stacked/tag_spec.rb +21 -0
- data/spec/stacked/user_spec.rb +187 -0
- data/spec/stacked/usertimeline_spec.rb +5 -0
- data/spec/support/aliases.rb +7 -0
- data/spec/support/sorted_by.rb +31 -0
- data/spec/support/within.rb +24 -0
- data/spec/within_spec.rb +19 -0
- data/stacked.gemspec +115 -0
- data/stylesheet.css +41 -0
- metadata +157 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
module Stacked
|
2
|
+
class Reputation < Base
|
3
|
+
attr_accessor :negative_rep,
|
4
|
+
:on_date,
|
5
|
+
:positive_rep,
|
6
|
+
:post_id,
|
7
|
+
:post_type,
|
8
|
+
:title
|
9
|
+
|
10
|
+
# Return the cumulative score of this reputation.
|
11
|
+
def score
|
12
|
+
positive_rep - negative_rep
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/stacked/tag.rb
ADDED
data/lib/stacked/user.rb
ADDED
@@ -0,0 +1,195 @@
|
|
1
|
+
module Stacked
|
2
|
+
class User < Base
|
3
|
+
attr_accessor :about_me,
|
4
|
+
:accept_rate,
|
5
|
+
:age,
|
6
|
+
:answer_count,
|
7
|
+
:creation_date,
|
8
|
+
:display_name,
|
9
|
+
:down_vote_count,
|
10
|
+
:email_hash,
|
11
|
+
:last_access_date,
|
12
|
+
:location,
|
13
|
+
:question_count,
|
14
|
+
:reputation,
|
15
|
+
:up_vote_count,
|
16
|
+
:user_id,
|
17
|
+
:user_type,
|
18
|
+
:view_count,
|
19
|
+
:website_url
|
20
|
+
|
21
|
+
collection :newest, :oldest, :name
|
22
|
+
|
23
|
+
class << self
|
24
|
+
alias_method :reputation, :all
|
25
|
+
|
26
|
+
# Returns users matching the given filter.
|
27
|
+
def filter(filter, options={})
|
28
|
+
options.reverse_merge!(:filter => filter)
|
29
|
+
records(path, options)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
###########
|
34
|
+
# Answers #
|
35
|
+
###########
|
36
|
+
|
37
|
+
# Paginated answers for this user.
|
38
|
+
def answers(options={})
|
39
|
+
parse_answers(request(singular(id) + "answers", options))
|
40
|
+
end
|
41
|
+
|
42
|
+
# Paginated answers by views for this user.
|
43
|
+
def answers_by_views(options={})
|
44
|
+
parse_answers(request(singular(id) + "answers/views", options))
|
45
|
+
end
|
46
|
+
|
47
|
+
# Paginated answers by votes for this user.
|
48
|
+
def answers_by_votes(options={})
|
49
|
+
parse_answers(request(singular(id) + "answers/votes", options))
|
50
|
+
end
|
51
|
+
|
52
|
+
# Newest answers for this user.
|
53
|
+
def newest_answers(options={})
|
54
|
+
parse_answers(request(singular(id) + "answers/newest", options))
|
55
|
+
end
|
56
|
+
|
57
|
+
############
|
58
|
+
# Comments #
|
59
|
+
############
|
60
|
+
|
61
|
+
# Paginated comments for this user.
|
62
|
+
def comments(options={})
|
63
|
+
parse_comments(request(singular(id) + "comments", options))
|
64
|
+
end
|
65
|
+
|
66
|
+
# Find a comment directed at +other_user_id+.
|
67
|
+
# Works only if you specify it the correct range.
|
68
|
+
# This method's a bit funny. http://dev.meta.stackoverflow.com/questions/34747/comments-api-method
|
69
|
+
def directed_at(other_user_id, options={})
|
70
|
+
parse_comments(request(singular(id) + "comments" + other_user_id.to_s, options))
|
71
|
+
end
|
72
|
+
|
73
|
+
# All comments directed at +other_user_id+ ordered by creation date in descending order.
|
74
|
+
def directed_at_by_date(other_user_id, options={})
|
75
|
+
parse_comments(request(singular(id) + "comments" + other_user_id.to_s + "recent", options))
|
76
|
+
end
|
77
|
+
|
78
|
+
# All comments directed at +other_user_id+ ordered by votes.
|
79
|
+
def directed_at_by_score(other_user_id, options={})
|
80
|
+
parse_comments(request(singular(id) + "comments" + other_user_id.to_s + "score", options))
|
81
|
+
end
|
82
|
+
|
83
|
+
# Paginated comments for this user ordered by score.
|
84
|
+
def comments_by_score(options={})
|
85
|
+
parse_comments(request(singular(id) + "comments/score", options))
|
86
|
+
end
|
87
|
+
|
88
|
+
alias_method :popular_comments, :comments_by_score
|
89
|
+
|
90
|
+
# Paginated comments for this user ordered by date created.
|
91
|
+
def recent_comments(options={})
|
92
|
+
parse_comments(request(singular(id) + "comments/recent", options))
|
93
|
+
end
|
94
|
+
|
95
|
+
##############
|
96
|
+
# Favourites #
|
97
|
+
##############
|
98
|
+
|
99
|
+
# Paginated favorites in the order they were added.
|
100
|
+
def added_favorites(options={})
|
101
|
+
parse_questions(request(singular(id) + "favorites/added", options))
|
102
|
+
end
|
103
|
+
|
104
|
+
# Paginated favorites.
|
105
|
+
def favorites(options={})
|
106
|
+
parse_questions(request(singular(id) + "favorites", options))
|
107
|
+
end
|
108
|
+
|
109
|
+
def newest_favorites(options={})
|
110
|
+
parse_questions(request(singular(id) + "favorites/newest", options))
|
111
|
+
end
|
112
|
+
|
113
|
+
def popular_favorites(options={})
|
114
|
+
parse_questions(request(singular(id) + "favorites/views", options))
|
115
|
+
end
|
116
|
+
|
117
|
+
alias_method :favorites_by_views, :popular_favorites
|
118
|
+
alias_method :favourites_by_views, :popular_favorites
|
119
|
+
|
120
|
+
def recent_favorites(options={})
|
121
|
+
parse_questions(request(singular(id) + "favorites/recent", options))
|
122
|
+
end
|
123
|
+
|
124
|
+
# Silly Americans.
|
125
|
+
alias_method :added_favourites, :added_favorites
|
126
|
+
alias_method :favourites, :favorites
|
127
|
+
alias_method :popular_favourites, :popular_favorites
|
128
|
+
alias_method :recent_favourites, :favorites
|
129
|
+
alias_method :newest_favourites, :newest_favorites
|
130
|
+
|
131
|
+
#############
|
132
|
+
# Questions #
|
133
|
+
#############
|
134
|
+
|
135
|
+
def newest_questions(options={})
|
136
|
+
parse_questions(request(singular(id) + "questions/newest", options))
|
137
|
+
end
|
138
|
+
|
139
|
+
def questions(options={})
|
140
|
+
parse_questions(request(singular(id) + "questions", options))
|
141
|
+
end
|
142
|
+
|
143
|
+
def questions_by_views(options={})
|
144
|
+
parse_questions(request(singular(id) + "questions/views", options))
|
145
|
+
end
|
146
|
+
|
147
|
+
def questions_by_votes(options={})
|
148
|
+
parse_questions(request(singular(id) + "questions/votes", options))
|
149
|
+
end
|
150
|
+
|
151
|
+
alias_method :popular_questions, :questions_by_votes
|
152
|
+
|
153
|
+
def recent_questions(options={})
|
154
|
+
parse_questions(request(singular(id) + "questions/recent", options))
|
155
|
+
end
|
156
|
+
|
157
|
+
###############
|
158
|
+
# Other stuff #
|
159
|
+
###############
|
160
|
+
|
161
|
+
def reputations(options={})
|
162
|
+
parse_reputations(request(singular(id) + "reputation", options))
|
163
|
+
end
|
164
|
+
|
165
|
+
def mentioned(options={})
|
166
|
+
parse_comments(request(singular(id) + "mentioned", options))
|
167
|
+
end
|
168
|
+
|
169
|
+
def badges(options={})
|
170
|
+
parse_badges(request(singular(id) + "badges", options))
|
171
|
+
end
|
172
|
+
|
173
|
+
def tags(options={})
|
174
|
+
parse_tags(request(singular(id) + "tags", options))
|
175
|
+
end
|
176
|
+
|
177
|
+
alias_method :mentions, :mentioned
|
178
|
+
|
179
|
+
def timeline(options={})
|
180
|
+
parse_user_timeline(request(singular(id) + "timeline", options))
|
181
|
+
end
|
182
|
+
|
183
|
+
alias_method :created_at, :creation_date
|
184
|
+
alias_method :down_votes, :down_vote_count
|
185
|
+
alias_method :gravatar, :email_hash
|
186
|
+
alias_method :id, :user_id
|
187
|
+
alias_method :name, :display_name
|
188
|
+
alias_method :recent_answers, :answers
|
189
|
+
alias_method :type, :user_type
|
190
|
+
alias_method :up_votes, :up_vote_count
|
191
|
+
alias_method :views, :view_count
|
192
|
+
|
193
|
+
|
194
|
+
end
|
195
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Stacked
|
2
|
+
# I would really *love* to call this UserTimeline but alas, the API fails me.
|
3
|
+
class Usertimeline < Base
|
4
|
+
attr_accessor :action,
|
5
|
+
:comment_id,
|
6
|
+
:creation_date,
|
7
|
+
:description,
|
8
|
+
:detail,
|
9
|
+
:post_id,
|
10
|
+
:timeline_type
|
11
|
+
|
12
|
+
alias_method :created_at, :creation_date
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe Spec::Matchers::Sortedby do
|
4
|
+
before do
|
5
|
+
@questions = []
|
6
|
+
@questions << Stacked::Question.new(:last_edit_date => Time.now.to_i)
|
7
|
+
@questions << Stacked::Question.new(:last_edit_date => (Time.now + 5.days).to_i)
|
8
|
+
end
|
9
|
+
|
10
|
+
subject { @questions }
|
11
|
+
|
12
|
+
it "sorted by" do
|
13
|
+
subject.should be_sorted_by(:last_edit_date)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "sorted by reverse" do
|
17
|
+
subject.reverse.should be_sorted_by(:last_edit_date, :desc)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "fails with an understandable error message" do
|
21
|
+
lambda { subject.reverse.should be_sorted_by(:last_edit_date, :asc) }.should raise_error("Expected result set to be sorted by last_edit_date in ascending order, but was not.")
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
require 'stacked'
|
4
|
+
require 'spec'
|
5
|
+
require 'spec/autorun'
|
6
|
+
require 'fakeweb'
|
7
|
+
|
8
|
+
Dir["spec/support/**/*.rb"].each { |f| require f }
|
9
|
+
|
10
|
+
# Uncomment only for debugging as we only ever want to test against the real API.
|
11
|
+
# At least, until it becomes stable.
|
12
|
+
# FakeWeb.allow_net_connect = false
|
13
|
+
|
14
|
+
Spec::Runner.configure do |config|
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Stacked::Answer do
|
4
|
+
context "class methods" do
|
5
|
+
it "raises an error if all is called" do
|
6
|
+
lambda { Stacked::Answer.all }.should raise_error(Stacked::NotImplemented, "The requested action is not available in the API.")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
context "instance methods" do
|
11
|
+
subject { Stacked::Answer.find(1237127, :body => true) }
|
12
|
+
it "finds the user for an answer" do
|
13
|
+
subject.user.display_name.should eql("Daniel Vandersluis")
|
14
|
+
end
|
15
|
+
|
16
|
+
it "finds the question for an answer" do
|
17
|
+
subject.question.should be_is_a(Stacked::Question)
|
18
|
+
end
|
19
|
+
|
20
|
+
aliases(:views => :view_count,
|
21
|
+
:up_votes => :up_vote_count,
|
22
|
+
:answer_id => :id,
|
23
|
+
:created_at => :creation_date,
|
24
|
+
:updated_at => :last_edit_date)
|
25
|
+
|
26
|
+
it "has a body" do
|
27
|
+
subject.body.should_not be_blank
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Stacked::Badge do
|
4
|
+
subject { Stacked::Badge }
|
5
|
+
it "finds all badges" do
|
6
|
+
subject.all.first.should be_is_a(Stacked::Badge)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "finds all badges ordered by name" do
|
10
|
+
subject.name.first.should be_is_a(Stacked::Badge)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "finds all badges based on tags" do
|
14
|
+
subject.tags.first.name.should eql(".net")
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Stacked::Base do
|
4
|
+
context "common methods" do
|
5
|
+
# We cannot use Stacked::Base here obviously because SO does not have Bases!
|
6
|
+
# So we use User instead.
|
7
|
+
subject { Stacked::User }
|
8
|
+
|
9
|
+
it "retrieves a list of a resource" do
|
10
|
+
subject.all.all? { |u| u.is_a?(subject) }.should be_true
|
11
|
+
end
|
12
|
+
|
13
|
+
it "paginates through the resource" do
|
14
|
+
subject.all.first.should_not eql(subject.all(:page => 2).first)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "limits the results" do
|
18
|
+
subject.all(:pagesize => 1).size.should eql(1)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "stats" do
|
22
|
+
Stacked::Base.stats.keys.sort.should eql(["answers_per_minute", "api_version", "badges_per_minute", "questions_per_minute", "total_answers", "total_badges", "total_comments", "total_questions", "total_unanswered", "total_users", "total_votes"])
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Stacked::Comment do
|
4
|
+
subject { Stacked::Comment }
|
5
|
+
|
6
|
+
context "class methods" do
|
7
|
+
|
8
|
+
it "raises an error if all is called" do
|
9
|
+
lambda { Stacked::Comment.all }.should raise_error(Stacked::NotImplemented, "The requested action is not available in the API.")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "finds a single comment" do
|
13
|
+
comment = Stacked::Comment.find(2561833)
|
14
|
+
comment.should be_is_a(Stacked::Comment)
|
15
|
+
comment.owner_user_id.should eql(22656)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "instance methods" do
|
20
|
+
subject { Stacked::Comment.find(2561833) }
|
21
|
+
|
22
|
+
aliases(:comment_id => :id,
|
23
|
+
:created_at => :creation_date,
|
24
|
+
:owner => :user,
|
25
|
+
:edits => :edit_count)
|
26
|
+
|
27
|
+
it "finds the related post for this comment" do
|
28
|
+
subject.post.should be_is_a(Stacked::Answer)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "finds who the comment was directed at, or nobody if nobody" do
|
32
|
+
Stacked::Comment.find(2561833).reply_to.should be_is_a(Stacked::User)
|
33
|
+
Stacked::Comment.find(1063043).reply_to.should be_nil
|
34
|
+
end
|
35
|
+
|
36
|
+
it "finds the user who wrote the comment" do
|
37
|
+
subject.owner.should be_is_a(Stacked::User)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Stacked::Question do
|
4
|
+
context "class methods" do
|
5
|
+
subject { Stacked::Question }
|
6
|
+
it "gets a list of all questions" do
|
7
|
+
subject.all.all? { |q| q.is_a?(subject) }.should be_true
|
8
|
+
end
|
9
|
+
|
10
|
+
it "gets a list of questions with comments" do
|
11
|
+
pending("Cannot currently get a list of questions with comments")
|
12
|
+
subject.all(:comments => true)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "active" do
|
16
|
+
subject.active(:pagesize => 1).first.last_activity_date.should be_within(1.day)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "newest" do
|
20
|
+
subject.newest(:pagesize => 1).first.creation_date.should be_within(1.day)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "featured" do
|
24
|
+
(subject.featured(:pagesize => 1).first.bounty_closes_date > Time.now.to_i).should be_true
|
25
|
+
end
|
26
|
+
|
27
|
+
it "hot" do
|
28
|
+
# It was 3555 as of 3rd April 2010.
|
29
|
+
(subject.hot(:pagesize => 1).first.view_count > 3555).should be_true
|
30
|
+
end
|
31
|
+
|
32
|
+
it "month" do
|
33
|
+
subject.month(:pagesize => 1).first.creation_date.should be_within(1.month)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "week" do
|
37
|
+
subject.week(:pagesize => 1).first.creation_date.should be_within(1.week)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "votes" do
|
41
|
+
subject.votes(:pagesize => 1).first.up_vote_count.should eql(1190)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "unanswered by votes" do
|
45
|
+
question = subject.unanswered_by_votes(:pagesize => 1).first
|
46
|
+
question.should be_is_a(Stacked::Question)
|
47
|
+
question.answers.should be_blank
|
48
|
+
end
|
49
|
+
|
50
|
+
it "tagged" do
|
51
|
+
question = subject.tagged(:tags => ["ruby", "ruby-on-rails"], :pagesize => 1).first
|
52
|
+
question.tags.map(&:name).should include("ruby")
|
53
|
+
question.tags.map(&:name).should include("ruby-on-rails")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "instance methods" do
|
58
|
+
subject { Stacked::Question.find(1236996, :comments => true, :body => true) }
|
59
|
+
|
60
|
+
aliases(
|
61
|
+
:created_at => :creation_date,
|
62
|
+
:down_votes => :down_vote_count,
|
63
|
+
:favorites => :favorite_count,
|
64
|
+
:favourites => :favorite_count,
|
65
|
+
:id => :question_id,
|
66
|
+
:updated_at => :last_edit_date,
|
67
|
+
:up_votes => :up_vote_count,
|
68
|
+
:user => :owner,
|
69
|
+
:views => :view_count
|
70
|
+
)
|
71
|
+
|
72
|
+
|
73
|
+
it "is the right question" do
|
74
|
+
subject.title.should eql("Calculating the distance between two times")
|
75
|
+
end
|
76
|
+
|
77
|
+
it "has a body" do
|
78
|
+
subject.body.should_not be_blank
|
79
|
+
end
|
80
|
+
|
81
|
+
it "retreives comments" do
|
82
|
+
subject.comments.should_not be_empty
|
83
|
+
subject.comments.first.should be_is_a(Stacked::Comment)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "retreives answers" do
|
87
|
+
subject.answers.should_not be_empty
|
88
|
+
subject.answers.first.should be_is_a(Stacked::Answer)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "retreives tags" do
|
92
|
+
subject.tags.should_not be_empty
|
93
|
+
subject.tags.first.should be_is_a(Stacked::Tag)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "finds the user for a question" do
|
97
|
+
subject.user.should be_is_a(Stacked::User)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "finds the accepted answer" do
|
101
|
+
subject.accepted_answer.should be_is_a(Stacked::Answer)
|
102
|
+
end
|
103
|
+
|
104
|
+
it "shows the timeline of the question" do
|
105
|
+
subject.timeline.first.should be_is_a(Stacked::Posttimeline)
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|