renshuu 0.1.0 → 1.0.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +5 -1
- data/CHANGELOG.md +15 -0
- data/README.md +123 -0
- data/lib/renshuu/models/grammar.rb +82 -0
- data/lib/renshuu/models/kanji.rb +80 -0
- data/lib/renshuu/models/list.rb +138 -0
- data/lib/renshuu/models/mixins/listable.rb +69 -0
- data/lib/renshuu/models/mixins/schedulable.rb +69 -0
- data/lib/renshuu/models/model.rb +2 -8
- data/lib/renshuu/models/presence.rb +66 -0
- data/lib/renshuu/models/profile.rb +158 -0
- data/lib/renshuu/models/schedule.rb +208 -0
- data/lib/renshuu/models/sentence.rb +56 -0
- data/lib/renshuu/models/types.rb +26 -0
- data/lib/renshuu/models/user_data.rb +53 -0
- data/lib/renshuu/models/word.rb +90 -0
- data/lib/renshuu/models.rb +17 -1
- data/lib/renshuu/version.rb +1 -1
- data/lib/renshuu.rb +1 -1
- metadata +18 -8
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Renshuu
|
|
4
|
+
##
|
|
5
|
+
# Model class for term presence.
|
|
6
|
+
class Presence < Model
|
|
7
|
+
##
|
|
8
|
+
# Model class for schedule presence.
|
|
9
|
+
class Schedule < Model
|
|
10
|
+
##
|
|
11
|
+
# @!attribute [r] sched_id
|
|
12
|
+
# @return [String]
|
|
13
|
+
attribute :sched_id, Types::String
|
|
14
|
+
alias schedule_id sched_id
|
|
15
|
+
##
|
|
16
|
+
# @!attribute [r] name
|
|
17
|
+
# @return [String]
|
|
18
|
+
attribute :name, Types::String
|
|
19
|
+
##
|
|
20
|
+
# @!attribute [r] has_word
|
|
21
|
+
# @return [Boolean]
|
|
22
|
+
attribute :has_word, Types::Params::Bool
|
|
23
|
+
alias has_word? has_word
|
|
24
|
+
|
|
25
|
+
##
|
|
26
|
+
# Retrieves the schedule associated with this presence item.
|
|
27
|
+
#
|
|
28
|
+
# @return [Renshuu::Schedule]
|
|
29
|
+
#
|
|
30
|
+
# @see Renshuu::Schedule.get
|
|
31
|
+
def schedule
|
|
32
|
+
Renshuu::Schedule.get(schedule_id)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
##
|
|
36
|
+
# @!attribute [r] scheds
|
|
37
|
+
# @return [Array<Schedule>]
|
|
38
|
+
attribute(:scheds, Types::Array.of(Schedule).default { [] })
|
|
39
|
+
alias schedules scheds
|
|
40
|
+
|
|
41
|
+
##
|
|
42
|
+
# Model class for list presence.
|
|
43
|
+
class List < Model
|
|
44
|
+
##
|
|
45
|
+
# @!attribute [r] list_id
|
|
46
|
+
# @return [String]
|
|
47
|
+
attribute :list_id, Types::String
|
|
48
|
+
##
|
|
49
|
+
# @!attribute [r] name
|
|
50
|
+
# @return [String]
|
|
51
|
+
attribute :name, Types::String
|
|
52
|
+
##
|
|
53
|
+
# @!attribute [r] set_name
|
|
54
|
+
# @return [String, nil]
|
|
55
|
+
attribute? :set_name, Types::String
|
|
56
|
+
##
|
|
57
|
+
# @!attribute [r] has_word
|
|
58
|
+
# @return [Boolean]
|
|
59
|
+
attribute :has_word, Types::Params::Bool
|
|
60
|
+
end
|
|
61
|
+
##
|
|
62
|
+
# @!attribute [r] lists
|
|
63
|
+
# @return [Array<List>]
|
|
64
|
+
attribute(:lists, Types::Array.of(List).default { [] })
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -12,5 +12,163 @@ module Renshuu
|
|
|
12
12
|
body = Renshuu.client.query(:get, 'v1/profile')
|
|
13
13
|
new(body)
|
|
14
14
|
end
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
# @!attribute [r] id
|
|
18
|
+
# @return [String]
|
|
19
|
+
attribute :id, Types::String
|
|
20
|
+
##
|
|
21
|
+
# @!attribute [r] real_name
|
|
22
|
+
# @return [String]
|
|
23
|
+
attribute :real_name, Types::String
|
|
24
|
+
##
|
|
25
|
+
# @!attribute [r] adventure_level
|
|
26
|
+
# @return [String]
|
|
27
|
+
attribute :adventure_level, Types::String
|
|
28
|
+
##
|
|
29
|
+
# @!attribute [r] user_length
|
|
30
|
+
# @return [String]
|
|
31
|
+
attribute :user_length, Types::String
|
|
32
|
+
##
|
|
33
|
+
# @!attribute [r] kao
|
|
34
|
+
# @return [URI]
|
|
35
|
+
attribute :kao, Types::URI
|
|
36
|
+
|
|
37
|
+
##
|
|
38
|
+
# Model class for user study counts.
|
|
39
|
+
class StudyCount < Model
|
|
40
|
+
##
|
|
41
|
+
# @!attribute [r] today_all
|
|
42
|
+
# @return [Integer]
|
|
43
|
+
attribute :today_all, Types::Integer
|
|
44
|
+
##
|
|
45
|
+
# @!attribute [r] today_grammar
|
|
46
|
+
# @return [Integer]
|
|
47
|
+
attribute :today_grammar, Types::Integer
|
|
48
|
+
##
|
|
49
|
+
# @!attribute [r] today_vocab
|
|
50
|
+
# @return [Integer]
|
|
51
|
+
attribute :today_vocab, Types::Integer
|
|
52
|
+
##
|
|
53
|
+
# @!attribute [r] today_kanji
|
|
54
|
+
# @return [Integer]
|
|
55
|
+
attribute :today_kanji, Types::Integer
|
|
56
|
+
##
|
|
57
|
+
# @!attribute [r] today_sent
|
|
58
|
+
# @return [Integer]
|
|
59
|
+
attribute :today_sent, Types::Integer
|
|
60
|
+
##
|
|
61
|
+
# @!attribute [r] today_aconj
|
|
62
|
+
# @return [Integer]
|
|
63
|
+
attribute :today_aconj, Types::Integer
|
|
64
|
+
##
|
|
65
|
+
# @!attribute [r] today_conj
|
|
66
|
+
# @return [Integer]
|
|
67
|
+
attribute :today_conj, Types::Integer
|
|
68
|
+
##
|
|
69
|
+
# @!attribute [r] total
|
|
70
|
+
# @return [Integer]
|
|
71
|
+
attribute :total, Types::Integer
|
|
72
|
+
##
|
|
73
|
+
# @!attribute [r] total_vocab
|
|
74
|
+
# @return [Integer]
|
|
75
|
+
attribute :total_vocab, Types::Integer
|
|
76
|
+
##
|
|
77
|
+
# @!attribute [r] total_kanji
|
|
78
|
+
# @return [Integer]
|
|
79
|
+
attribute :total_kanji, Types::Integer
|
|
80
|
+
##
|
|
81
|
+
# @!attribute [r] total_grammar
|
|
82
|
+
# @return [Integer]
|
|
83
|
+
attribute :total_grammar, Types::Integer
|
|
84
|
+
##
|
|
85
|
+
# @!attribute [r] total_sent
|
|
86
|
+
# @return [Integer]
|
|
87
|
+
attribute :total_sent, Types::Integer
|
|
88
|
+
end
|
|
89
|
+
##
|
|
90
|
+
# @!attribute [r] studied
|
|
91
|
+
# @return [StudyCount]
|
|
92
|
+
attribute :studied, StudyCount
|
|
93
|
+
alias study_count studied
|
|
94
|
+
|
|
95
|
+
##
|
|
96
|
+
# Model class for profile JLPT progress.
|
|
97
|
+
class Progress < Model
|
|
98
|
+
##
|
|
99
|
+
# @!attribute [r] n1
|
|
100
|
+
# @return [Integer]
|
|
101
|
+
attribute :n1, Types::Integer
|
|
102
|
+
##
|
|
103
|
+
# @!attribute [r] n2
|
|
104
|
+
# @return [Integer]
|
|
105
|
+
attribute :n2, Types::Integer
|
|
106
|
+
##
|
|
107
|
+
# @!attribute [r] n3
|
|
108
|
+
# @return [Integer]
|
|
109
|
+
attribute :n3, Types::Integer
|
|
110
|
+
##
|
|
111
|
+
# @!attribute [r] n4
|
|
112
|
+
# @return [Integer]
|
|
113
|
+
attribute :n4, Types::Integer
|
|
114
|
+
##
|
|
115
|
+
# @!attribute [r] n5
|
|
116
|
+
# @return [Integer]
|
|
117
|
+
attribute :n5, Types::Integer
|
|
118
|
+
end
|
|
119
|
+
##
|
|
120
|
+
# @!attribute [r] level_progress_percs
|
|
121
|
+
# @return [Hash{String => Progress}]
|
|
122
|
+
attribute :level_progress_percs, Types::Hash.map(Types::String, Progress)
|
|
123
|
+
|
|
124
|
+
##
|
|
125
|
+
# Model class for profile study streaks.
|
|
126
|
+
class Streak < Model
|
|
127
|
+
##
|
|
128
|
+
# @!attribute [r] correct_in_a_row
|
|
129
|
+
# @return [Integer]
|
|
130
|
+
attribute :correct_in_a_row, Types::Integer
|
|
131
|
+
##
|
|
132
|
+
# @!attribute [r] correct_in_a_row_alltime
|
|
133
|
+
# @return [Integer]
|
|
134
|
+
attribute :correct_in_a_row_alltime, Types::Integer
|
|
135
|
+
##
|
|
136
|
+
# @!attribute [r] days_studied_in_a_row
|
|
137
|
+
# @return [Integer]
|
|
138
|
+
attribute :days_studied_in_a_row, Types::Integer
|
|
139
|
+
##
|
|
140
|
+
# @!attribute [r] days_studied_in_a_row_alltime
|
|
141
|
+
# @return [Integer]
|
|
142
|
+
attribute :days_studied_in_a_row_alltime, Types::Integer
|
|
143
|
+
end
|
|
144
|
+
##
|
|
145
|
+
# @!attribute [r] streaks
|
|
146
|
+
# @return [Hash{String => Streak}]
|
|
147
|
+
attribute :streaks, Types::Hash.map(Types::String, Streak)
|
|
148
|
+
|
|
149
|
+
##
|
|
150
|
+
# Model class for profile API usage.
|
|
151
|
+
class APIUsage < Model
|
|
152
|
+
##
|
|
153
|
+
# @!attribute [r] calls_today
|
|
154
|
+
# @return [Integer]
|
|
155
|
+
attribute :calls_today, Types::Integer
|
|
156
|
+
##
|
|
157
|
+
# @!attribute [r] daily_allowance
|
|
158
|
+
# @return [Integer]
|
|
159
|
+
attribute :daily_allowance, Types::Integer
|
|
160
|
+
|
|
161
|
+
##
|
|
162
|
+
# Number of API calls remaining in today's quota.
|
|
163
|
+
#
|
|
164
|
+
# @return [Integer]
|
|
165
|
+
def remaining_today
|
|
166
|
+
daily_allowance - calls_today
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
##
|
|
170
|
+
# @!attribute [r] api_usage
|
|
171
|
+
# @return [APIUsage]
|
|
172
|
+
attribute :api_usage, APIUsage
|
|
15
173
|
end
|
|
16
174
|
end
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Renshuu
|
|
4
|
+
##
|
|
5
|
+
# Model class for schedules.
|
|
6
|
+
#
|
|
7
|
+
# @see https://api.renshuu.org/docs/#/Schedules
|
|
8
|
+
class Schedule < Model
|
|
9
|
+
##
|
|
10
|
+
# Mapping between schedule booktypes and model classes.
|
|
11
|
+
#
|
|
12
|
+
# @see #term_class
|
|
13
|
+
BOOKTYPES = {
|
|
14
|
+
'kanji' => Kanji, 'vocab' => Word, 'grammar' => Grammar,
|
|
15
|
+
'sent' => Sentence
|
|
16
|
+
}.freeze
|
|
17
|
+
|
|
18
|
+
##
|
|
19
|
+
# Lists all schedules of the current user.
|
|
20
|
+
#
|
|
21
|
+
# @return [Array<Schedule>]
|
|
22
|
+
#
|
|
23
|
+
# @see https://api.renshuu.org/docs/#/Schedules/get_schedule
|
|
24
|
+
def self.list
|
|
25
|
+
body = Renshuu.client.query(:get, 'v1/schedule')
|
|
26
|
+
|
|
27
|
+
body.fetch(:schedules).map { new(_1) }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
##
|
|
31
|
+
# Retrieves a specific schedule from the API.
|
|
32
|
+
#
|
|
33
|
+
# @param [String, Integer] id
|
|
34
|
+
# @return [Schedule]
|
|
35
|
+
#
|
|
36
|
+
# @see https://api.renshuu.org/docs/#/Schedules/get_schedule__id_
|
|
37
|
+
def self.get(id)
|
|
38
|
+
body = Renshuu.client.query(:get, "v1/schedule/#{id}")
|
|
39
|
+
|
|
40
|
+
body.fetch(:schedules).first.then { new(_1) }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
##
|
|
44
|
+
# @!attribute [r] id
|
|
45
|
+
# @return [String]
|
|
46
|
+
attribute :id, Types::String
|
|
47
|
+
##
|
|
48
|
+
# @!attribute [r] name
|
|
49
|
+
# @return [String]
|
|
50
|
+
attribute :name, Types::String
|
|
51
|
+
##
|
|
52
|
+
# @!attribute [r] booktype
|
|
53
|
+
# @return [String]
|
|
54
|
+
attribute :booktype, Types::String
|
|
55
|
+
##
|
|
56
|
+
# @!attribute [r] is_frozen
|
|
57
|
+
# @return [Boolean]
|
|
58
|
+
attribute :is_frozen, Types::Params::Bool
|
|
59
|
+
|
|
60
|
+
##
|
|
61
|
+
# Model class for schedules today counts.
|
|
62
|
+
class TodayCount < Model
|
|
63
|
+
transform_keys do |key|
|
|
64
|
+
key == :new ? :new_terms : key
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
##
|
|
68
|
+
# @!attribute [r] review
|
|
69
|
+
# @return [Integer]
|
|
70
|
+
attribute :review, Types::Integer
|
|
71
|
+
##
|
|
72
|
+
# @!attribute [r] new_terms
|
|
73
|
+
# @note +new+ is a reserved keyword, so we have to circumvent that.
|
|
74
|
+
# @return [Integer]
|
|
75
|
+
attribute :new_terms, Types::Integer
|
|
76
|
+
end
|
|
77
|
+
##
|
|
78
|
+
# @!attribute [r] today
|
|
79
|
+
# rn [TodayCount]
|
|
80
|
+
attribute :today, TodayCount
|
|
81
|
+
|
|
82
|
+
##
|
|
83
|
+
# Model class for schedule upcoming counts.
|
|
84
|
+
class UpcomingCount < Model
|
|
85
|
+
##
|
|
86
|
+
# @!attribute [r] days_in_future
|
|
87
|
+
# @return [Integer]
|
|
88
|
+
attribute :days_in_future, Types::Integer
|
|
89
|
+
##
|
|
90
|
+
# @!attribute [r] terms_to_review
|
|
91
|
+
# @return [Integer]
|
|
92
|
+
attribute :terms_to_review, Types::Integer
|
|
93
|
+
end
|
|
94
|
+
##
|
|
95
|
+
# @!attribute [r] upcoming
|
|
96
|
+
# @return [Array<UpcomingCount>]
|
|
97
|
+
attribute :upcoming, Types::Array.of(UpcomingCount)
|
|
98
|
+
|
|
99
|
+
##
|
|
100
|
+
# Model class for schedule term counts.
|
|
101
|
+
class TermCount < Model
|
|
102
|
+
##
|
|
103
|
+
# @!attribute [r] total_count
|
|
104
|
+
# @return [Integer]
|
|
105
|
+
attribute :total_count, Types::Integer
|
|
106
|
+
##
|
|
107
|
+
# @!attribute [r] studied_count
|
|
108
|
+
# @return [Integer]
|
|
109
|
+
attribute :studied_count, Types::Integer
|
|
110
|
+
##
|
|
111
|
+
# @!attribute [r] unstudied_count
|
|
112
|
+
# @return [Integer]
|
|
113
|
+
attribute :unstudied_count, Types::Integer
|
|
114
|
+
##
|
|
115
|
+
# @!attribute [r] hidden_count
|
|
116
|
+
# @return [Integer]
|
|
117
|
+
attribute :hidden_count, Types::Integer
|
|
118
|
+
end
|
|
119
|
+
##
|
|
120
|
+
# @!attribute [r] terms
|
|
121
|
+
# @return [TermCount]
|
|
122
|
+
attribute :terms, TermCount
|
|
123
|
+
|
|
124
|
+
##
|
|
125
|
+
# Model class for schedule new term counts.
|
|
126
|
+
class NewTermCount < Model
|
|
127
|
+
##
|
|
128
|
+
# @!attribute [r] today_count
|
|
129
|
+
# @return [Integer]
|
|
130
|
+
attribute :today_count, Types::Integer
|
|
131
|
+
##
|
|
132
|
+
# @!attribute [r] rolling_week_count
|
|
133
|
+
# @return [Integer]
|
|
134
|
+
attribute :rolling_week_count, Types::Integer
|
|
135
|
+
end
|
|
136
|
+
##
|
|
137
|
+
# @!attribute [r] new_terms
|
|
138
|
+
# @return [NewTermCount]
|
|
139
|
+
attribute :new_terms, NewTermCount
|
|
140
|
+
|
|
141
|
+
##
|
|
142
|
+
# Retrieves the terms contained in the schedule.
|
|
143
|
+
#
|
|
144
|
+
# @param [Integer, nil] page
|
|
145
|
+
# @param [Symbol, nil] group One of +:all+, +:blocked+, +:studied+,
|
|
146
|
+
# +:notyetstudied+, +:cannot_study+, +:review_today+, +:mastery_1+,
|
|
147
|
+
# +:mastery_2+, +:mastery_3+, +:mastery_4+, +:mastery_5+, +:mastery_6+,
|
|
148
|
+
# +:mastery_7+, +:mastery_8+ or +:mastery_9+.
|
|
149
|
+
#
|
|
150
|
+
# @return [Array<Kanji,Word,Grammar,Sentence>] Depending on the type of
|
|
151
|
+
# schedule
|
|
152
|
+
def contents(page: nil, group: nil)
|
|
153
|
+
params = { pg: page, group: }.compact
|
|
154
|
+
body = Renshuu.client.query(:get, "v1/schedule/#{id}/list", params:)
|
|
155
|
+
|
|
156
|
+
body.dig(:contents, :terms).map { term_class.new(_1) }
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
##
|
|
160
|
+
# Adds the given item to the schedule.
|
|
161
|
+
#
|
|
162
|
+
# @param [Schedulable] item
|
|
163
|
+
#
|
|
164
|
+
# @return [Void]
|
|
165
|
+
# @raise [ArgumentError] If the type of the item does not match the
|
|
166
|
+
# schedule's type
|
|
167
|
+
#
|
|
168
|
+
# @see Schedulable#add_to_schedule
|
|
169
|
+
def add(item)
|
|
170
|
+
unless item.is_a?(term_class)
|
|
171
|
+
raise ArgumentError, "Expected a `#{term_class}`, got a `#{item.class}`"
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
item.add_to_schedule(self)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
##
|
|
178
|
+
# Removes the given item from the schedule.
|
|
179
|
+
#
|
|
180
|
+
# @param [Schedulable] item
|
|
181
|
+
#
|
|
182
|
+
# @return [Void]
|
|
183
|
+
# @raise [ArgumentError] If the type of the item does not match the
|
|
184
|
+
# schedule's type
|
|
185
|
+
#
|
|
186
|
+
# @see Schedulable#remove_from_schedule
|
|
187
|
+
def remove(item)
|
|
188
|
+
unless item.is_a?(term_class)
|
|
189
|
+
raise ArgumentError, "Expected a `#{term_class}`, got a `#{item.class}`"
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
item.remove_from_schedule(self)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
##
|
|
196
|
+
# Model class to use for this schedule's terms.
|
|
197
|
+
#
|
|
198
|
+
# @return [Class]
|
|
199
|
+
# @raise [KeyError]
|
|
200
|
+
#
|
|
201
|
+
# @see ::BOOKTYPES
|
|
202
|
+
def term_class
|
|
203
|
+
@term_class ||= BOOKTYPES.fetch(booktype) do |key|
|
|
204
|
+
raise KeyError, "Unkown schedule type `#{key}`"
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Renshuu
|
|
4
|
+
##
|
|
5
|
+
# Model class for sentences.
|
|
6
|
+
#
|
|
7
|
+
# @see https://api.renshuu.org/docs/#/Sentence
|
|
8
|
+
class Sentence < Model
|
|
9
|
+
##
|
|
10
|
+
# Searches sentences in Renshuu's dictionary.
|
|
11
|
+
#
|
|
12
|
+
# @param [String] value
|
|
13
|
+
#
|
|
14
|
+
# @return [Array<Sentence>]
|
|
15
|
+
#
|
|
16
|
+
# @see https://api.renshuu.org/docs/#/Sentence/get_reibun_search
|
|
17
|
+
def self.search(value)
|
|
18
|
+
Renshuu.client.query(:get, 'v1/reibun/search', params: { value: })
|
|
19
|
+
.fetch(:reibuns).map { new(_1) }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
# Retrieves sentences from Renshuu's dictionary for a specific word.
|
|
24
|
+
#
|
|
25
|
+
# @param [Word, Integer] word
|
|
26
|
+
#
|
|
27
|
+
# @return [Array<Sentence>]
|
|
28
|
+
#
|
|
29
|
+
# @see https://api.renshuu.org/docs/#/Sentence/get_reibun_search__word_id_
|
|
30
|
+
def self.word_search(word)
|
|
31
|
+
identifier = case word
|
|
32
|
+
when Integer then word
|
|
33
|
+
else word.id
|
|
34
|
+
end
|
|
35
|
+
Renshuu.client.query(:get, "v1/reibun/search/#{identifier}")
|
|
36
|
+
.fetch(:reibuns).map { new(_1) }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
##
|
|
40
|
+
# @!attribute [r] id
|
|
41
|
+
# @return [String]
|
|
42
|
+
attribute :id, Types::String
|
|
43
|
+
##
|
|
44
|
+
# @!attribute [r] japanese
|
|
45
|
+
# @return [String]
|
|
46
|
+
attribute :japanese, Types::String
|
|
47
|
+
##
|
|
48
|
+
# @!attribute [r] hiragana
|
|
49
|
+
# @return [String, nil]
|
|
50
|
+
attribute? :hiragana, Types::String
|
|
51
|
+
##
|
|
52
|
+
# @!attribute [r] meaning
|
|
53
|
+
# @return [Hash{String => String}]
|
|
54
|
+
attribute :meaning, Types::Hash.map(Types::String, Types::String)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Renshuu
|
|
4
|
+
##
|
|
5
|
+
# Module for type values.
|
|
6
|
+
module Types
|
|
7
|
+
include Dry.Types(default: :coercible)
|
|
8
|
+
|
|
9
|
+
##
|
|
10
|
+
# Dry type for dates.
|
|
11
|
+
Date = Constructor(::Date) do |date|
|
|
12
|
+
case date
|
|
13
|
+
when ::Date then date
|
|
14
|
+
when 'Not yet' then nil
|
|
15
|
+
when 'Now' then ::Date.today
|
|
16
|
+
else ::Date.parse(date)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
##
|
|
21
|
+
# Dry type for URIs.
|
|
22
|
+
URI = Constructor(URI) do |uri|
|
|
23
|
+
::URI.parse(uri)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Renshuu
|
|
4
|
+
##
|
|
5
|
+
# Model class for user data.
|
|
6
|
+
class UserData < Model
|
|
7
|
+
##
|
|
8
|
+
# @!attribute [r] correct_count
|
|
9
|
+
# @return [Integer]
|
|
10
|
+
attribute :correct_count, Types::Integer
|
|
11
|
+
##
|
|
12
|
+
# @!attribute [r] missed_count
|
|
13
|
+
# @return [Integer]
|
|
14
|
+
attribute :missed_count, Types::Integer
|
|
15
|
+
##
|
|
16
|
+
# @!attribute [r] mastery_avg_perc
|
|
17
|
+
# @return [Integer]
|
|
18
|
+
attribute :mastery_avg_perc, Types::Integer.fallback(0)
|
|
19
|
+
|
|
20
|
+
##
|
|
21
|
+
# Model class for user data study vectors.
|
|
22
|
+
class StudyVector < Model
|
|
23
|
+
##
|
|
24
|
+
# @!attribute [r] name
|
|
25
|
+
# @return [String]
|
|
26
|
+
attribute :name, Types::String
|
|
27
|
+
##
|
|
28
|
+
# @!attribute [r] correct_count
|
|
29
|
+
# @return [Integer]
|
|
30
|
+
attribute :correct_count, Types::Integer
|
|
31
|
+
##
|
|
32
|
+
# @!attribute [r] missed_count
|
|
33
|
+
# @return [Integer]
|
|
34
|
+
attribute :missed_count, Types::Integer
|
|
35
|
+
##
|
|
36
|
+
# @!attribute [r] mastery_perc
|
|
37
|
+
# @return [Integer]
|
|
38
|
+
attribute :mastery_perc, Types::Integer
|
|
39
|
+
##
|
|
40
|
+
# @!attribute [r] last_quizzed
|
|
41
|
+
# @return [Date]
|
|
42
|
+
attribute :last_quizzed, Types::Date
|
|
43
|
+
##
|
|
44
|
+
# @!attribute [r] next_quiz
|
|
45
|
+
# @return [Date]
|
|
46
|
+
attribute :next_quiz, Types::Date
|
|
47
|
+
end
|
|
48
|
+
##
|
|
49
|
+
# @!attribute [r] study_vectors
|
|
50
|
+
# @return [Hash{String => StudyVector}]
|
|
51
|
+
attribute? :study_vectors, Types::Hash.map(Types::String, StudyVector)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Renshuu
|
|
4
|
+
##
|
|
5
|
+
# Model class for words and vocabulary.
|
|
6
|
+
#
|
|
7
|
+
# @see https://api.renshuu.org/docs/#/Vocabulary
|
|
8
|
+
class Word < Model
|
|
9
|
+
include Schedulable
|
|
10
|
+
include Listable
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
# Searches the Renshuu vocabulary dictionary.
|
|
14
|
+
#
|
|
15
|
+
# @param [String] value
|
|
16
|
+
#
|
|
17
|
+
# @return [Array<Word>]
|
|
18
|
+
def self.search(value)
|
|
19
|
+
body = Renshuu.client.query(:get, 'v1/word/search', params: { value: })
|
|
20
|
+
|
|
21
|
+
body.fetch(:words).map { new(_1) }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
##
|
|
25
|
+
# Retrieves a word from the dictionary by its identifier.
|
|
26
|
+
#
|
|
27
|
+
# @param [Integer] id
|
|
28
|
+
#
|
|
29
|
+
# @return [Word]
|
|
30
|
+
def self.get(id)
|
|
31
|
+
body = Renshuu.client.query(:get, "v1/word/#{id}")
|
|
32
|
+
|
|
33
|
+
body.fetch(:words).first.then { new(_1) }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
##
|
|
37
|
+
# @!attribute [r] id
|
|
38
|
+
# @return [String]
|
|
39
|
+
attribute :id, Types::String
|
|
40
|
+
##
|
|
41
|
+
# @!attribute [r] kanji_full
|
|
42
|
+
# @return [String]
|
|
43
|
+
attribute :kanji_full, Types::String
|
|
44
|
+
##
|
|
45
|
+
# @!attribute [r] hiragana_full
|
|
46
|
+
# @return [String]
|
|
47
|
+
attribute :hiragana_full, Types::String
|
|
48
|
+
##
|
|
49
|
+
# @!attribute [r] pic
|
|
50
|
+
# @return [Array<URI>]
|
|
51
|
+
attribute(:pic, Types::Array.of(Types::URI).default { [] })
|
|
52
|
+
alias pictures pic
|
|
53
|
+
##
|
|
54
|
+
# @!attribute [r] markers
|
|
55
|
+
# @return [Array<String>]
|
|
56
|
+
attribute(:markers, Types::Array.of(Types::String).default { [] })
|
|
57
|
+
##
|
|
58
|
+
# @!attribute [r] pitch
|
|
59
|
+
# @return [Array<String>]
|
|
60
|
+
attribute :pitch, Types::Array.of(Types::String)
|
|
61
|
+
##
|
|
62
|
+
# @!attribute [r] typeofspeech
|
|
63
|
+
# @return [String]
|
|
64
|
+
attribute :typeofspeech, Types::String
|
|
65
|
+
alias type_of_speech typeofspeech
|
|
66
|
+
##
|
|
67
|
+
# @!attribute [r] def
|
|
68
|
+
# @return [Array<String>]
|
|
69
|
+
attribute :def, Types::Array.of(Types::String)
|
|
70
|
+
|
|
71
|
+
##
|
|
72
|
+
# @!attribute [r] user_data
|
|
73
|
+
# @return [UserData, nil]
|
|
74
|
+
attribute? :user_data, UserData
|
|
75
|
+
##
|
|
76
|
+
# @!attribute [r] presence
|
|
77
|
+
# @return [Presence, nil]
|
|
78
|
+
attribute? :presence, Presence
|
|
79
|
+
|
|
80
|
+
##
|
|
81
|
+
# Retrieves sentences using this word from the dictionary.
|
|
82
|
+
#
|
|
83
|
+
# @return [Array<Sentence>]
|
|
84
|
+
#
|
|
85
|
+
# @see Sentence.word_search
|
|
86
|
+
def sentences
|
|
87
|
+
Sentence.word_search(self)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
data/lib/renshuu/models.rb
CHANGED
|
@@ -3,9 +3,25 @@
|
|
|
3
3
|
module Renshuu # rubocop:disable Style/Documentation
|
|
4
4
|
end
|
|
5
5
|
|
|
6
|
+
# Types
|
|
7
|
+
require_relative 'models/types'
|
|
8
|
+
|
|
9
|
+
# Mixins
|
|
10
|
+
require_relative 'models/mixins/listable'
|
|
11
|
+
require_relative 'models/mixins/schedulable'
|
|
12
|
+
|
|
6
13
|
# Base class
|
|
7
14
|
require_relative 'models/model'
|
|
8
15
|
|
|
9
|
-
# Other models
|
|
16
|
+
# Other models (respect blank lines for dependency order)
|
|
17
|
+
require_relative 'models/presence'
|
|
18
|
+
require_relative 'models/user_data'
|
|
19
|
+
|
|
20
|
+
require_relative 'models/grammar'
|
|
10
21
|
require_relative 'models/kanji'
|
|
11
22
|
require_relative 'models/profile'
|
|
23
|
+
require_relative 'models/sentence'
|
|
24
|
+
require_relative 'models/word'
|
|
25
|
+
|
|
26
|
+
require_relative 'models/list'
|
|
27
|
+
require_relative 'models/schedule'
|
data/lib/renshuu/version.rb
CHANGED