Skip to content

Commit

Permalink
feat: recursive updater
Browse files Browse the repository at this point in the history
  • Loading branch information
linsyking committed Jun 18, 2023
1 parent 42a2641 commit 0e31c60
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 108 deletions.
2 changes: 1 addition & 1 deletion elm.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "linsyking/messenger-core",
"summary": "Core library for Messenger.",
"license": "BSD-3-Clause",
"version": "5.0.0",
"version": "6.0.0",
"exposed-modules": {
"Definitions": [
"Messenger.Recursion",
Expand Down
17 changes: 9 additions & 8 deletions src/Messenger/GeneralModel.elm
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ General model is designed to be an abstract interface of scenes, layers, compone
- a: data type
- b: environment type
- d: message type
- e: target type
- f: render type
- c: message type
- d: target type
- e: render type
@docs GeneralModel
@docs viewModelList, viewModelArray
Expand All @@ -29,24 +29,25 @@ import Array exposing (Array)
This has a name field.
-}
type alias GeneralModel a b d e f =
type alias GeneralModel a b c d e =
{ name : String
, data : a
, update : b -> d -> a -> ( a, List ( e, d ), b )
, view : b -> a -> f
, update : b -> a -> ( a, List ( d, c ), b )
, updaterec : b -> c -> a -> ( a, List ( d, c ), b )
, view : b -> a -> e
}


{-| View model list.
-}
viewModelList : b -> List (GeneralModel a b d e f) -> List f
viewModelList : b -> List (GeneralModel a b c d e) -> List e
viewModelList env models =
List.map (\model -> model.view env model.data) models


{-| View model array.
-}
viewModelArray : b -> Array (GeneralModel a b d e f) -> List f
viewModelArray : b -> Array (GeneralModel a b c d e) -> List e
viewModelArray env models =
Array.toList models
|> List.map (\model -> model.view env model.data)
7 changes: 7 additions & 0 deletions src/Messenger/Recursion.elm
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ c: environment messages
d: target
-}
type alias Updater a b c d =
a -> c -> ( a, List ( d, b ), c )


{-| The recursive updater
-}
type alias RecUpdater a b c d =
a -> c -> b -> ( a, List ( d, b ), c )


Expand Down Expand Up @@ -51,6 +57,7 @@ Pass this as an argument to the updater
-}
type alias RecBody a b c d =
{ update : Updater a b c d
, updaterec : RecUpdater a b c d
, match : Matcher a d
, super : Super d
, clean : Cleaner c
Expand Down
58 changes: 9 additions & 49 deletions src/Messenger/RecursionArray.elm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module Messenger.RecursionArray exposing
( updateObjects, updateObjectsWithTarget
, getObjectIndices, getObjectIndex, getObjects, getObject, updateObjectByIndex, updateObjectsByTarget
, getObjectIndices, getObjectIndex, getObjects, getObject
)

{-|
Expand All @@ -15,7 +15,7 @@ Array implementation for the recursion algorithm
## Tools
@docs getObjectIndices, getObjectIndex, getObjects, getObject, updateObjectByIndex, updateObjectsByTarget
@docs getObjectIndices, getObjectIndex, getObjects, getObject
-}

Expand All @@ -26,11 +26,11 @@ import Messenger.Recursion exposing (Matcher, RecBody)

{-| Recursively update all the objects in the List
-}
updateObjects : RecBody a b c d -> c -> b -> Array a -> ( Array a, List b, c )
updateObjects rec env msg objs =
updateObjects : RecBody a b c d -> c -> Array a -> ( Array a, List b, c )
updateObjects rec env objs =
let
( newObjs, ( newMsgUnfinished, newMsgFinished ), newEnv ) =
updateOnce rec env msg objs
updateOnce rec env objs
in
updateRemain rec (rec.clean newEnv) ( newMsgUnfinished, newMsgFinished ) newObjs

Expand All @@ -46,13 +46,13 @@ updateObjectsWithTarget rec env msgs objs =
-- Below are all helper functions


updateOnce : RecBody a b c d -> c -> b -> Array a -> ( Array a, ( List ( d, b ), List b ), c )
updateOnce rec env msg objs =
updateOnce : RecBody a b c d -> c -> Array a -> ( Array a, ( List ( d, b ), List b ), c )
updateOnce rec env objs =
Array.foldr
(\ele ( lastObjs, ( lastMsgUnfinished, lastMsgFinished ), lastEnv ) ->
let
( newObj, newMsg, newEnv ) =
rec.update ele lastEnv msg
rec.update ele lastEnv

finishedMsg =
List.filterMap
Expand Down Expand Up @@ -115,7 +115,7 @@ updateRemain rec env ( unfinishedMsg, finishedMsg ) objs =
(\msg ( lastObj2, ( lastMsgUnfinished2, lastMsgFinished2 ), lastEnv2 ) ->
let
( newEle, newMsgs, newEnv3 ) =
rec.update lastObj2 lastEnv2 msg
rec.updaterec lastObj2 lastEnv2 msg

finishedMsgs =
List.filterMap
Expand Down Expand Up @@ -201,43 +201,3 @@ getObjects matcher tar objs =
getObject : Matcher a d -> d -> Array a -> Maybe a
getObject matcher tar objs =
Array.get 0 <| getObjects matcher tar objs


{-| Update the object by index
-}
updateObjectByIndex : RecBody a b c d -> c -> b -> Int -> Array a -> ( Array a, List ( d, b ), c )
updateObjectByIndex rec env msg index objs =
case Array.get index objs of
Nothing ->
( objs, [], env )

Just obj ->
let
( newObj, newMsg, newEnv ) =
rec.update obj env msg
in
( Array.set index newObj objs, newMsg, newEnv )


{-| Update all the objects that match the target
-}
updateObjectsByTarget : RecBody a b c d -> c -> b -> d -> Array a -> ( Array a, List ( d, b ), c )
updateObjectsByTarget rec env msg tar objs =
let
( newObjs, newMsg, newEnv ) =
Array.foldl
(\obj ( lastObjs, lastMsg, lastEnv ) ->
if rec.match obj tar then
let
( newObj, newMsg2, newEnv2 ) =
rec.update obj lastEnv msg
in
( Array.push newObj lastObjs, lastMsg ++ newMsg2, newEnv2 )

else
( Array.push obj lastObjs, lastMsg, lastEnv )
)
( Array.empty, [], env )
objs
in
( newObjs, newMsg, newEnv )
60 changes: 10 additions & 50 deletions src/Messenger/RecursionList.elm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module Messenger.RecursionList exposing
( updateObjects, updateObjectsWithTarget
, getObjectByIndex, getObjectIndices, getObjectIndex, getObjects, getObject, updateObjectByIndex, updateObjectsByTarget
, getObjectByIndex, getObjectIndices, getObjectIndex, getObjects, getObject
)

{-|
Expand All @@ -15,7 +15,7 @@ List implementation for the recursion algorithm
## Tools
@docs getObjectByIndex, getObjectIndices, getObjectIndex, getObjects, getObject, updateObjectByIndex, updateObjectsByTarget
@docs getObjectByIndex, getObjectIndices, getObjectIndex, getObjects, getObject
-}

Expand All @@ -25,11 +25,11 @@ import Messenger.Recursion exposing (Matcher, RecBody)

{-| Recursively update all the objects in the List
-}
updateObjects : RecBody a b c d -> c -> b -> List a -> ( List a, List b, c )
updateObjects rec env msg objs =
updateObjects : RecBody a b c d -> c -> List a -> ( List a, List b, c )
updateObjects rec env objs =
let
( newObjs, ( newMsgUnfinished, newMsgFinished ), newEnv ) =
updateOnce rec env msg objs
updateOnce rec env objs
in
updateRemain rec (rec.clean newEnv) ( newMsgUnfinished, newMsgFinished ) newObjs

Expand All @@ -42,16 +42,16 @@ updateObjectsWithTarget rec env msgs objs =



-- Below are all helper functions
-- Below are some helper functions


updateOnce : RecBody a b c d -> c -> b -> List a -> ( List a, ( List ( d, b ), List b ), c )
updateOnce rec env msg objs =
updateOnce : RecBody a b c d -> c -> List a -> ( List a, ( List ( d, b ), List b ), c )
updateOnce rec env objs =
List.foldr
(\ele ( lastObjs, ( lastMsgUnfinished, lastMsgFinished ), lastEnv ) ->
let
( newObj, newMsg, newEnv ) =
rec.update ele lastEnv msg
rec.update ele lastEnv

finishedMsg =
List.filterMap
Expand Down Expand Up @@ -110,7 +110,7 @@ updateRemain rec env ( unfinishedMsg, finishedMsg ) objs =
(\msg ( lastObj2, ( lastMsgUnfinished2, lastMsgFinished2 ), lastEnv2 ) ->
let
( newEle, newMsgs, newEnv3 ) =
rec.update lastObj2 lastEnv2 msg
rec.updaterec lastObj2 lastEnv2 msg

finishedMsgs =
List.filterMap
Expand Down Expand Up @@ -176,43 +176,3 @@ getObjects matcher tar objs =
getObject : Matcher a d -> d -> List a -> Maybe a
getObject matcher tar objs =
List.Extra.find (\x -> matcher x tar) objs


{-| Update the object by index
-}
updateObjectByIndex : RecBody a b c d -> c -> b -> Int -> List a -> ( List a, List ( d, b ), c )
updateObjectByIndex rec env msg index objs =
case List.Extra.getAt index objs of
Nothing ->
( objs, [], env )

Just obj ->
let
( newObj, newMsg, newEnv ) =
rec.update obj env msg
in
( List.Extra.setAt index newObj objs, newMsg, newEnv )


{-| Update all the objects that match the target
-}
updateObjectsByTarget : RecBody a b c d -> c -> b -> d -> List a -> ( List a, List ( d, b ), c )
updateObjectsByTarget rec env msg tar objs =
let
( newObjs, newMsg, newEnv ) =
List.foldl
(\obj ( lastObjs, lastMsg, lastEnv ) ->
if rec.match obj tar then
let
( newObj, newMsg2, newEnv2 ) =
rec.update obj lastEnv msg
in
( lastObjs ++ [ newObj ], lastMsg ++ newMsg2, newEnv2 )

else
( lastObjs ++ [ obj ], lastMsg, lastEnv )
)
( [], [], env )
objs
in
( newObjs, newMsg, newEnv )

0 comments on commit 0e31c60

Please sign in to comment.