Created
March 19, 2018 21:22
-
-
Save kryachkov/94a58304dc9f21a0be0d6aac4a245f0f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rspec' | |
class Flashcard | |
def initialize(question:, correct_answer:) | |
@question = question | |
@correct_answer = correct_answer | |
end | |
def answer_correct?(answer) | |
answer == correct_answer | |
end | |
def cli_humanize | |
"#{question} (#{correct_answer})" | |
end | |
attr_reader :correct_answer, :question | |
end | |
class Deck | |
attr_reader :flashcards, :session_numbers | |
def initialize(flashcards: [], session_numbers: []) | |
@flashcards = flashcards | |
@session_numbers = session_numbers | |
end | |
def include?(flashcard) | |
flashcards.include?(flashcard) | |
end | |
def empty? | |
flashcards.size == 0 | |
end | |
end | |
PROGRESS_DECK_SESSION_NUMBERS = [ | |
[2,5,9], | |
[3,6,0], | |
[4,7,1], | |
[5,8,2], | |
[6,9,3], | |
[7,0,4], | |
[8,1,5], | |
[9,2,6], | |
[0,3,7], | |
[1,4,8] | |
] | |
progress_decks = [] | |
COUNTRIES = <<-EOL | |
Albania,Tirana | |
Andorra,Andorra la Vella | |
Austria,Vienna | |
Belarus,Minsk | |
Belgium,Brussels | |
Bosnia and Herzegovina,Sarajevo | |
Bulgaria,Sofia | |
Croatia,Zagreb | |
Cyprus,Nicosia | |
Czech Republic,Prague | |
Denmark,Copenhagen | |
Estonia,Tallinn | |
Finland,Helsinki | |
France,Paris | |
Georgia,Tbilisi | |
Germany,Berlin | |
Greece,Athens | |
Hungary,Budapest | |
Iceland,Reykjavik | |
Republic of Ireland,Dublin | |
Italy,Rome | |
Latvia,Riga | |
Liechtenstein,Vaduz | |
Lithuania,Vilnius | |
Luxembourg,Luxembourg City | |
Republic of Macedonia,Skopje | |
Malta,Valletta | |
Moldova,Chisinau | |
Monaco,Monaco | |
Montenegro,Podgorica | |
Netherlands,Amsterdam | |
Norway,Oslo | |
Poland,Warsaw | |
Portugal,Lisbon | |
Romania,Bucharest | |
Russia,Moscow | |
San Marino,San Marino | |
Serbia,Belgrade | |
Slovakia,Bratislava | |
Slovenia,Ljubljana | |
Spain,Madrid | |
Sweden,Stockholm | |
Switzerland,Bern | |
Turkey,Ankara | |
Ukraine,Kyiv | |
United Kingdom,London | |
Vatican City,Vatican City | |
EOL | |
def build_flashcards(n) | |
n.times.map do | |
a = rand(100) | |
b = rand(100) | |
Flashcard.new(question: "#{a} + #{b} =", correct_answer: (a + b).to_s) | |
end | |
end | |
(0..9).each do |deck| | |
progress_decks << Deck.new(flashcards: build_flashcards(5), session_numbers: PROGRESS_DECK_SESSION_NUMBERS[deck]) | |
end | |
current_deck = Deck.new(flashcards: build_flashcards(5)) | |
progress_decks.each_with_index do |deck, i| | |
puts "Deck#{i} #{deck.session_numbers.inspect} | #{deck.flashcards.map {|f| f.cli_humanize}.join("; ")}" | |
end | |
class Course | |
attr_reader :current_deck, :progress_decks, :retired_deck, :current_session | |
def initialize(current_deck: Deck.new, progress_decks:, retired_deck: Deck.new, current_session: 0) | |
@current_deck = current_deck | |
@progress_decks = progress_decks | |
@retired_deck = retired_deck | |
@current_session = current_session | |
end | |
def move_flashcard!(flashcard, source_deck, target_deck) | |
source_deck.flashcards.delete(flashcard) | |
target_deck.flashcards.push(flashcard) | |
end | |
def review_cards | |
progress_decks.select { |d| d.session_numbers.include?(@current_session) }.map { |d| d.flashcards }.flatten | |
end | |
def current_set_of_flashcards | |
current_deck.flashcards + review_cards | |
end | |
def next_session! | |
@current_session += 1 | |
end | |
def cycled_session_number | |
current_session % 10 | |
end | |
def cli_inspect | |
puts "Current deck cards:" | |
current_deck.flashcards.each do |fc| | |
puts fc.cli_humanize | |
end | |
puts "Progress decks:" | |
progress_decks.each_with_index do |d, i| | |
puts " Deck #{i}:" | |
d.flashcards.each do |fc| | |
puts " " + fc.cli_humanize | |
end | |
end | |
puts "Retired deck cards:" | |
retired_deck.flashcards.each do |fc| | |
puts fc.cli_humanize | |
end | |
end | |
def current_set_of_flashcards_inspect | |
puts "Current deck cards:" | |
current_deck.flashcards.each do |fc| | |
puts fc.cli_humanize | |
end | |
puts "Review cards:" | |
review_cards.each do |fc| | |
puts fc.cli_humanize | |
end | |
:ok | |
end | |
def handle_attempt(flashcard, answer) | |
if flashcard.answer_correct?(answer) | |
puts 'Correct!' | |
if current_deck.include?(flashcard) | |
move_flashcard!(flashcard, current_deck, progress_decks[cycled_session_number]) | |
elsif deck_of_flashcard(flashcard) | |
deck = deck_of_flashcard(flashcard) | |
if deck.session_numbers.last == cycled_session_number | |
move_flashcard!(flashcard, deck, retired_deck) | |
end | |
end | |
else | |
puts 'Incorrect!' | |
if review_cards.include?(flashcard) | |
move_flashcard!(flashcard, deck_of_flashcard(flashcard), current_deck) | |
end | |
end | |
end | |
def deck_of_flashcard(flashcard) | |
progress_decks.detect { |d| d.include?(flashcard) } | |
end | |
def start | |
cli_inspect | |
puts "Session: #{current_session}" | |
current_set_of_flashcards.each do |fc| | |
puts fc.question + " " + fc.correct_answer | |
answer = gets.strip | |
handle_attempt(fc, answer) | |
end | |
next_session! | |
start unless all_decks_are_empty? | |
end | |
def all_decks_are_empty? | |
current_deck.empty? && progress_decks.all?(&:empty?) | |
end | |
end | |
describe Course do | |
describe '#move_flashcard' do | |
it 'moves card from source deck to target deck' do | |
flashcard = Flashcard.new(question: 'Why', correct_answer: "Because f**k you, that's why!") | |
source_deck = Deck.new(flashcards: [flashcard]) | |
target_deck = Deck.new(flashcards: []) | |
course = Course.new(progress_decks: [source_deck, target_deck]) | |
course.move_flashcard!(flashcard, source_deck, target_deck) | |
expect(source_deck.flashcards).to eq([]) | |
expect(target_deck.flashcards).to eq([flashcard]) | |
end | |
end | |
describe '#handle_attempt' do | |
context 'learner is successful with card from current deck' do | |
it 'moves the card to deck with number == current session number' do | |
flashcard = Flashcard.new(question: 'Why', correct_answer: "Because f**k you, that's why!") | |
current_deck = Deck.new(flashcards: [flashcard]) | |
target_deck = Deck.new(flashcards: []) | |
another_deck = Deck.new(flashcards: []) | |
course = Course.new(current_deck: current_deck, progress_decks: [another_deck, target_deck], current_session: 1) | |
course.handle_attempt(flashcard, "Because f**k you, that's why!") | |
expect(current_deck.flashcards).to eq([]) | |
expect(target_deck.flashcards).to eq([flashcard]) | |
end | |
end | |
context 'learner is not successful with card from current deck' do | |
it 'does not move the card' do | |
flashcard = Flashcard.new(question: 'Why', correct_answer: "Because f**k you, that's why!") | |
current_deck = Deck.new(flashcards: [flashcard]) | |
target_deck = Deck.new(flashcards: []) | |
another_deck = Deck.new(flashcards: []) | |
course = Course.new(current_deck: current_deck, progress_decks: [another_deck, target_deck], current_session: 1) | |
course.handle_attempt(flashcard, "Incorrect answer") | |
expect(current_deck.flashcards).to eq([flashcard]) | |
expect(target_deck.flashcards).to eq([]) | |
end | |
end | |
context 'learner is not successful with review card' do | |
it 'moves card to current deck' do | |
flashcard = Flashcard.new(question: 'Why', correct_answer: "Because f**k you, that's why!") | |
review_flashcard = Flashcard.new(question: 'Question of life', correct_answer: "42") | |
current_deck = Deck.new(flashcards: [flashcard]) | |
deck0 = Deck.new(flashcards: [], session_numbers: [1]) | |
deck1 = Deck.new(flashcards: [review_flashcard], session_numbers: [7, 4, 0]) | |
course = Course.new(current_deck: current_deck, progress_decks: [deck0, deck1], current_session: 0) | |
expect(course.current_set_of_flashcards).to match_array([flashcard, review_flashcard]) | |
course.handle_attempt(review_flashcard, "43") | |
expect(current_deck.flashcards).to match_array([flashcard, review_flashcard]) | |
expect(deck1.flashcards).to eq([]) | |
end | |
end | |
context 'if learner is successful with review card' do | |
context 'when current session number matches last session number of the deck' do | |
it 'moves card to retired' do | |
flashcard = Flashcard.new(question: 'Why', correct_answer: "Because f**k you, that's why!") | |
review_flashcard = Flashcard.new(question: 'Question of life', correct_answer: "42") | |
current_deck = Deck.new(flashcards: [flashcard]) | |
deck0 = Deck.new(flashcards: [], session_numbers: [1]) | |
deck1 = Deck.new(flashcards: [review_flashcard], session_numbers: [7, 4, 0]) | |
retired_deck = Deck.new | |
course = Course.new(current_deck: current_deck, progress_decks: [deck0, deck1], current_session: 0, retired_deck: retired_deck) | |
expect(course.current_set_of_flashcards).to match_array([flashcard, review_flashcard]) | |
course.handle_attempt(review_flashcard, "42") | |
expect(current_deck.flashcards).to match_array([flashcard]) | |
expect(deck0.flashcards).to eq([]) | |
expect(deck1.flashcards).to eq([]) | |
expect(retired_deck.flashcards).to eq([review_flashcard]) | |
end | |
end | |
context 'when current session number does not match last session number of the deck' do | |
it 'does not move the card' do | |
flashcard = Flashcard.new(question: 'Why', correct_answer: "Because f**k you, that's why!") | |
review_flashcard = Flashcard.new(question: 'Question of life', correct_answer: "42") | |
current_deck = Deck.new(flashcards: [flashcard]) | |
deck0 = Deck.new(flashcards: [], session_numbers: [1]) | |
deck1 = Deck.new(flashcards: [review_flashcard], session_numbers: [7, 0, 4]) | |
retired_deck = Deck.new | |
course = Course.new(current_deck: current_deck, progress_decks: [deck0, deck1], current_session: 0, retired_deck: retired_deck) | |
expect(course.current_set_of_flashcards).to match_array([flashcard, review_flashcard]) | |
course.handle_attempt(review_flashcard, "42") | |
expect(current_deck.flashcards).to match_array([flashcard]) | |
expect(deck0.flashcards).to eq([]) | |
expect(deck1.flashcards).to eq([review_flashcard]) | |
expect(retired_deck.flashcards).to eq([]) | |
end | |
end | |
end | |
end | |
end | |
course = Course.new(current_deck: current_deck, progress_decks: progress_decks) | |
puts course.current_set_of_flashcards_inspect | |
course.start |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment