duolingo_personal_data 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rubocop.yml +20 -0
- data/.rubocop_todo.yml +50 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +202 -0
- data/README.md +38 -0
- data/Rakefile +22 -0
- data/duolingo_personal_data.gemspec +26 -0
- data/fixtures/TeacherPrivacySettings.csv +2 -0
- data/fixtures/auth_data.csv +6 -0
- data/fixtures/avatar_images.csv +13 -0
- data/fixtures/duolingo-blast-emails.csv +17 -0
- data/fixtures/duolingo-notify-data.csv +4 -0
- data/fixtures/friends-follow.csv +2 -0
- data/fixtures/inventory.csv +5 -0
- data/fixtures/languages.csv +4 -0
- data/fixtures/leaderboards.csv +4 -0
- data/fixtures/profile.csv +13 -0
- data/fixtures/stories-story-completions.csv +4 -0
- data/fixtures/stories.csv +2 -0
- data/lib/duolingo_personal_data/auth_data.rb +39 -0
- data/lib/duolingo_personal_data/avatar_images.rb +24 -0
- data/lib/duolingo_personal_data/blast_emails.rb +84 -0
- data/lib/duolingo_personal_data/friends_follow.rb +47 -0
- data/lib/duolingo_personal_data/inventory.rb +48 -0
- data/lib/duolingo_personal_data/languages.rb +42 -0
- data/lib/duolingo_personal_data/leaderboards.rb +24 -0
- data/lib/duolingo_personal_data/notify_data.rb +33 -0
- data/lib/duolingo_personal_data/profile.rb +67 -0
- data/lib/duolingo_personal_data/stories.rb +29 -0
- data/lib/duolingo_personal_data/story_completions.rb +23 -0
- data/lib/duolingo_personal_data/teacher_privacy_settings.rb +51 -0
- data/lib/duolingo_personal_data/version.rb +3 -0
- data/lib/duolingo_personal_data.rb +17 -0
- data/manifest.scm +3 -0
- data/sig/duolingo_personal_data.rbs +272 -0
- metadata +83 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
module DuolingoPersonalData
|
2
|
+
class FriendsFollow
|
3
|
+
def initialize(csv_path)
|
4
|
+
@csv_path = csv_path
|
5
|
+
end
|
6
|
+
|
7
|
+
def num_following
|
8
|
+
@num_following ||= integer_value_from_property("num_following")
|
9
|
+
end
|
10
|
+
|
11
|
+
def num_followers
|
12
|
+
@num_followers ||= integer_value_from_property("num_followers")
|
13
|
+
end
|
14
|
+
|
15
|
+
def num_blocking
|
16
|
+
@num_blocking ||= integer_value_from_property("num_blocking")
|
17
|
+
end
|
18
|
+
|
19
|
+
def num_blockers
|
20
|
+
@num_blockers ||= integer_value_from_property("num_blockers")
|
21
|
+
end
|
22
|
+
|
23
|
+
def timestamp_generated
|
24
|
+
@timestamp_generated ||= timestamp_value_from_property("timestamp_generated")
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def value_from_property(property_name)
|
30
|
+
table.first[property_name]
|
31
|
+
end
|
32
|
+
|
33
|
+
def integer_value_from_property(property_name)
|
34
|
+
value = value_from_property(property_name)
|
35
|
+
Integer(value)
|
36
|
+
end
|
37
|
+
|
38
|
+
def timestamp_value_from_property(property_name)
|
39
|
+
value = integer_value_from_property(property_name)
|
40
|
+
Time.at(value)
|
41
|
+
end
|
42
|
+
|
43
|
+
def table
|
44
|
+
@table ||= CSV.read(@csv_path, headers: true)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
|
3
|
+
module DuolingoPersonalData
|
4
|
+
InventoryItem = Struct.new(:item_type, :purchase_datetime, :active, :price_in_virtual_currency, :wager_day,
|
5
|
+
:payment_processor, :product, :expected_expiration, keyword_init: true)
|
6
|
+
|
7
|
+
class Inventory
|
8
|
+
def initialize(csv_path)
|
9
|
+
@csv_path = csv_path
|
10
|
+
end
|
11
|
+
|
12
|
+
extend Forwardable
|
13
|
+
def_delegators :items, *(Array.instance_methods - [:object_id])
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def items
|
18
|
+
@items ||= table.map do |row|
|
19
|
+
item = InventoryItem.new(item_type: row["item_type"],
|
20
|
+
purchase_datetime: parse_datetime(row["purchase_datetime"]), active: parse_boolean(row["active"]), payment_processor: row["payment_processor"], product: row["product"])
|
21
|
+
price = row["price_in_virtual_currency"]
|
22
|
+
item.price_in_virtual_currency = Integer(price) if price
|
23
|
+
day = row["wager_day"]
|
24
|
+
item.wager_day = Integer(day) if day
|
25
|
+
expiration = row["expected_expiration"]
|
26
|
+
item.expected_expiration = parse_datetime(expiration) if expiration
|
27
|
+
item
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def parse_datetime(str)
|
32
|
+
Time.strptime(str, "%Y-%m-%d %T")
|
33
|
+
end
|
34
|
+
|
35
|
+
def parse_boolean(str)
|
36
|
+
case str
|
37
|
+
when "false" then false
|
38
|
+
when "true" then true
|
39
|
+
else
|
40
|
+
raise Error, "cannot parse #{str.inspect} as boolean"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def table
|
45
|
+
@table ||= CSV.read(@csv_path, headers: true)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
require "csv"
|
3
|
+
|
4
|
+
module DuolingoPersonalData
|
5
|
+
Language = Struct.new(:from_language, :points, :skill_learned, :total_lessons, :days_active, :last_active,
|
6
|
+
:prior_proficiency, :subscribed, keyword_init: true)
|
7
|
+
class Languages
|
8
|
+
def initialize(csv_path)
|
9
|
+
@csv_path = csv_path
|
10
|
+
end
|
11
|
+
|
12
|
+
extend Forwardable
|
13
|
+
def_delegators :languages, *(Hash.instance_methods - [:object_id])
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def languages
|
18
|
+
@languages ||= CSV.read(@csv_path, headers: true).map do |row|
|
19
|
+
language = Language.new(from_language: row["from_language"])
|
20
|
+
points = row["points"]
|
21
|
+
language.points = Integer(points) if points
|
22
|
+
skills = row["skills_learned"]
|
23
|
+
language.skill_learned = Integer(skills) if skills
|
24
|
+
lessons = row["total_lessons"]
|
25
|
+
language.total_lessons = Integer(lessons) if lessons
|
26
|
+
days = row["days_active"]
|
27
|
+
language.days_active = Integer(days) if days
|
28
|
+
active = row["last_active"]
|
29
|
+
language.last_active = parse_datetime(active) if active
|
30
|
+
proficiency = row["prior_proficiency"]
|
31
|
+
language.prior_proficiency = Integer(proficiency) if proficiency
|
32
|
+
subscribed = row["subscribed"]
|
33
|
+
language.subscribed = parse_datetime(subscribed) if subscribed
|
34
|
+
{ row["learning_language"] => language }
|
35
|
+
end.reduce(&:merge)
|
36
|
+
end
|
37
|
+
|
38
|
+
def parse_datetime(str)
|
39
|
+
Time.strptime(str, "%Y-%m-%d %T")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "csv"
|
2
|
+
require "forwardable"
|
3
|
+
|
4
|
+
module DuolingoPersonalData
|
5
|
+
LeaderboardsEntry = Struct.new(:timestamp, :tier, :score, keyword_init: true)
|
6
|
+
|
7
|
+
class Leaderboards
|
8
|
+
def initialize(csv_path)
|
9
|
+
@csv_path = csv_path
|
10
|
+
end
|
11
|
+
|
12
|
+
extend Forwardable
|
13
|
+
def_delegators :leaderboards_entries, *(Array.instance_methods - [:object_id])
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def leaderboards_entries
|
18
|
+
@leaderboards_entries ||= CSV.read(@csv_path, headers: true).map do |row|
|
19
|
+
LeaderboardsEntry.new(timestamp: Time.strptime(row["timestamp"], "%FT%TZ"), tier: Integer(row["tier"]),
|
20
|
+
score: Float(row["score"]))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "json"
|
2
|
+
|
3
|
+
module DuolingoPersonalData
|
4
|
+
class NotifyData
|
5
|
+
def initialize(csv_path)
|
6
|
+
@csv_path = csv_path
|
7
|
+
end
|
8
|
+
|
9
|
+
def email
|
10
|
+
@email ||= value_from_property("email")
|
11
|
+
end
|
12
|
+
|
13
|
+
def device_ids
|
14
|
+
@device_ids ||= json_value_from_property("device_ids")
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def value_from_property(property_name)
|
20
|
+
table.find { |row| row["property"] == property_name }["value"]
|
21
|
+
end
|
22
|
+
|
23
|
+
def json_value_from_property(property_name)
|
24
|
+
value = value_from_property(property_name)
|
25
|
+
value.gsub!("'", '"')
|
26
|
+
JSON.parse(value)
|
27
|
+
end
|
28
|
+
|
29
|
+
def table
|
30
|
+
@table ||= CSV.read(@csv_path, headers: true)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require "csv"
|
2
|
+
|
3
|
+
module DuolingoPersonalData
|
4
|
+
class Profile
|
5
|
+
def initialize(csv_path)
|
6
|
+
@csv_path = csv_path
|
7
|
+
end
|
8
|
+
|
9
|
+
def username
|
10
|
+
@username ||= value_from_property("username")
|
11
|
+
end
|
12
|
+
|
13
|
+
def email
|
14
|
+
@email ||= value_from_property("email")
|
15
|
+
end
|
16
|
+
|
17
|
+
def fullname
|
18
|
+
@fullname ||= value_from_property("fullname")
|
19
|
+
end
|
20
|
+
|
21
|
+
def joined_at
|
22
|
+
@joined_at ||= datetime_value_from_property("joined_at")
|
23
|
+
end
|
24
|
+
|
25
|
+
def ui_language
|
26
|
+
@ui_language ||= value_from_property("ui_language")
|
27
|
+
end
|
28
|
+
|
29
|
+
def learning_language
|
30
|
+
@learning_language ||= value_from_property("learning_language")
|
31
|
+
end
|
32
|
+
|
33
|
+
def lingots
|
34
|
+
@lingots ||= integer_value_from_property("lingots")
|
35
|
+
end
|
36
|
+
|
37
|
+
def daily_goal
|
38
|
+
@daily_goal ||= integer_value_from_property("daily_goal")
|
39
|
+
end
|
40
|
+
|
41
|
+
def timezone
|
42
|
+
@timezone ||= value_from_property("timezone")
|
43
|
+
end
|
44
|
+
|
45
|
+
def avatar_url
|
46
|
+
@avatar_url ||= value_from_property("avatar_url")
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def value_from_property(property_name)
|
52
|
+
table.find { |row| row["name"] == property_name }["value"]
|
53
|
+
end
|
54
|
+
|
55
|
+
def integer_value_from_property(property_name)
|
56
|
+
Integer(value_from_property(property_name))
|
57
|
+
end
|
58
|
+
|
59
|
+
def datetime_value_from_property(property_name)
|
60
|
+
Time.strptime(value_from_property(property_name), "%F %T")
|
61
|
+
end
|
62
|
+
|
63
|
+
def table
|
64
|
+
@table ||= CSV.read(@csv_path, headers: true)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module DuolingoPersonalData
|
2
|
+
class Stories
|
3
|
+
def initialize(csv_path)
|
4
|
+
@csv_path = csv_path
|
5
|
+
end
|
6
|
+
|
7
|
+
def user_id
|
8
|
+
@user_id ||= value_from_property("userId")
|
9
|
+
end
|
10
|
+
|
11
|
+
def date_of_first_visit_to_stories
|
12
|
+
@date_of_first_visit_to_stories ||= datetime_value_from_property("dateOfFirstVisitToStories")
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def value_from_property(property_name)
|
18
|
+
table.first[property_name]
|
19
|
+
end
|
20
|
+
|
21
|
+
def datetime_value_from_property(property_name)
|
22
|
+
Time.strptime(value_from_property(property_name), "%F %T")
|
23
|
+
end
|
24
|
+
|
25
|
+
def table
|
26
|
+
@table ||= CSV.read(@csv_path, headers: true)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
|
3
|
+
module DuolingoPersonalData
|
4
|
+
StoryCompletion = Struct.new(:user_id, :story_id, :score, :time, keyword_init: true)
|
5
|
+
|
6
|
+
class StoryCompletions
|
7
|
+
def initialize(csv_path)
|
8
|
+
@csv_path = csv_path
|
9
|
+
end
|
10
|
+
|
11
|
+
extend Forwardable
|
12
|
+
def_delegators :completions, *(Array.instance_methods - [:object_id])
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def completions
|
17
|
+
@completions ||= CSV.read(@csv_path, headers: true).map do |row|
|
18
|
+
StoryCompletion.new(user_id: row["userId"], story_id: row["storyId"], score: Integer(row["score"]),
|
19
|
+
time: Time.strptime(row["time"], "%F %T"))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module DuolingoPersonalData
|
2
|
+
class TeacherPrivacySettings
|
3
|
+
def initialize(csv_path)
|
4
|
+
@csv_path = csv_path
|
5
|
+
end
|
6
|
+
|
7
|
+
def disable_clubs
|
8
|
+
@disable_clubs ||= boolean_value_from_property("disable_clubs")
|
9
|
+
end
|
10
|
+
|
11
|
+
def disable_discussions
|
12
|
+
@disable_discussions ||= boolean_value_from_property("disable_discussions")
|
13
|
+
end
|
14
|
+
|
15
|
+
def disable_events
|
16
|
+
@disable_events ||= boolean_value_from_property("disable_events")
|
17
|
+
end
|
18
|
+
|
19
|
+
def disable_stream
|
20
|
+
@disable_stream ||= boolean_value_from_property("disable_stream")
|
21
|
+
end
|
22
|
+
|
23
|
+
def disable_immersion
|
24
|
+
@disable_immersion ||= boolean_value_from_property("disable_immersion")
|
25
|
+
end
|
26
|
+
|
27
|
+
def disable_mature_words
|
28
|
+
@disable_mature_words ||= boolean_value_from_property("disable_mature_words")
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def boolean_value_from_property(property_name)
|
34
|
+
value = value_from_property(property_name)
|
35
|
+
case value
|
36
|
+
when "False" then false
|
37
|
+
when "True" then true
|
38
|
+
else
|
39
|
+
raise Error, "cannot interpret #{value.inspect} as boolean"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def value_from_property(property_name)
|
44
|
+
table.first[property_name]
|
45
|
+
end
|
46
|
+
|
47
|
+
def table
|
48
|
+
@table ||= CSV.read(@csv_path, headers: true)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative "duolingo_personal_data/version"
|
2
|
+
require_relative "duolingo_personal_data/auth_data"
|
3
|
+
require_relative "duolingo_personal_data/avatar_images"
|
4
|
+
require_relative "duolingo_personal_data/blast_emails"
|
5
|
+
require_relative "duolingo_personal_data/notify_data"
|
6
|
+
require_relative "duolingo_personal_data/friends_follow"
|
7
|
+
require_relative "duolingo_personal_data/inventory"
|
8
|
+
require_relative "duolingo_personal_data/languages"
|
9
|
+
require_relative "duolingo_personal_data/leaderboards"
|
10
|
+
require_relative "duolingo_personal_data/profile"
|
11
|
+
require_relative "duolingo_personal_data/stories"
|
12
|
+
require_relative "duolingo_personal_data/story_completions"
|
13
|
+
require_relative "duolingo_personal_data/teacher_privacy_settings"
|
14
|
+
|
15
|
+
module DuolingoPersonalData
|
16
|
+
class Error < StandardError; end
|
17
|
+
end
|
data/manifest.scm
ADDED
@@ -0,0 +1,272 @@
|
|
1
|
+
# TypeProf 0.21.3
|
2
|
+
|
3
|
+
# Classes
|
4
|
+
module DuolingoPersonalData
|
5
|
+
VERSION: String
|
6
|
+
|
7
|
+
class AuthData
|
8
|
+
@csv_path: untyped
|
9
|
+
@user_account_name: String?
|
10
|
+
@table: Array[Array[String?]]
|
11
|
+
@email_address: String?
|
12
|
+
@last_update_timestamp: String?
|
13
|
+
@last_login_attempt_timestamp: String?
|
14
|
+
@last_authentication_key_refresh_timestamp: String?
|
15
|
+
|
16
|
+
def initialize: (untyped csv_path) -> void
|
17
|
+
def user_account_name: -> String?
|
18
|
+
def email_address: -> String?
|
19
|
+
def last_update_timestamp: -> String?
|
20
|
+
def last_login_attempt_timestamp: -> String?
|
21
|
+
def last_authentication_key_refresh_timestamp: -> String?
|
22
|
+
|
23
|
+
private
|
24
|
+
def value_from_property: (String property_name) -> String?
|
25
|
+
def table: -> Array[Array[String?]]
|
26
|
+
end
|
27
|
+
|
28
|
+
class AvatarImages
|
29
|
+
extend Forwardable
|
30
|
+
@csv_path: untyped
|
31
|
+
@urls: Array[URI::Generic]
|
32
|
+
@table: Array[Array[String?]]
|
33
|
+
|
34
|
+
def initialize: (untyped csv_path) -> void
|
35
|
+
|
36
|
+
private
|
37
|
+
def urls: -> Array[URI::Generic]
|
38
|
+
def table: -> Array[Array[String?]]
|
39
|
+
end
|
40
|
+
|
41
|
+
class BlastEmails
|
42
|
+
@csv_path: untyped
|
43
|
+
@email_address: String?
|
44
|
+
@table: Array[Array[String?]]
|
45
|
+
@ui_language: String?
|
46
|
+
@learning_language: String?
|
47
|
+
@enabled: bool
|
48
|
+
@announcement: bool
|
49
|
+
@creation_datetime: untyped
|
50
|
+
@last_session: untyped
|
51
|
+
@trial_user: bool
|
52
|
+
@country: String?
|
53
|
+
@client: String?
|
54
|
+
@schools_role: Integer
|
55
|
+
|
56
|
+
def initialize: (untyped csv_path) -> void
|
57
|
+
def email_address: -> String?
|
58
|
+
def ui_language: -> String?
|
59
|
+
def learning_language: -> String?
|
60
|
+
def enabled: -> bool
|
61
|
+
def announcement: -> bool
|
62
|
+
def creation_datetime: -> untyped
|
63
|
+
def last_session: -> untyped
|
64
|
+
def trial_user: -> bool
|
65
|
+
def country: -> String?
|
66
|
+
def client: -> String?
|
67
|
+
def schools_role: -> Integer
|
68
|
+
|
69
|
+
private
|
70
|
+
def value_from_property: (String property_name) -> String?
|
71
|
+
def boolean_value_from_property: (String property_name) -> bool
|
72
|
+
def time_value_from_property: (String property_name) -> untyped
|
73
|
+
def integer_value_from_property: (String property_name) -> Integer
|
74
|
+
def table: -> Array[Array[String?]]
|
75
|
+
end
|
76
|
+
|
77
|
+
class FriendsFollow
|
78
|
+
@csv_path: untyped
|
79
|
+
@num_following: Integer
|
80
|
+
@table: Array[Array[String?]]
|
81
|
+
@num_followers: Integer
|
82
|
+
@num_blocking: Integer
|
83
|
+
@num_blockers: Integer
|
84
|
+
@timestamp_generated: Time
|
85
|
+
|
86
|
+
def initialize: (untyped csv_path) -> void
|
87
|
+
def num_following: -> Integer
|
88
|
+
def num_followers: -> Integer
|
89
|
+
def num_blocking: -> Integer
|
90
|
+
def num_blockers: -> Integer
|
91
|
+
def timestamp_generated: -> Time
|
92
|
+
|
93
|
+
private
|
94
|
+
def value_from_property: (String property_name) -> String?
|
95
|
+
def integer_value_from_property: (String property_name) -> Integer
|
96
|
+
def timestamp_value_from_property: (String property_name) -> Time
|
97
|
+
def table: -> Array[Array[String?]]
|
98
|
+
end
|
99
|
+
|
100
|
+
class InventoryItem < Struct[untyped]
|
101
|
+
attr_accessor item_type(): String?
|
102
|
+
attr_accessor purchase_datetime(): untyped
|
103
|
+
attr_accessor active(): bool
|
104
|
+
attr_accessor price_in_virtual_currency(): Integer
|
105
|
+
attr_accessor wager_day(): Integer
|
106
|
+
attr_accessor payment_processor(): String?
|
107
|
+
attr_accessor product(): String?
|
108
|
+
attr_accessor expected_expiration(): untyped
|
109
|
+
end
|
110
|
+
|
111
|
+
class Inventory
|
112
|
+
extend Forwardable
|
113
|
+
@csv_path: untyped
|
114
|
+
@items: Array[InventoryItem]
|
115
|
+
@table: Array[Array[String?]]
|
116
|
+
|
117
|
+
def initialize: (untyped csv_path) -> void
|
118
|
+
|
119
|
+
private
|
120
|
+
def items: -> Array[InventoryItem]
|
121
|
+
def parse_datetime: (String? str) -> untyped
|
122
|
+
def parse_boolean: (String? str) -> bool
|
123
|
+
def table: -> Array[Array[String?]]
|
124
|
+
end
|
125
|
+
|
126
|
+
class Language < Struct[untyped]
|
127
|
+
attr_accessor from_language(): String?
|
128
|
+
attr_accessor points(): Integer
|
129
|
+
attr_accessor skill_learned(): Integer
|
130
|
+
attr_accessor total_lessons(): Integer
|
131
|
+
attr_accessor days_active(): Integer
|
132
|
+
attr_accessor last_active(): untyped
|
133
|
+
attr_accessor prior_proficiency(): Integer
|
134
|
+
attr_accessor subscribed(): untyped
|
135
|
+
end
|
136
|
+
|
137
|
+
class Languages
|
138
|
+
extend Forwardable
|
139
|
+
@csv_path: untyped
|
140
|
+
@languages: Hash[String?, Language]
|
141
|
+
|
142
|
+
def initialize: (untyped csv_path) -> void
|
143
|
+
|
144
|
+
private
|
145
|
+
def languages: -> Hash[String?, Language]
|
146
|
+
def parse_datetime: (String str) -> untyped
|
147
|
+
end
|
148
|
+
|
149
|
+
class LeaderboardsEntry < Struct[untyped]
|
150
|
+
attr_accessor timestamp(): untyped
|
151
|
+
attr_accessor tier(): Integer
|
152
|
+
attr_accessor score(): Float
|
153
|
+
end
|
154
|
+
|
155
|
+
class Leaderboards
|
156
|
+
extend Forwardable
|
157
|
+
@csv_path: untyped
|
158
|
+
@entries: Array[LeaderboardsEntry]
|
159
|
+
|
160
|
+
def initialize: (untyped csv_path) -> void
|
161
|
+
|
162
|
+
private
|
163
|
+
def entries: -> Array[LeaderboardsEntry]
|
164
|
+
end
|
165
|
+
|
166
|
+
class NotifyData
|
167
|
+
@csv_path: untyped
|
168
|
+
@email: String?
|
169
|
+
@table: Array[Array[String?]]
|
170
|
+
@device_ids: untyped
|
171
|
+
|
172
|
+
def initialize: (untyped csv_path) -> void
|
173
|
+
def email: -> String?
|
174
|
+
def device_ids: -> untyped
|
175
|
+
|
176
|
+
private
|
177
|
+
def value_from_property: (String property_name) -> String?
|
178
|
+
def json_value_from_property: (String property_name) -> untyped
|
179
|
+
def table: -> Array[Array[String?]]
|
180
|
+
end
|
181
|
+
|
182
|
+
class Profile
|
183
|
+
@csv_path: untyped
|
184
|
+
@username: String?
|
185
|
+
@table: Array[Array[String?]]
|
186
|
+
@email: String?
|
187
|
+
@fullname: String?
|
188
|
+
@joined_at: untyped
|
189
|
+
@ui_language: String?
|
190
|
+
@learning_language: String?
|
191
|
+
@lingots: Integer
|
192
|
+
@daily_goal: Integer
|
193
|
+
@timezone: String?
|
194
|
+
@avatar_url: String?
|
195
|
+
|
196
|
+
def initialize: (untyped csv_path) -> void
|
197
|
+
def username: -> String?
|
198
|
+
def email: -> String?
|
199
|
+
def fullname: -> String?
|
200
|
+
def joined_at: -> untyped
|
201
|
+
def ui_language: -> String?
|
202
|
+
def learning_language: -> String?
|
203
|
+
def lingots: -> Integer
|
204
|
+
def daily_goal: -> Integer
|
205
|
+
def timezone: -> String?
|
206
|
+
def avatar_url: -> String?
|
207
|
+
|
208
|
+
private
|
209
|
+
def value_from_property: (String property_name) -> String?
|
210
|
+
def integer_value_from_property: (String property_name) -> Integer
|
211
|
+
def datetime_value_from_property: (String property_name) -> untyped
|
212
|
+
def table: -> Array[Array[String?]]
|
213
|
+
end
|
214
|
+
|
215
|
+
class Stories
|
216
|
+
@csv_path: untyped
|
217
|
+
@user_id: String?
|
218
|
+
@table: Array[Array[String?]]
|
219
|
+
@date_of_first_visit_to_stories: untyped
|
220
|
+
|
221
|
+
def initialize: (untyped csv_path) -> void
|
222
|
+
def user_id: -> String?
|
223
|
+
def date_of_first_visit_to_stories: -> untyped
|
224
|
+
|
225
|
+
private
|
226
|
+
def value_from_property: (String property_name) -> String?
|
227
|
+
def datetime_value_from_property: (String property_name) -> untyped
|
228
|
+
def table: -> Array[Array[String?]]
|
229
|
+
end
|
230
|
+
|
231
|
+
class StoryCompletion < Struct[untyped]
|
232
|
+
attr_accessor user_id(): String?
|
233
|
+
attr_accessor story_id(): String?
|
234
|
+
attr_accessor score(): Integer
|
235
|
+
attr_accessor time(): untyped
|
236
|
+
end
|
237
|
+
|
238
|
+
class StoryCompletions
|
239
|
+
extend Forwardable
|
240
|
+
@csv_path: untyped
|
241
|
+
@completions: Array[StoryCompletion]
|
242
|
+
|
243
|
+
def initialize: (untyped csv_path) -> void
|
244
|
+
|
245
|
+
private
|
246
|
+
def completions: -> Array[StoryCompletion]
|
247
|
+
end
|
248
|
+
|
249
|
+
class TeacherPrivacySettings
|
250
|
+
@csv_path: untyped
|
251
|
+
@disable_clubs: bool
|
252
|
+
@table: Array[Array[String?]]
|
253
|
+
@disable_discussions: bool
|
254
|
+
@disable_events: bool
|
255
|
+
@disable_stream: bool
|
256
|
+
@disable_immersion: bool
|
257
|
+
@disable_mature_words: bool
|
258
|
+
|
259
|
+
def initialize: (untyped csv_path) -> void
|
260
|
+
def disable_clubs: -> bool
|
261
|
+
def disable_discussions: -> bool
|
262
|
+
def disable_events: -> bool
|
263
|
+
def disable_stream: -> bool
|
264
|
+
def disable_immersion: -> bool
|
265
|
+
def disable_mature_words: -> bool
|
266
|
+
|
267
|
+
private
|
268
|
+
def boolean_value_from_property: (String property_name) -> bool
|
269
|
+
def value_from_property: (String property_name) -> String?
|
270
|
+
def table: -> Array[Array[String?]]
|
271
|
+
end
|
272
|
+
end
|