language_cards 0.3.1 → 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 -42
- data/.travis.yml +0 -5
- data/cards/en/japanese-hiragana.yml +0 -149
- data/cards/en/japanese-kanji-jlpt-n5.yml +0 -107
- data/cards/en/japanese-katakana.yml +0 -366
- 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,24 +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/
|
|
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
|
|
119
147
|
- language_cards.gemspec
|
|
120
148
|
- lib/language_cards.rb
|
|
149
|
+
- lib/language_cards/card_set_builder.rb
|
|
121
150
|
- lib/language_cards/controllers/application_controller.rb
|
|
122
151
|
- lib/language_cards/controllers/game.rb
|
|
123
152
|
- lib/language_cards/controllers/main_menu.rb
|
|
124
|
-
- lib/language_cards/
|
|
153
|
+
- lib/language_cards/defaults.rb
|
|
125
154
|
- lib/language_cards/helpers/game_helper.rb
|
|
126
155
|
- lib/language_cards/helpers/view_helper.rb
|
|
127
|
-
- lib/language_cards/
|
|
156
|
+
- lib/language_cards/menu_builder.rb
|
|
128
157
|
- lib/language_cards/menu_node.rb
|
|
158
|
+
- lib/language_cards/models/card.rb
|
|
129
159
|
- lib/language_cards/models/card_set.rb
|
|
130
|
-
- lib/language_cards/models/grapheme.rb
|
|
131
160
|
- lib/language_cards/modes/game.rb
|
|
132
161
|
- lib/language_cards/modes/translate.rb
|
|
133
162
|
- lib/language_cards/modes/typing_practice.rb
|
|
163
|
+
- lib/language_cards/paginator.rb
|
|
134
164
|
- lib/language_cards/timer.rb
|
|
135
165
|
- lib/language_cards/user_interface.rb
|
|
136
166
|
- lib/language_cards/version.rb
|
|
@@ -142,7 +172,6 @@ homepage: http://github.com/danielpclark/language_cards
|
|
|
142
172
|
licenses:
|
|
143
173
|
- MIT
|
|
144
174
|
metadata: {}
|
|
145
|
-
post_install_message:
|
|
146
175
|
rdoc_options: []
|
|
147
176
|
require_paths:
|
|
148
177
|
- lib
|
|
@@ -151,16 +180,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
151
180
|
requirements:
|
|
152
181
|
- - ">="
|
|
153
182
|
- !ruby/object:Gem::Version
|
|
154
|
-
version: '
|
|
183
|
+
version: '2.5'
|
|
155
184
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
156
185
|
requirements:
|
|
157
186
|
- - ">="
|
|
158
187
|
- !ruby/object:Gem::Version
|
|
159
188
|
version: '0'
|
|
160
189
|
requirements: []
|
|
161
|
-
|
|
162
|
-
rubygems_version: 2.7.6
|
|
163
|
-
signing_key:
|
|
190
|
+
rubygems_version: 3.6.9
|
|
164
191
|
specification_version: 4
|
|
165
|
-
summary:
|
|
192
|
+
summary: Terminal flashcard game for learning languages with foreign scripts.
|
|
166
193
|
test_files: []
|