Skip to content
This repository has been archived by the owner on Dec 30, 2018. It is now read-only.

Commit

Permalink
Start splitting out view models by function.
Browse files Browse the repository at this point in the history
  • Loading branch information
cstorey committed Apr 28, 2013
1 parent 0c72f41 commit 98037ea
Show file tree
Hide file tree
Showing 5 changed files with 312 additions and 166 deletions.
104 changes: 38 additions & 66 deletions lib/srsrb/deck_view.rb → lib/srsrb/card_editor_projection.rb
Expand Up @@ -5,7 +5,7 @@
require 'atomic'

module SRSRB
class DeckViewModel
class CardEditorProjection
def initialize event_store
self.event_store = event_store
self.cards = Atomic.new Hamster.hash
Expand All @@ -19,20 +19,6 @@ def start!
event_store.subscribe self
end

def next_card_upto time
return if cards.get.empty?
next_card = cards.get.values.sort_by { |c| c.due_date }.first
next_card if next_card.due_date <= time
end

def card_for id
cards.get[id]
end

def enqueue_card card
update_card(card.id) { card }
end

def card_models
_card_model_ids.get
end
Expand All @@ -51,7 +37,6 @@ def editable_card_for id

def handle_event id, event, _version
case event
when CardReviewed then handle_card_reviewed id, event
when CardEdited then handle_card_edited id, event
when CardModelChanged then handle_card_model_changed id, event
when ModelNamed then handle_model_named id, event
Expand All @@ -60,37 +45,8 @@ def handle_event id, event, _version
end
end

private
def handle_card_reviewed id, event
update_card(id) { |card0|
card0.set_review_count(card0.review_count.to_i.succ).
set_due_date(event.next_due_date)
}
end

def handle_card_edited id, event
model = model_for_card_id id

question = model.format_question_with(event.card_fields)
answer = model.format_answer_with(event.card_fields)

update_card(id) { |card| card.set_question(question).set_answer(answer) }
_editable_cards.update { |oldver| oldver.put(id, EditableCard.new(id: id, fields: event.card_fields)) }
end

def handle_card_model_changed id, event
_card_model_id_by_card.update { |idx| idx.put(id, event.model_id) }
end

def handle_model_templates_changed id, event
update_model(id) { |model|
model ||= CardModel.new id: id
model.set_question_template(event.question).set_answer_template(event.answer)
}
end

def handle_model_named id, event
update_model(id) { |model| model ||= CardFormat.new(id: id); model.set_name(event.name) }
def enqueue_card card
update_card(card.id) { card }
end

def update_card id, &block
Expand All @@ -101,6 +57,18 @@ def update_card id, &block
}
end

def card_for id
cards.get[id]
end

private
def handle_model_field_added id, event
update_model(id) { |old_model|
model = old_model || CardFormat.new(id: id)
model.set_fields model.fields.add(event.field)
}
end

def update_model id, &block
_card_models.update do |old_cards|
old_model = old_cards[id]
Expand All @@ -111,35 +79,39 @@ def update_model id, &block
_card_model_ids.update { |ids| ids.include?(id) ? ids : ids.add(id) }
end

