From 8e0e82762406df9e009cd52f28a207b274999824 Mon Sep 17 00:00:00 2001 From: giangduong36 Date: Wed, 11 Apr 2018 06:26:31 -0500 Subject: [PATCH 1/5] Elm done --- elm-todo/Todo.elm | 34 +++------------------------------- 1 file changed, 3 insertions(+), 31 deletions(-) diff --git a/elm-todo/Todo.elm b/elm-todo/Todo.elm index 3a07b24..0817cbb 100755 --- a/elm-todo/Todo.elm +++ b/elm-todo/Todo.elm @@ -45,7 +45,6 @@ type alias Model = type alias Entry = { description : String , completed : Bool - , editing : Bool , id : Int } @@ -62,7 +61,6 @@ newEntry : String -> Int -> Entry newEntry desc id = { description = desc , completed = False - , editing = False , id = id } @@ -76,7 +74,6 @@ to them. -} type Msg = UpdateNewEntryField String - | EditingEntry Int Bool | UpdateEntry Int String | Add | Delete Int @@ -102,19 +99,6 @@ update msg model = UpdateNewEntryField str -> { model | newEntryField = str } - EditingEntry id isEditing -> - let - updateEntry t = - if t.id == id then - { t | editing = isEditing } - else - t - - focus = - Dom.focus ("todo-" ++ toString id) - in - { model | entries = List.map updateEntry model.entries } - UpdateEntry id task -> let updateEntry t = @@ -229,7 +213,7 @@ viewKeyedEntry todo = viewEntry : Entry -> Html Msg viewEntry todo = li - [ classList [ ( "completed", todo.completed ), ( "editing", todo.editing ) ] ] + [ classList [ ( "completed", todo.completed )] ] [ div [ class "view" ] [ input @@ -240,7 +224,7 @@ viewEntry todo = ] [] , label - [ onDoubleClick (EditingEntry todo.id True) ] + [] [ text todo.description ] , button [ class "destroy" @@ -248,20 +232,9 @@ viewEntry todo = ] [] ] - , input - [ class "edit" - , value todo.description - , name "title" - , id ("todo-" ++ toString todo.id) - , onInput (UpdateEntry todo.id) - , onBlur (EditingEntry todo.id False) - , onEnter (EditingEntry todo.id False) - ] - [] ] - -- VIEW CONTROLS AND FOOTER @@ -313,8 +286,7 @@ viewControlsClear entriesCompleted = infoFooter : Html msg infoFooter = footer [ class "info" ] - [ p [] [ text "Double-click to edit a todo" ] - , p [] + [ p [] [ text "Written by " , a [ href "https://github.com/evancz" ] [ text "Evan Czaplicki" ] ] From 2d048e09005a651ea89907daf6fb7b4a5e43ef34 Mon Sep 17 00:00:00 2001 From: giangduong36 Date: Wed, 11 Apr 2018 11:15:20 -0500 Subject: [PATCH 2/5] Attempt ruby --- ruby-todo/lib/engine.rb | 6 ++++-- ruby-todo/lib/messages.rb | 39 ++++++++++++++++++++++++++++------- ruby-todo/lib/model.rb | 2 +- ruby-todo/test/test_helper.rb | 4 ++-- ruby-todo/test/todo_test.rb | 4 ++-- 5 files changed, 41 insertions(+), 14 deletions(-) diff --git a/ruby-todo/lib/engine.rb b/ruby-todo/lib/engine.rb index a257c20..eebad9e 100644 --- a/ruby-todo/lib/engine.rb +++ b/ruby-todo/lib/engine.rb @@ -4,9 +4,11 @@ def self.run(*args) end def self.run_with_history(model, messages) + puts model.inspect messages.map do |msg| - msg.apply_to(model) - model + # puts "ENGINE:" + model.inspect + model = msg.apply_to(model) + model end end end diff --git a/ruby-todo/lib/messages.rb b/ruby-todo/lib/messages.rb index abe85de..395ccbf 100644 --- a/ruby-todo/lib/messages.rb +++ b/ruby-todo/lib/messages.rb @@ -2,13 +2,25 @@ module Msg class Add def apply_to(model) + + new_entries = model.entries.dup unless model.new_entry_field.blank? - model.entries << Entry.new( + # model.entries << Entry.new( + # description: model.new_entry_field, + # id: model.next_id) + new_entry = Entry.new( description: model.new_entry_field, id: model.next_id) + + new_entries << new_entry end - model.next_id += 1 - model.new_entry_field = "" + # model.next_id += 1 + # model.new_entry_field = "" + # puts "ADD:" + new_entries.to_s + Model.new( + entries: new_entries, + new_entry_field: "", + next_id: model.next_id + 1) end end @@ -20,7 +32,12 @@ def initialize(str) attr_reader :str def apply_to(model) - model.new_entry_field = str + # model.new_entry_field = str + + Model.new( + entries: model.entries.dup, # dup or not + new_entry_field: str, + next_id: model.next_id) end end @@ -32,11 +49,13 @@ def initialize(id, is_completed) attr_reader :id, :is_completed def apply_to(model) - model.entries.each do |entry| + new_model = model.dup + new_model.entries.each do |entry| if entry.id == id entry.completed = is_completed end end + new_model end end @@ -48,13 +67,19 @@ def initialize(id) attr_reader :id def apply_to(model) - model.entries.reject! { |e| e.id == id } + new_model = model.dup + new_model.entries.reject! { |e| e.id == id } + # puts "DELETE", model.inspect, new_model.inspect + new_model end end class DeleteAllCompleted def apply_to(model) - model.entries.reject!(&:completed) + new_model = model.dup + new_model.entries.reject!(&:completed) + new_model + # model.dup.entries.reject!(&:completed) end end diff --git a/ruby-todo/lib/model.rb b/ruby-todo/lib/model.rb index 75a6085..bdfccc1 100644 --- a/ruby-todo/lib/model.rb +++ b/ruby-todo/lib/model.rb @@ -5,7 +5,7 @@ def initialize(entries: [], new_entry_field: "", next_id: nil) (entries.lazy.map(&:id).max || -1) + 1 end - attr_accessor :entries, :new_entry_field, :next_id + attr_reader :entries, :new_entry_field, :next_id def ==(other) !other.nil? && diff --git a/ruby-todo/test/test_helper.rb b/ruby-todo/test/test_helper.rb index 17e4fcb..1ae63c9 100644 --- a/ruby-todo/test/test_helper.rb +++ b/ruby-todo/test/test_helper.rb @@ -8,5 +8,5 @@ # To see full test names when running tests: # -# require "minitest/reporters" -# Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new +require "minitest/reporters" +Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new diff --git a/ruby-todo/test/todo_test.rb b/ruby-todo/test/todo_test.rb index f7436c7..6692abf 100644 --- a/ruby-todo/test/todo_test.rb +++ b/ruby-todo/test/todo_test.rb @@ -91,7 +91,7 @@ end it "supports time travel" do - skip "Mutable model does not support time travel" + # skip "Mutable model does not support time travel" actual_history = Engine.run_with_history(Model.new, [ Msg::UpdateNewEntryField.new("go forward in time"), @@ -163,4 +163,4 @@ end end -end +end \ No newline at end of file From f0c7e3ed2e31325630e6ec118894eab17d65ef41 Mon Sep 17 00:00:00 2001 From: giangduong36 Date: Wed, 11 Apr 2018 11:49:08 -0500 Subject: [PATCH 3/5] All tests passed but need polishing --- ruby-todo/lib/messages.rb | 39 +++++++++++++++------- swift-todo/Sources/Todo/Engine.swift | 5 +-- swift-todo/Sources/Todo/Message.swift | 28 +++++++++++----- swift-todo/Sources/Todo/Model.swift | 4 +-- swift-todo/Tests/TodoTests/TodoTests.swift | 6 ++-- 5 files changed, 56 insertions(+), 26 deletions(-) diff --git a/ruby-todo/lib/messages.rb b/ruby-todo/lib/messages.rb index 395ccbf..4747c73 100644 --- a/ruby-todo/lib/messages.rb +++ b/ruby-todo/lib/messages.rb @@ -49,13 +49,18 @@ def initialize(id, is_completed) attr_reader :id, :is_completed def apply_to(model) - new_model = model.dup - new_model.entries.each do |entry| + new_entries = [] + model.entries.each do |entry| if entry.id == id - entry.completed = is_completed + new_entries << Entry.new(id: entry.id, description: entry.description, completed: is_completed) + else + new_entries << Entry.new(id: entry.id, description: entry.description, completed: entry.completed) end end - new_model + Model.new( + entries: new_entries, + new_entry_field: model.new_entry_field, + next_id: model.next_id) end end @@ -67,19 +72,29 @@ def initialize(id) attr_reader :id def apply_to(model) - new_model = model.dup - new_model.entries.reject! { |e| e.id == id } - # puts "DELETE", model.inspect, new_model.inspect - new_model + new_entries = [] + model.entries.each do |entry| + new_entries << Entry.new(id: entry.id, description: entry.description, completed: entry.completed) + end + new_entries.reject! { |e| e.id == id } + Model.new( + entries: new_entries, + new_entry_field: model.new_entry_field, + next_id: model.next_id) end end class DeleteAllCompleted def apply_to(model) - new_model = model.dup - new_model.entries.reject!(&:completed) - new_model - # model.dup.entries.reject!(&:completed) + new_entries = [] + model.entries.each do |entry| + new_entries << Entry.new(id: entry.id, description: entry.description, completed: entry.completed) + end + new_entries.reject!(&:completed) + Model.new( + entries: new_entries, + new_entry_field: model.new_entry_field, + next_id: model.next_id) end end diff --git a/swift-todo/Sources/Todo/Engine.swift b/swift-todo/Sources/Todo/Engine.swift index e3b14a7..8373ea5 100644 --- a/swift-todo/Sources/Todo/Engine.swift +++ b/swift-todo/Sources/Todo/Engine.swift @@ -13,9 +13,10 @@ struct Engine { } static func runWithHistory(on model: Model, applying messages: [Message]) -> [Model] { + var newModel = model return messages.map { message in - message.apply(to: model) - return model + newModel = message.apply(to: newModel) + return newModel } } } diff --git a/swift-todo/Sources/Todo/Message.swift b/swift-todo/Sources/Todo/Message.swift index 92dd868..65c0230 100644 --- a/swift-todo/Sources/Todo/Message.swift +++ b/swift-todo/Sources/Todo/Message.swift @@ -14,30 +14,42 @@ enum Message { case delete(Int) case deleteAllCompleted - func apply(to model: Model) { + func apply(to model: Model) -> Model { switch(self) { case .add: + var new_entries = model.entries if !model.newEntryField.isBlank() { - model.entries.append(Entry(id: model.nextID, description: model.newEntryField)) + new_entries.append(Entry(id: model.nextID, description: model.newEntryField)) } - model.nextID += 1 - model.newEntryField = "" + return Model(nextID: model.nextID + 1, newEntryField: "", entries: new_entries) case .updateNewEntryField(let str): - model.newEntryField = str + return Model(nextID: model.nextID, newEntryField: str, entries: model.entries) case .check(let id, let isCompleted): + var new_entries = [Entry]() for entry in model.entries { if(entry.id == id) { - entry.completed = isCompleted + new_entries.append(Entry(id: entry.id, + description: entry.description, + completed: isCompleted)) + } else{ + new_entries.append(entry) } } + return Model(nextID: model.nextID, newEntryField: model.newEntryField, entries: new_entries) + case .delete(let id): - model.entries.remove { $0.id == id } + var new_entries = model.entries + new_entries.remove { $0.id == id } + return Model(nextID: model.nextID, newEntryField: model.newEntryField, entries: new_entries) + case .deleteAllCompleted: - model.entries.remove { $0.completed } + var new_entries = model.entries + new_entries.remove { $0.completed } + return Model(nextID: model.nextID, newEntryField: model.newEntryField, entries: new_entries) } } } diff --git a/swift-todo/Sources/Todo/Model.swift b/swift-todo/Sources/Todo/Model.swift index 1cca801..d50d863 100644 --- a/swift-todo/Sources/Todo/Model.swift +++ b/swift-todo/Sources/Todo/Model.swift @@ -1,4 +1,4 @@ -class Model { +struct Model { var entries: [Entry] var newEntryField: String var nextID: Int @@ -11,7 +11,7 @@ class Model { } } -class Entry { +struct Entry { var id: Int var description: String var completed: Bool diff --git a/swift-todo/Tests/TodoTests/TodoTests.swift b/swift-todo/Tests/TodoTests/TodoTests.swift index 9220517..a8094ae 100644 --- a/swift-todo/Tests/TodoTests/TodoTests.swift +++ b/swift-todo/Tests/TodoTests/TodoTests.swift @@ -26,6 +26,8 @@ class TodoTests: XCTestCase { .updateNewEntryField("hop on one foot"), .add ]) + + print(newModel.newEntryField) XCTAssertEqual(3, newModel.entries.count) let newEntry = newModel.entries.last! XCTAssertEqual(12, newEntry.id) @@ -77,7 +79,7 @@ class TodoTests: XCTestCase { XCTAssertEqual([11], newModel.entries.map { $0.id }) } -/* + func testTimeTravel() { let actualHistory = Engine.runWithHistory(on: Model(), applying: [ .updateNewEntryField("go forward in time"), @@ -145,6 +147,6 @@ class TodoTests: XCTestCase { XCTAssertEqual(expected, actual, "History mismatch at step \(index)") } } -*/ + } From ff956e8d7deef7930b3a1b9c80cc151b8b486ad6 Mon Sep 17 00:00:00 2001 From: giangduong36 Date: Fri, 13 Apr 2018 14:08:52 -0500 Subject: [PATCH 4/5] Update Swift part --- swift-todo/Sources/Todo/Message.swift | 40 +++++++++++++-------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/swift-todo/Sources/Todo/Message.swift b/swift-todo/Sources/Todo/Message.swift index 65c0230..6d57d49 100644 --- a/swift-todo/Sources/Todo/Message.swift +++ b/swift-todo/Sources/Todo/Message.swift @@ -17,39 +17,37 @@ enum Message { func apply(to model: Model) -> Model { switch(self) { case .add: - var new_entries = model.entries + var model = model if !model.newEntryField.isBlank() { - new_entries.append(Entry(id: model.nextID, description: model.newEntryField)) + model.entries.append(Entry(id: model.nextID, description: model.newEntryField)) } - return Model(nextID: model.nextID + 1, newEntryField: "", entries: new_entries) + model.nextID += 1 + model.newEntryField = "" + return model case .updateNewEntryField(let str): - return Model(nextID: model.nextID, newEntryField: str, entries: model.entries) + var model = model + model.newEntryField = str + return model case .check(let id, let isCompleted): - var new_entries = [Entry]() - for entry in model.entries { - if(entry.id == id) { - new_entries.append(Entry(id: entry.id, - description: entry.description, - completed: isCompleted)) - } else{ - new_entries.append(entry) + var model = model + for (index, _) in model.entries.enumerated() { + if(model.entries[index].id == id) { + model.entries[index].completed = isCompleted } } - return Model(nextID: model.nextID, newEntryField: model.newEntryField, entries: new_entries) - + return model case .delete(let id): - var new_entries = model.entries - new_entries.remove { $0.id == id } - return Model(nextID: model.nextID, newEntryField: model.newEntryField, entries: new_entries) - + var model = model + model.entries.remove { $0.id == id } + return model case .deleteAllCompleted: - var new_entries = model.entries - new_entries.remove { $0.completed } - return Model(nextID: model.nextID, newEntryField: model.newEntryField, entries: new_entries) + var model = model + model.entries.remove { $0.completed } + return model } } } From c74e961c03bc302a6d0521195f147db009cbe3eb Mon Sep 17 00:00:00 2001 From: giangduong36 Date: Fri, 13 Apr 2018 15:11:02 -0500 Subject: [PATCH 5/5] Update Ruby part --- elm-todo/Todo.elm | 12 +---- ruby-todo/lib/engine.rb | 4 +- ruby-todo/lib/messages.rb | 51 ++++++++++++++-------- swift-todo/Tests/TodoTests/TodoTests.swift | 1 - 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/elm-todo/Todo.elm b/elm-todo/Todo.elm index 0817cbb..f755be8 100755 --- a/elm-todo/Todo.elm +++ b/elm-todo/Todo.elm @@ -74,13 +74,13 @@ to them. -} type Msg = UpdateNewEntryField String - | UpdateEntry Int String | Add | Delete Int | DeleteAllCompleted | Check Int Bool + -- How we update our Model on a given Msg? update : Msg -> Model -> Model update msg model = @@ -99,16 +99,6 @@ update msg model = UpdateNewEntryField str -> { model | newEntryField = str } - UpdateEntry id task -> - let - updateEntry t = - if t.id == id then - { t | description = task } - else - t - in - { model | entries = List.map updateEntry model.entries } - Check id isCompleted -> let updateEntry t = diff --git a/ruby-todo/lib/engine.rb b/ruby-todo/lib/engine.rb index eebad9e..c28e9a2 100644 --- a/ruby-todo/lib/engine.rb +++ b/ruby-todo/lib/engine.rb @@ -4,11 +4,9 @@ def self.run(*args) end def self.run_with_history(model, messages) - puts model.inspect messages.map do |msg| - # puts "ENGINE:" + model.inspect model = msg.apply_to(model) - model + model end end end diff --git a/ruby-todo/lib/messages.rb b/ruby-todo/lib/messages.rb index 4747c73..0a1cc2f 100644 --- a/ruby-todo/lib/messages.rb +++ b/ruby-todo/lib/messages.rb @@ -2,21 +2,21 @@ module Msg class Add def apply_to(model) + # copy model.entries to a new array of entries + new_entries = [] + model.entries.each do |entry| + new_entries << Entry.new( + id: entry.id, + description: entry.description, + completed: entry.completed) + end - new_entries = model.entries.dup unless model.new_entry_field.blank? - # model.entries << Entry.new( - # description: model.new_entry_field, - # id: model.next_id) - new_entry = Entry.new( + new_entries << Entry.new( description: model.new_entry_field, id: model.next_id) - - new_entries << new_entry end - # model.next_id += 1 - # model.new_entry_field = "" - # puts "ADD:" + new_entries.to_s + Model.new( entries: new_entries, new_entry_field: "", @@ -32,10 +32,17 @@ def initialize(str) attr_reader :str def apply_to(model) - # model.new_entry_field = str + # copy model.entries to a new array of entries + new_entries = [] + model.entries.each do |entry| + new_entries << Entry.new( + id: entry.id, + description: entry.description, + completed: entry.completed) + end Model.new( - entries: model.entries.dup, # dup or not + entries: new_entries, new_entry_field: str, next_id: model.next_id) end @@ -51,11 +58,11 @@ def initialize(id, is_completed) def apply_to(model) new_entries = [] model.entries.each do |entry| - if entry.id == id - new_entries << Entry.new(id: entry.id, description: entry.description, completed: is_completed) - else - new_entries << Entry.new(id: entry.id, description: entry.description, completed: entry.completed) - end + new_complete_status = (entry.id == id) ? is_completed : entry.completed + new_entries << Entry.new( + id: entry.id, + description: entry.description, + completed: new_complete_status) end Model.new( entries: new_entries, @@ -74,7 +81,10 @@ def initialize(id) def apply_to(model) new_entries = [] model.entries.each do |entry| - new_entries << Entry.new(id: entry.id, description: entry.description, completed: entry.completed) + new_entries << Entry.new( + id: entry.id, + description: entry.description, + completed: entry.completed) end new_entries.reject! { |e| e.id == id } Model.new( @@ -88,7 +98,10 @@ class DeleteAllCompleted def apply_to(model) new_entries = [] model.entries.each do |entry| - new_entries << Entry.new(id: entry.id, description: entry.description, completed: entry.completed) + new_entries << Entry.new( + id: entry.id, + description: entry.description, + completed: entry.completed) end new_entries.reject!(&:completed) Model.new( diff --git a/swift-todo/Tests/TodoTests/TodoTests.swift b/swift-todo/Tests/TodoTests/TodoTests.swift index a8094ae..4cdd5a0 100644 --- a/swift-todo/Tests/TodoTests/TodoTests.swift +++ b/swift-todo/Tests/TodoTests/TodoTests.swift @@ -27,7 +27,6 @@ class TodoTests: XCTestCase { .add ]) - print(newModel.newEntryField) XCTAssertEqual(3, newModel.entries.count) let newEntry = newModel.entries.last! XCTAssertEqual(12, newEntry.id)