language_cards 0.3.2 → 2.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/.github/workflows/ci.yml +20 -0
- data/CHANGELOG.md +31 -0
- data/README.md +80 -22
- data/bin/language_cards +7 -1
- data/cards/en/arabic.yml +370 -0
- data/cards/en/armenian.yml +406 -0
- data/cards/en/bengali.yml +395 -0
- data/cards/en/chinese-hsk1.yml +157 -0
- data/cards/en/chinese-hsk2.yml +154 -0
- data/cards/en/chinese-hsk3.yml +305 -0
- data/cards/en/chinese-hsk4.yml +605 -0
- data/cards/en/georgian.yml +362 -0
- data/cards/en/greek.yml +379 -0
- data/cards/en/hebrew.yml +355 -0
- data/cards/en/hindi.yml +412 -0
- data/cards/en/japanese-01-hiragana.yml +227 -0
- data/cards/en/japanese-02-katakana.yml +296 -0
- data/cards/en/japanese-03-keyboard-mappings.yml +357 -0
- data/cards/en/japanese-10-kanji-jlpt-n5.yml +86 -0
- data/cards/en/japanese-11-kanji-jlpt-n4.yml +173 -0
- data/cards/en/japanese-12-kanji-jlpt-n3.yml +374 -0
- data/cards/en/japanese-13-kanji-jlpt-n2.yml +374 -0
- data/cards/en/japanese-14-kanji-jlpt-n1.yml +1239 -0
- data/cards/en/japanese-20-vocabulary-jlpt-n5.yml +708 -0
- data/cards/en/japanese-21-vocabulary-jlpt-n4.yml +668 -0
- data/cards/en/japanese-22-vocabulary-jlpt-n3.yml +2108 -0
- data/cards/en/japanese-23-vocabulary-jlpt-n2.yml +1738 -0
- data/cards/en/japanese-24-vocabulary-jlpt-n1.yml +2689 -0
- data/cards/en/korean.yml +534 -0
- data/cards/en/persian.yml +370 -0
- data/cards/en/punjabi.yml +393 -0
- data/cards/en/russian.yml +398 -0
- data/cards/en/tamil.yml +405 -0
- data/cards/en/thai.yml +408 -0
- data/cards/en/ukrainian.yml +398 -0
- data/cards/en/urdu.yml +374 -0
- data/language_cards.gemspec +7 -6
- data/lib/language_cards/card_set_builder.rb +11 -0
- data/lib/language_cards/controllers/application_controller.rb +2 -0
- data/lib/language_cards/controllers/game.rb +10 -6
- data/lib/language_cards/controllers/main_menu.rb +20 -3
- data/lib/language_cards/defaults.rb +33 -0
- data/lib/language_cards/helpers/view_helper.rb +3 -2
- data/lib/language_cards/menu_builder.rb +11 -0
- data/lib/language_cards/menu_node.rb +9 -4
- data/lib/language_cards/models/card.rb +18 -0
- data/lib/language_cards/models/card_set.rb +15 -16
- data/lib/language_cards/modes/game.rb +15 -4
- data/lib/language_cards/modes/translate.rb +12 -1
- data/lib/language_cards/modes/typing_practice.rb +5 -1
- data/lib/language_cards/paginator.rb +59 -0
- data/lib/language_cards/user_interface.rb +84 -52
- data/lib/language_cards/version.rb +1 -1
- data/lib/language_cards/view/main_menu.erb +3 -1
- data/lib/language_cards/yaml_loader.rb +5 -3
- data/lib/language_cards.rb +7 -24
- data/locales/en.yml +11 -0
- metadata +69 -43
- data/.travis.yml +0 -5
- data/cards/en/japanese-hiragana.yml +0 -113
- data/cards/en/japanese-kanji-jlpt-n5.yml +0 -107
- data/cards/en/japanese-katakana-keyboard-mappings.yml +0 -180
- data/cards/en/japanese-katakana.yml +0 -109
- data/lib/language_cards/grapheme_builder.rb +0 -12
- data/lib/language_cards/language_cards.rb +0 -25
- data/lib/language_cards/models/grapheme.rb +0 -18
|
@@ -3,18 +3,20 @@ module LanguageCards
|
|
|
3
3
|
module Modes
|
|
4
4
|
class Game
|
|
5
5
|
def initialize card_set
|
|
6
|
-
@card_set = card_set
|
|
6
|
+
@card_set = card_set.cards
|
|
7
7
|
@index = 0
|
|
8
8
|
@current = nil
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def current
|
|
12
|
-
@current or raise "Current
|
|
12
|
+
@current or raise "Current flash card not yet set!"
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
#
|
|
15
|
+
# Picks a random card, avoiding the same card twice in a row.
|
|
16
|
+
# @return self
|
|
16
17
|
def sample
|
|
17
|
-
@current
|
|
18
|
+
choices = @card_set.length > 1 ? @card_set - [@current] : @card_set
|
|
19
|
+
@current = choices.sample
|
|
18
20
|
self
|
|
19
21
|
end
|
|
20
22
|
|
|
@@ -25,6 +27,15 @@ module LanguageCards
|
|
|
25
27
|
@index += 1
|
|
26
28
|
@current = value
|
|
27
29
|
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
# Makes comparisons forgiving of surrounding/repeated whitespace and of
|
|
33
|
+
# differing Unicode compositions (e.g. pinyin tone marks).
|
|
34
|
+
def normalize(text)
|
|
35
|
+
text = text.to_s
|
|
36
|
+
text = text.unicode_normalize(:nfc) rescue text
|
|
37
|
+
text.strip.squeeze(' ')
|
|
38
|
+
end
|
|
28
39
|
end
|
|
29
40
|
end
|
|
30
41
|
end
|
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
require 'language_cards/modes/game'
|
|
2
2
|
module LanguageCards
|
|
3
3
|
module Modes
|
|
4
|
+
def self.translate card_set
|
|
5
|
+
Translate.new card_set
|
|
6
|
+
end
|
|
7
|
+
|
|
4
8
|
class Translate < Game
|
|
5
9
|
def match? input
|
|
6
|
-
|
|
10
|
+
answer = comparable(input)
|
|
11
|
+
current.translation.any? {|value| comparable(value) == answer }
|
|
7
12
|
end
|
|
8
13
|
|
|
9
14
|
def mode
|
|
10
15
|
:translate
|
|
11
16
|
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
# Case-insensitive, and a leading "to " is optional ("to eat" == "eat").
|
|
20
|
+
def comparable(text)
|
|
21
|
+
normalize(text).downcase.sub(/\Ato (?=\S)/, '')
|
|
22
|
+
end
|
|
12
23
|
end
|
|
13
24
|
end
|
|
14
25
|
end
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
require 'language_cards/modes/game'
|
|
2
2
|
module LanguageCards
|
|
3
3
|
module Modes
|
|
4
|
+
def self.typing_practice card_set
|
|
5
|
+
TypingPractice.new card_set
|
|
6
|
+
end
|
|
7
|
+
|
|
4
8
|
class TypingPractice < Game
|
|
5
9
|
def match? input
|
|
6
|
-
|
|
10
|
+
normalize(current) == normalize(input)
|
|
7
11
|
end
|
|
8
12
|
|
|
9
13
|
def mode
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module LanguageCards
|
|
2
|
+
# Splits a list of menu entries into pages so long menus stay readable.
|
|
3
|
+
# Entries keep their absolute numbering across pages, so any listed
|
|
4
|
+
# number can be picked no matter which page is currently shown.
|
|
5
|
+
class Paginator
|
|
6
|
+
attr_reader :items, :per_page, :page
|
|
7
|
+
|
|
8
|
+
def initialize(items, per_page = PER_PAGE)
|
|
9
|
+
@items = Array(items)
|
|
10
|
+
@per_page = [per_page.to_i, 1].max
|
|
11
|
+
@page = 0
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# @return Array<Array(Integer, Object)> number/item pairs for the current page
|
|
15
|
+
def current
|
|
16
|
+
items.each_with_index
|
|
17
|
+
.map {|item, index| [index + 1, item] }
|
|
18
|
+
.slice(page * per_page, per_page) || []
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def pages
|
|
22
|
+
[(items.length.to_f / per_page).ceil, 1].max
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def paginated?
|
|
26
|
+
pages > 1
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def next_page?
|
|
30
|
+
page < pages - 1
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def previous_page?
|
|
34
|
+
page > 0
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def next_page
|
|
38
|
+
@page += 1 if next_page?
|
|
39
|
+
self
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def previous_page
|
|
43
|
+
@page -= 1 if previous_page?
|
|
44
|
+
self
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @param number [Integer] the 1-based number shown in the menu
|
|
48
|
+
# @return the item for that number or nil
|
|
49
|
+
def [](number)
|
|
50
|
+
number = Integer(number) rescue (return nil)
|
|
51
|
+
return nil unless (1..items.length).include?(number)
|
|
52
|
+
items[number - 1]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def offset
|
|
56
|
+
page * per_page
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
require 'language_cards/timer'
|
|
2
|
+
require 'language_cards/paginator'
|
|
2
3
|
require 'language_cards/helpers/view_helper'
|
|
3
4
|
require 'language_cards/helpers/game_helper'
|
|
4
5
|
require 'language_cards/controllers/main_menu'
|
|
5
6
|
require 'language_cards/controllers/game'
|
|
6
|
-
require 'erb'
|
|
7
7
|
|
|
8
8
|
module LanguageCards
|
|
9
9
|
class UserInterface
|
|
10
10
|
include Helpers::ViewHelper
|
|
11
11
|
include Controllers
|
|
12
|
-
def initialize
|
|
13
|
-
@
|
|
14
|
-
@
|
|
12
|
+
def initialize menu_items
|
|
13
|
+
@menu_items = menu_items
|
|
14
|
+
@languages = group_by_language(menu_items)
|
|
15
15
|
@mode = [:translate, :typing_practice].cycle
|
|
16
16
|
end
|
|
17
17
|
|
|
@@ -22,70 +22,102 @@ module LanguageCards
|
|
|
22
22
|
sleep 2
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
clear
|
|
28
|
-
|
|
29
|
-
CLI.say MainMenu.new(opts).render courses: courses, mode: mode
|
|
30
|
-
|
|
31
|
-
value = CLI.ask("")
|
|
32
|
-
|
|
33
|
-
next mode.next if value =~ /\Am\z/i
|
|
34
|
-
value = value.to_i - 1 rescue next
|
|
35
|
-
|
|
36
|
-
last = nil
|
|
37
|
-
if (0..courses.length-1).include? value
|
|
38
|
-
|
|
39
|
-
collection = cards[value] # MenuNode
|
|
40
|
-
title = "#{collection.title} (#{humanize mode.peek})"
|
|
41
|
-
collection = collection.mode(mode.peek) # Mode<CardSet> < Game
|
|
42
|
-
|
|
43
|
-
game = Game.new(opts)
|
|
44
|
-
timer = Timer.new
|
|
45
|
-
begin # Game Loop
|
|
46
|
-
loop do
|
|
47
|
-
clear
|
|
48
|
-
timer.mark
|
|
49
|
-
CLI.say game.render correct: correct,
|
|
50
|
-
incorrect: incorrect,
|
|
51
|
-
title: title,
|
|
52
|
-
timer: timer,
|
|
53
|
-
last: last
|
|
54
|
-
result = game.process(collection, collection.mode)
|
|
55
|
-
result[:correct] ? correct! : incorrect!
|
|
56
|
-
last = result[:last]
|
|
57
|
-
end
|
|
58
|
-
rescue SystemExit, Interrupt
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
rescue SystemExit, Interrupt
|
|
25
|
+
catch(:quit) do
|
|
26
|
+
languages.length == 1 ? card_set_menu(languages.keys.first, false) : language_menu
|
|
64
27
|
end
|
|
28
|
+
rescue SystemExit, Interrupt, EOFError
|
|
65
29
|
end
|
|
66
30
|
|
|
67
31
|
private
|
|
68
|
-
attr_reader :mode, :
|
|
32
|
+
attr_reader :mode, :menu_items, :languages
|
|
69
33
|
def opts
|
|
70
34
|
@opts ||= {}
|
|
71
35
|
end
|
|
72
36
|
|
|
73
|
-
|
|
74
|
-
|
|
37
|
+
# First screen: pick a language.
|
|
38
|
+
def language_menu
|
|
39
|
+
menu_loop(
|
|
40
|
+
Paginator.new(languages.keys),
|
|
41
|
+
heading: t('Menu.ChooseLanguage'),
|
|
42
|
+
label: ->(language) {
|
|
43
|
+
sets = languages[language].length
|
|
44
|
+
"#{language} (#{sets} #{t(sets == 1 ? 'Menu.Set' : 'Menu.Sets')})"
|
|
45
|
+
}
|
|
46
|
+
) {|language| card_set_menu(language) }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Second screen: pick a card set for the chosen language.
|
|
50
|
+
def card_set_menu(language, back = true)
|
|
51
|
+
menu_loop(
|
|
52
|
+
Paginator.new(languages[language]),
|
|
53
|
+
heading: "#{language}#{JOIN}#{t('Menu.ChooseCardSet')}",
|
|
54
|
+
back: back,
|
|
55
|
+
label: ->(course) { "#{course.title(JOIN, 1..-1)} (#{course.size} #{t('Menu.Cards')})" }
|
|
56
|
+
) {|course| play(course) }
|
|
75
57
|
end
|
|
76
58
|
|
|
77
|
-
|
|
78
|
-
|
|
59
|
+
# Renders a paginated menu until the user goes back. Selected items
|
|
60
|
+
# are yielded to the block.
|
|
61
|
+
def menu_loop(pages, heading:, label:, back: false)
|
|
62
|
+
loop do
|
|
63
|
+
clear
|
|
64
|
+
CLI.say MainMenu.new(opts).render courses: pages.current.map {|_, item| label.(item) },
|
|
65
|
+
offset: pages.offset,
|
|
66
|
+
mode: mode,
|
|
67
|
+
heading: heading,
|
|
68
|
+
pages: pages,
|
|
69
|
+
back: back
|
|
70
|
+
|
|
71
|
+
value = CLI.ask("").to_s.strip
|
|
72
|
+
|
|
73
|
+
case value
|
|
74
|
+
when /\Am\z/i then mode.next
|
|
75
|
+
when /\An\z/i, '>' then pages.next_page
|
|
76
|
+
when /\Ap\z/i, '<' then pages.previous_page
|
|
77
|
+
when /\Ab\z/i then return if back
|
|
78
|
+
when /\Aq\z/i then throw :quit
|
|
79
|
+
else
|
|
80
|
+
item = pages[value]
|
|
81
|
+
yield item if item
|
|
82
|
+
end
|
|
83
|
+
end
|
|
79
84
|
end
|
|
80
85
|
|
|
81
|
-
def
|
|
82
|
-
|
|
86
|
+
def play(course)
|
|
87
|
+
title = "#{course.title} (#{humanize mode.peek})"
|
|
88
|
+
collection = course.game(mode.peek) # Mode<CardSet> < Game
|
|
89
|
+
game = Game.new(opts)
|
|
90
|
+
timer = Timer.new
|
|
91
|
+
correct = incorrect = last = nil
|
|
92
|
+
|
|
93
|
+
loop do # Game Loop
|
|
94
|
+
clear
|
|
95
|
+
timer.mark
|
|
96
|
+
CLI.say game.render correct: correct,
|
|
97
|
+
incorrect: incorrect,
|
|
98
|
+
title: title,
|
|
99
|
+
timer: timer,
|
|
100
|
+
last: last
|
|
101
|
+
result = game.process(collection)
|
|
102
|
+
if result[:correct]
|
|
103
|
+
correct = correct.to_i + 1
|
|
104
|
+
else
|
|
105
|
+
incorrect = incorrect.to_i + 1
|
|
106
|
+
end
|
|
107
|
+
last = result[:last]
|
|
108
|
+
end
|
|
109
|
+
rescue Interrupt # CTRL-C returns to the menu
|
|
110
|
+
end
|
|
83
111
|
|
|
84
|
-
|
|
112
|
+
# @return Hash{String => Array<MenuNode>} languages sorted by name
|
|
113
|
+
def group_by_language(menu_items)
|
|
114
|
+
if menu_items.empty?
|
|
85
115
|
opts[:errors] = ["No Flash Cards found for language: #{CARD_LANGUAGE}"]
|
|
86
116
|
end
|
|
87
117
|
|
|
88
|
-
|
|
118
|
+
menu_items.group_by {|item| item.label.first }
|
|
119
|
+
.sort_by {|language, _| language.downcase }
|
|
120
|
+
.to_h
|
|
89
121
|
end
|
|
90
122
|
end
|
|
91
123
|
end
|
|
@@ -5,5 +5,7 @@
|
|
|
5
5
|
<% (_courses.empty? ? errors : _courses).each do |course| %>
|
|
6
6
|
<%= course.chomp %><% end %>
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
<% if _page %><%= draw(_page.first, nil, _page.last) %>
|
|
9
|
+
<% end %><%= draw(_back, nil, _toggle) %>
|
|
10
|
+
<%= draw(_mexit, nil, _quit) %>
|
|
9
11
|
<%= divider %>
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require 'yaml'
|
|
2
|
+
|
|
1
3
|
module LanguageCards
|
|
2
4
|
class YAMLLoader
|
|
3
5
|
def initialize
|
|
@@ -8,7 +10,7 @@ module LanguageCards
|
|
|
8
10
|
cards = {}
|
|
9
11
|
|
|
10
12
|
cards_yaml.each do |c|
|
|
11
|
-
next unless yaml_data = YAML.
|
|
13
|
+
next unless yaml_data = YAML.safe_load(File.read(c, encoding: 'UTF-8'))
|
|
12
14
|
for language in yaml_data.keys do
|
|
13
15
|
# Merges sub-items for languages
|
|
14
16
|
if cards.has_key? language
|
|
@@ -35,12 +37,12 @@ module LanguageCards
|
|
|
35
37
|
end
|
|
36
38
|
|
|
37
39
|
def application_path_cards_yaml
|
|
38
|
-
Dir[File.join(application_path, 'cards', language, '*.yml')]
|
|
40
|
+
Dir[File.join(application_path, 'cards', language, '*.yml')].sort
|
|
39
41
|
end
|
|
40
42
|
|
|
41
43
|
def home_path_cards_yaml
|
|
42
44
|
if ENV['HOME']
|
|
43
|
-
Dir[File.join(ENV['HOME'], '.language_cards', 'cards', language, '*.yml')]
|
|
45
|
+
Dir[File.join(ENV['HOME'], '.language_cards', 'cards', language, '*.yml')].sort
|
|
44
46
|
else
|
|
45
47
|
[]
|
|
46
48
|
end
|
data/lib/language_cards.rb
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
require 'language_cards/version'
|
|
2
|
-
require 'language_cards/
|
|
3
|
-
require '
|
|
4
|
-
require '
|
|
5
|
-
require '
|
|
6
|
-
require 'highline'
|
|
2
|
+
require 'language_cards/defaults'
|
|
3
|
+
require 'language_cards/yaml_loader'
|
|
4
|
+
require 'language_cards/user_interface'
|
|
5
|
+
require 'language_cards/menu_builder'
|
|
7
6
|
|
|
8
7
|
##
|
|
9
8
|
# TODO:
|
|
@@ -12,25 +11,9 @@ require 'highline'
|
|
|
12
11
|
# * Weighted random for better learning
|
|
13
12
|
|
|
14
13
|
module LanguageCards
|
|
15
|
-
OPTS = Slop.parse do |args|
|
|
16
|
-
args.string '-l', '--language', 'language (default: en)', default: 'en'
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
CARD_LANGUAGE = OPTS[:language]
|
|
20
|
-
|
|
21
|
-
module ESC
|
|
22
|
-
CLEAR = (ERASE_SCOLLBACK = "\e[3J") + (CURSOR_HOME = "\e[H") + (ERASE_DISPLAY = "\e[2J")
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
CLI = HighLine.new
|
|
26
|
-
JOIN = " : "
|
|
27
|
-
|
|
28
|
-
SUBMENUWIDTH = 60
|
|
29
|
-
|
|
30
|
-
::I18n.load_path = Dir[File.join(File.expand_path(File.join('..','..'), __FILE__), 'locales', '*.yml')]
|
|
31
|
-
::I18n.load_path += Dir[File.join(File.expand_path(ENV['HOME']), '.language_cards', 'locales', '*.yml')] if ENV['HOME']
|
|
32
|
-
|
|
33
14
|
def self.start
|
|
34
|
-
|
|
15
|
+
yaml = YAMLLoader.new.load
|
|
16
|
+
menu = menu_builder(yaml)
|
|
17
|
+
UserInterface.new(menu).start
|
|
35
18
|
end
|
|
36
19
|
end
|
data/locales/en.yml
CHANGED
|
@@ -2,6 +2,16 @@ en:
|
|
|
2
2
|
Menu:
|
|
3
3
|
Title: Language Cards by @6ftdan
|
|
4
4
|
Choose: Select an option
|
|
5
|
+
ChooseLanguage: Select a language
|
|
6
|
+
ChooseCardSet: Select a card set
|
|
7
|
+
Set: set
|
|
8
|
+
Sets: sets
|
|
9
|
+
Cards: cards
|
|
10
|
+
Page: "Page %{page} of %{pages}"
|
|
11
|
+
NextPage: Next page
|
|
12
|
+
PreviousPage: Previous page
|
|
13
|
+
Back: Back
|
|
14
|
+
Quit: Quit
|
|
5
15
|
GameMode: "GAME MODE: "
|
|
6
16
|
ToggleGameMode: Change Mode
|
|
7
17
|
ModeTranslate: Translate
|
|
@@ -9,6 +19,7 @@ en:
|
|
|
9
19
|
Exit: Press CTRL-C to quit.
|
|
10
20
|
Game:
|
|
11
21
|
TypeThis: Type the following in
|
|
22
|
+
Exit: Press CTRL-C for the menu.
|
|
12
23
|
Correct: Correct!
|
|
13
24
|
Incorrect: Wrong!
|
|
14
25
|
Its: it's
|
metadata
CHANGED
|
@@ -1,43 +1,54 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: language_cards
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Daniel P. Clark
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: highline
|
|
15
14
|
requirement: !ruby/object:Gem::Requirement
|
|
16
15
|
requirements:
|
|
17
|
-
- - "
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.0'
|
|
19
|
+
- - "<"
|
|
18
20
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
21
|
+
version: '4'
|
|
20
22
|
type: :runtime
|
|
21
23
|
prerelease: false
|
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
25
|
requirements:
|
|
24
|
-
- - "
|
|
26
|
+
- - ">="
|
|
25
27
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
28
|
+
version: '2.0'
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '4'
|
|
27
32
|
- !ruby/object:Gem::Dependency
|
|
28
33
|
name: i18n
|
|
29
34
|
requirement: !ruby/object:Gem::Requirement
|
|
30
35
|
requirements:
|
|
31
|
-
- - "
|
|
36
|
+
- - ">="
|
|
32
37
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '0
|
|
38
|
+
version: '1.0'
|
|
39
|
+
- - "<"
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '2'
|
|
34
42
|
type: :runtime
|
|
35
43
|
prerelease: false
|
|
36
44
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
45
|
requirements:
|
|
38
|
-
- - "
|
|
46
|
+
- - ">="
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: '1.0'
|
|
49
|
+
- - "<"
|
|
39
50
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '
|
|
51
|
+
version: '2'
|
|
41
52
|
- !ruby/object:Gem::Dependency
|
|
42
53
|
name: slop
|
|
43
54
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -52,34 +63,20 @@ dependencies:
|
|
|
52
63
|
- - "~>"
|
|
53
64
|
- !ruby/object:Gem::Version
|
|
54
65
|
version: '4.6'
|
|
55
|
-
- !ruby/object:Gem::Dependency
|
|
56
|
-
name: bundler
|
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
|
58
|
-
requirements:
|
|
59
|
-
- - "~>"
|
|
60
|
-
- !ruby/object:Gem::Version
|
|
61
|
-
version: '1.13'
|
|
62
|
-
type: :development
|
|
63
|
-
prerelease: false
|
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
-
requirements:
|
|
66
|
-
- - "~>"
|
|
67
|
-
- !ruby/object:Gem::Version
|
|
68
|
-
version: '1.13'
|
|
69
66
|
- !ruby/object:Gem::Dependency
|
|
70
67
|
name: rake
|
|
71
68
|
requirement: !ruby/object:Gem::Requirement
|
|
72
69
|
requirements:
|
|
73
70
|
- - "~>"
|
|
74
71
|
- !ruby/object:Gem::Version
|
|
75
|
-
version: '
|
|
72
|
+
version: '13.0'
|
|
76
73
|
type: :development
|
|
77
74
|
prerelease: false
|
|
78
75
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
76
|
requirements:
|
|
80
77
|
- - "~>"
|
|
81
78
|
- !ruby/object:Gem::Version
|
|
82
|
-
version: '
|
|
79
|
+
version: '13.0'
|
|
83
80
|
- !ruby/object:Gem::Dependency
|
|
84
81
|
name: minitest
|
|
85
82
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -94,8 +91,9 @@ dependencies:
|
|
|
94
91
|
- - "~>"
|
|
95
92
|
- !ruby/object:Gem::Version
|
|
96
93
|
version: '5.10'
|
|
97
|
-
description: Flashcard game for language learning
|
|
98
|
-
|
|
94
|
+
description: 'Flashcard game for language learning: Japanese (kana, JLPT N5-N1 kanji
|
|
95
|
+
and vocabulary), Chinese (HSK 1-4), Korean, Russian, Arabic, Hindi and many more.
|
|
96
|
+
Make your own cards or translations as well.'
|
|
99
97
|
email:
|
|
100
98
|
- 6ftdan@gmail.com
|
|
101
99
|
executables:
|
|
@@ -104,8 +102,9 @@ extensions: []
|
|
|
104
102
|
extra_rdoc_files: []
|
|
105
103
|
files:
|
|
106
104
|
- ".appveyor.yml"
|
|
105
|
+
- ".github/workflows/ci.yml"
|
|
107
106
|
- ".gitignore"
|
|
108
|
-
-
|
|
107
|
+
- CHANGELOG.md
|
|
109
108
|
- Gemfile
|
|
110
109
|
- LICENSE.txt
|
|
111
110
|
- README.md
|
|
@@ -113,25 +112,55 @@ files:
|
|
|
113
112
|
- bin/console
|
|
114
113
|
- bin/language_cards
|
|
115
114
|
- bin/setup
|
|
116
|
-
- cards/en/
|
|
117
|
-
- cards/en/
|
|
118
|
-
- cards/en/
|
|
119
|
-
- cards/en/
|
|
115
|
+
- cards/en/arabic.yml
|
|
116
|
+
- cards/en/armenian.yml
|
|
117
|
+
- cards/en/bengali.yml
|
|
118
|
+
- cards/en/chinese-hsk1.yml
|
|
119
|
+
- cards/en/chinese-hsk2.yml
|
|
120
|
+
- cards/en/chinese-hsk3.yml
|
|
121
|
+
- cards/en/chinese-hsk4.yml
|
|
122
|
+
- cards/en/georgian.yml
|
|
123
|
+
- cards/en/greek.yml
|
|
124
|
+
- cards/en/hebrew.yml
|
|
125
|
+
- cards/en/hindi.yml
|
|
126
|
+
- cards/en/japanese-01-hiragana.yml
|
|
127
|
+
- cards/en/japanese-02-katakana.yml
|
|
128
|
+
- cards/en/japanese-03-keyboard-mappings.yml
|
|
129
|
+
- cards/en/japanese-10-kanji-jlpt-n5.yml
|
|
130
|
+
- cards/en/japanese-11-kanji-jlpt-n4.yml
|
|
131
|
+
- cards/en/japanese-12-kanji-jlpt-n3.yml
|
|
132
|
+
- cards/en/japanese-13-kanji-jlpt-n2.yml
|
|
133
|
+
- cards/en/japanese-14-kanji-jlpt-n1.yml
|
|
134
|
+
- cards/en/japanese-20-vocabulary-jlpt-n5.yml
|
|
135
|
+
- cards/en/japanese-21-vocabulary-jlpt-n4.yml
|
|
136
|
+
- cards/en/japanese-22-vocabulary-jlpt-n3.yml
|
|
137
|
+
- cards/en/japanese-23-vocabulary-jlpt-n2.yml
|
|
138
|
+
- cards/en/japanese-24-vocabulary-jlpt-n1.yml
|
|
139
|
+
- cards/en/korean.yml
|
|
140
|
+
- cards/en/persian.yml
|
|
141
|
+
- cards/en/punjabi.yml
|
|
142
|
+
- cards/en/russian.yml
|
|
143
|
+
- cards/en/tamil.yml
|
|
144
|
+
- cards/en/thai.yml
|
|
145
|
+
- cards/en/ukrainian.yml
|
|
146
|
+
- cards/en/urdu.yml
|
|
120
147
|
- language_cards.gemspec
|
|
121
148
|
- lib/language_cards.rb
|
|
149
|
+
- lib/language_cards/card_set_builder.rb
|
|
122
150
|
- lib/language_cards/controllers/application_controller.rb
|
|
123
151
|
- lib/language_cards/controllers/game.rb
|
|
124
152
|
- lib/language_cards/controllers/main_menu.rb
|
|
125
|
-
- lib/language_cards/
|
|
153
|
+
- lib/language_cards/defaults.rb
|
|
126
154
|
- lib/language_cards/helpers/game_helper.rb
|
|
127
155
|
- lib/language_cards/helpers/view_helper.rb
|
|
128
|
-
- lib/language_cards/
|
|
156
|
+
- lib/language_cards/menu_builder.rb
|
|
129
157
|
- lib/language_cards/menu_node.rb
|
|
158
|
+
- lib/language_cards/models/card.rb
|
|
130
159
|
- lib/language_cards/models/card_set.rb
|
|
131
|
-
- lib/language_cards/models/grapheme.rb
|
|
132
160
|
- lib/language_cards/modes/game.rb
|
|
133
161
|
- lib/language_cards/modes/translate.rb
|
|
134
162
|
- lib/language_cards/modes/typing_practice.rb
|
|
163
|
+
- lib/language_cards/paginator.rb
|
|
135
164
|
- lib/language_cards/timer.rb
|
|
136
165
|
- lib/language_cards/user_interface.rb
|
|
137
166
|
- lib/language_cards/version.rb
|
|
@@ -143,7 +172,6 @@ homepage: http://github.com/danielpclark/language_cards
|
|
|
143
172
|
licenses:
|
|
144
173
|
- MIT
|
|
145
174
|
metadata: {}
|
|
146
|
-
post_install_message:
|
|
147
175
|
rdoc_options: []
|
|
148
176
|
require_paths:
|
|
149
177
|
- lib
|
|
@@ -152,16 +180,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
152
180
|
requirements:
|
|
153
181
|
- - ">="
|
|
154
182
|
- !ruby/object:Gem::Version
|
|
155
|
-
version: '
|
|
183
|
+
version: '2.5'
|
|
156
184
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
157
185
|
requirements:
|
|
158
186
|
- - ">="
|
|
159
187
|
- !ruby/object:Gem::Version
|
|
160
188
|
version: '0'
|
|
161
189
|
requirements: []
|
|
162
|
-
|
|
163
|
-
rubygems_version: 2.7.6
|
|
164
|
-
signing_key:
|
|
190
|
+
rubygems_version: 3.6.9
|
|
165
191
|
specification_version: 4
|
|
166
|
-
summary:
|
|
192
|
+
summary: Terminal flashcard game for learning languages with foreign scripts.
|
|
167
193
|
test_files: []
|