def handle_model_field_added id, event
update_model(id) { |old_model|
model = old_model || CardFormat.new(id: id)
model.set_fields model.fields.add(event.field)
def handle_model_templates_changed id, event
update_model(id) { |model|
model ||= CardFormat.new id: id
model.set_question_template(event.question).set_answer_template(event.answer)
}
end

def model_for_card_id id
model_id = _card_model_id_by_card.get.fetch(id)
_card_models.get.find { |m| true }.last
def handle_card_model_changed id, event
_card_model_id_by_card.update { |idx| idx.put(id, event.model_id) }
end

attr_accessor :queue, :cards, :event_store, :_card_models, :_card_model_ids, :_card_model_id_by_card, :_editable_cards
end
def handle_card_edited id, event
model = model_for_card_id id

class Card < Hamsterdam::Struct.define(:id, :question, :answer, :review_count, :due_date)
def as_json
Hash.new.tap do |h|
self.class.field_names.each do |f|
h[f] = public_send f
end
end
question = model.format_question_with(event.card_fields)
answer = model.format_answer_with(event.card_fields)

update_card(id) { |card| card.set_question(question).set_answer(answer) }
_editable_cards.update { |oldver| oldver.put(id, EditableCard.new(id: id, fields: event.card_fields)) }
end

def due_date
super || 0
def handle_model_named id, event
update_model(id) { |model| model ||= CardFormat.new(id: id); model.set_name(event.name) }
end

def model_for_card_id id
model_id = _card_model_id_by_card.get.fetch(id)
_card_models.get.find { |m| true }.last
end
end

attr_accessor :queue, :cards, :event_store, :_card_models, :_card_model_ids, :_card_model_id_by_card, :_editable_cards
end

class EditableCard < Hamsterdam::Struct.define(:id, :fields)
end

Expand Down
24 changes: 16 additions & 8 deletions lib/srsrb/main.rb
@@ -1,4 +1,5 @@
require 'srsrb/deck_view'
require 'srsrb/review_projection'
require 'srsrb/card_editor_projection'
require 'srsrb/decks'
require 'srsrb/leveldb_event_store'
require 'srsrb/object_patch'
Expand Down Expand Up @@ -31,22 +32,28 @@ def deck_reviews
def card_editing
@card_editing ||= CardEditing.new event_store, models
end
def deck
@deck ||= DeckViewModel.new event_store
def review_projection
@review_projection ||= ReviewProjection.new event_store
end

def card_editor_projection
@card_editor_projection ||= CardEditorProjection.new event_store
end

# We really want layered mixins for this.
def reviews_app
ReviewsApp.new deck, deck_reviews
ReviewsApp.new review_projection, deck_reviews
end

def card_editor_app
CardEditorApp.new deck, card_editing
CardEditorApp.new card_editor_projection, card_editing
end

def model_editor_app
ModelEditorApp.new deck, model_editing
ModelEditorApp.new :model_editor_stub, model_editing
end
def system_test_hack_api
SystemTestHackApi.new(nil, deck, card_editing, model_editing)
SystemTestHackApi.new(nil, review_projection, card_editing, model_editing)
end

def app
Expand All @@ -63,7 +70,8 @@ def app

def assemble
at_exit { shutdown }
deck.start!
review_projection.start!
card_editor_projection.start!
models.start!
app
end
Expand Down
122 changes: 122 additions & 0 deletions lib/srsrb/review_projection.rb
@@ -0,0 +1,122 @@
require 'hamsterdam'
require 'hamster/queue'
require 'hamster/hash'
require 'hamster/vector'
require 'atomic'

module SRSRB
class ReviewProjection
def initialize event_store
self.event_store = event_store
self.cards = Atomic.new Hamster.hash
self._card_models = Atomic.new Hamster.hash
self._card_model_ids = Atomic.new Hamster.vector
self._card_model_id_by_card = Atomic.new Hamster.hash
self._editable_cards = Atomic.new(Hamster.hash)
end

def start!
event_store.subscribe self
end

def next_card_upto time
return if cards.get.empty?
next_card = cards.get.values.sort_by { |c| c.due_date }.first
next_card if next_card.due_date <= time
end

def card_for id
cards.get[id]
end

def enqueue_card card
update_card(card.id) { card }
end

def handle_event id, event, _version
case event
when CardReviewed then handle_card_reviewed id, event
when CardEdited then handle_card_edited id, event
when CardModelChanged then handle_card_model_changed id, event
when ModelTemplatesChanged then handle_model_templates_changed id, event
end
end

private
def handle_card_reviewed id, event
update_card(id) { |card0|
card0.set_review_count(card0.review_count.to_i.succ).
set_due_date(event.next_due_date)
}
end

def handle_card_edited id, event
model = model_for_card_id id

question = model.format_question_with(event.card_fields)
answer = model.format_answer_with(event.card_fields)

update_card(id) { |card| card.set_question(question).set_answer(answer) }
_editable_cards.update { |oldver| oldver.put(id, EditableCard.new(id: id, fields: event.card_fields)) }
end

def handle_card_model_changed id, event
_card_model_id_by_card.update { |idx| idx.put(id, event.model_id) }
end

def handle_model_templates_changed id, event
update_model(id) { |model|
model ||= CardFormat.new id: id
model.set_question_template(event.question).set_answer_template(event.answer)
}
end

def update_card id, &block
cards.update { |oldver|
oldver.fetch(id) { Card.new id: id }.
into { |old_card| block.call old_card }.
into { |new_card| oldver.put(id, new_card) }
}
end

def update_model id, &block
_card_models.update do |old_cards|
old_model = old_cards[id]
new_model = block.call old_model
old_cards.put id, new_model
end

_card_model_ids.update { |ids| ids.include?(id) ? ids : ids.add(id) }
end

def handle_model_field_added id, event
update_model(id) { |old_model|
model = old_model || CardFormat.new(id: id)
model.set_fields model.fields.add(event.field)
}
end

def model_for_card_id id
model_id = _card_model_id_by_card.get.fetch(id)
_card_models.get.find { |m| true }.last
end

attr_accessor :queue, :cards, :event_store, :_card_models, :_card_model_ids, :_card_model_id_by_card, :_editable_cards
end

class Card < Hamsterdam::Struct.define(:id, :question, :answer, :review_count, :due_date)
def as_json
Hash.new.tap do |h|
self.class.field_names.each do |f|
h[f] = public_send f
end
end
end

def due_date
super || 0
end
end


end

0 comments on commit 98037ea

Please sign in to comment.