Skip to content

Instantly share code, notes, and snippets.

@kryachkov
Created March 19, 2018 21:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kryachkov/94a58304dc9f21a0be0d6aac4a245f0f to your computer and use it in GitHub Desktop.
Save kryachkov/94a58304dc9f21a0be0d6aac4a245f0f to your computer and use it in GitHub Desktop.
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