From ed5dd38507b0c3d61204f33c50bab9c89d581c0c Mon Sep 17 00:00:00 2001 From: Piper Niehaus Date: Fri, 18 Nov 2016 17:24:48 -0700 Subject: [PATCH 01/23] broken wip --- src/elm/Main.elm | 96 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/src/elm/Main.elm b/src/elm/Main.elm index 5b655ca..def62b1 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -125,7 +125,97 @@ update msg model = } -getNeighbors : Point -> List Point + +-- starting points are the places where the first letter matches + + +updateGuess : String -> String +updateGuess guess = + -- guess - the first letter + guess + + +type alias StartingPoints = + List Point + + +toPath : Point -> Path +toPath point = + [ point ] + + +matchingNeighbors : BoardDict -> Point -> String -> List Point +matchingNeighbors board point letter = + let + matchList ( x, y ) = + Set.toList <| + Set.remove ( x, y ) <| + Set.fromList + [ ( max (x - 1) 0, max (y - 1) 0 ) + , ( max (x - 1) 0, y ) + , ( max (x - 1) 0, min (y + 1) boardWidth ) + , ( x, max (y - 1) 0 ) + , ( x, min (y + 1) boardWidth ) + , ( min (x + 1) boardWidth, max (y - 1) 0 ) + , ( min (x + 1) boardWidth, y ) + , ( min (x + 1) boardWidth, min (y + 1) boardWidth ) + ] + + isMatch : Point -> Tile -> Bool + isMatch point tile = + (List.member point matchList) && tile.letter == letter + in + Dict.keys <| Dict.filter isMatch board + + +explorePath : BoardDict -> Path -> String -> Path +explorePath board path word = + let + lastPoint : path -> point + lastPoint path = + List.drop 1 path + + shortenedWord word = + String.dropLeft 1 word + + travel : BoardDict -> String -> Path -> Path + travel board path word = + List.append (matchingNeighbors board (lastPoint path) word) path + in + if String.length word > 0 then + explorePath board (travel board path word) <| shortenedWord word + else + path + + +findPaths : StartingPoints -> Paths +findPaths startingPoints = + -- iterate through starting points + List.map (\point -> explorePath (toPath point) "remainingGuess") startingPoints + + +type alias Path = + List Point + + +type alias Paths = + List Path + + + +-- +-- updateGuess(guess) +-- startingPoints = List(tuple) +-- startingPoints.each ( +-- path = explorePoint([point], remainingWord)) +-- if path then update dictionary with things in path +--explorePoint(list, word) +-- if word is nil return list +-- else if no neighbords return nil +-- getNeighbors(tail(list)).filter(neighbor.letter == firstLetter word, explorePoint(list+neighbor, remainingWord)) + + +getNeighbors : Point -> Tile -> Bool getNeighbors ( x, y ) = Set.toList <| Set.remove ( x, y ) <| @@ -141,6 +231,10 @@ getNeighbors ( x, y ) = ] +type alias Entry = + ( Point, Tile ) + + checkTile : String -> Point -> Tile -> Tile checkTile guessLetter location tile = { tile | match = (guessLetter == tile.letter) } From 73d219eae7e71a35ebb3a73652941add4a0da472 Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Sat, 19 Nov 2016 22:54:18 -0700 Subject: [PATCH 02/23] cleanup wip --- src/elm/Main.elm | 138 +++++++++++++++-------------------------------- 1 file changed, 44 insertions(+), 94 deletions(-) diff --git a/src/elm/Main.elm b/src/elm/Main.elm index def62b1..4fea18c 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -5,6 +5,7 @@ import Html.Attributes exposing (placeholder, value, classList, class) import Html.Events exposing (onClick, onInput) import Dict exposing (Dict) import Set exposing (Set) +import Array exposing (Array) -- APP @@ -39,6 +40,22 @@ type alias Row = List Tile +type alias StartingPoints = + List Point + + +type alias Path = + List Point + + +type alias Paths = + List Path + + +type alias BoardDict = + Dict Point Tile + + model : Model model = { board = board, score = 0, currentGuess = "" } @@ -76,6 +93,11 @@ type Msg | UpdateGuess String +firstLetter : String -> String +firstLetter string = + String.slice 0 1 string + + update : Msg -> Model -> Model update msg model = case msg of @@ -90,13 +112,13 @@ update msg model = UpdateGuess guess -> let - firstLetter : String -> String - firstLetter string = - String.slice 0 1 string + checkTile : String -> Tile -> Tile + checkTile guessLetter tile = + { tile | match = (guessLetter == tile.letter) } matchFirstLetter : Point -> Tile -> Tile matchFirstLetter point tile = - checkTile (firstLetter guess) point tile + checkTile (firstLetter guess) tile isMatching : Point -> Tile -> Bool isMatching _ tile = @@ -109,15 +131,16 @@ update msg model = Dict.filter isMatching <| Dict.map matchFirstLetter model.board - mappingThingy : Point -> Tile -> Tile - mappingThingy point tile = + findNeighbors : Point -> Tile -> Tile + findNeighbors point tile = if List.member point neighborList then { tile | match = True } else tile + -- findMatches : Point -> Tile -> Path newDict = - Dict.map mappingThingy model.board + Dict.map findNeighbors board in { model | currentGuess = guess @@ -125,97 +148,37 @@ update msg model = } - --- starting points are the places where the first letter matches - - -updateGuess : String -> String -updateGuess guess = - -- guess - the first letter - guess - - -type alias StartingPoints = - List Point - - -toPath : Point -> Path -toPath point = - [ point ] - - -matchingNeighbors : BoardDict -> Point -> String -> List Point -matchingNeighbors board point letter = - let - matchList ( x, y ) = - Set.toList <| - Set.remove ( x, y ) <| - Set.fromList - [ ( max (x - 1) 0, max (y - 1) 0 ) - , ( max (x - 1) 0, y ) - , ( max (x - 1) 0, min (y + 1) boardWidth ) - , ( x, max (y - 1) 0 ) - , ( x, min (y + 1) boardWidth ) - , ( min (x + 1) boardWidth, max (y - 1) 0 ) - , ( min (x + 1) boardWidth, y ) - , ( min (x + 1) boardWidth, min (y + 1) boardWidth ) - ] - - isMatch : Point -> Tile -> Bool - isMatch point tile = - (List.member point matchList) && tile.letter == letter - in - Dict.keys <| Dict.filter isMatch board - - explorePath : BoardDict -> Path -> String -> Path explorePath board path word = let - lastPoint : path -> point + lastPoint : Path -> Maybe Point lastPoint path = - List.drop 1 path + Array.get ((List.length path) - 1) (Array.fromList path) shortenedWord word = String.dropLeft 1 word travel : BoardDict -> String -> Path -> Path - travel board path word = - List.append (matchingNeighbors board (lastPoint path) word) path + travel board word path = + List.append (matchingNeighbors board (lastPoint path) (firstLetter word)) path in if String.length word > 0 then - explorePath board (travel board path word) <| shortenedWord word + explorePath board (travel board word path) <| shortenedWord word else path -findPaths : StartingPoints -> Paths -findPaths startingPoints = - -- iterate through starting points - List.map (\point -> explorePath (toPath point) "remainingGuess") startingPoints - - -type alias Path = - List Point - - -type alias Paths = - List Path - - - --- --- updateGuess(guess) --- startingPoints = List(tuple) --- startingPoints.each ( --- path = explorePoint([point], remainingWord)) --- if path then update dictionary with things in path ---explorePoint(list, word) --- if word is nil return list --- else if no neighbords return nil --- getNeighbors(tail(list)).filter(neighbor.letter == firstLetter word, explorePoint(list+neighbor, remainingWord)) +matchingNeighbors : BoardDict -> Maybe Point -> String -> List Point +matchingNeighbors board point letter = + let + isMatch : Point -> Tile -> Bool + isMatch point tile = + (List.member point <| getNeighbors point) && tile.letter == letter + in + Dict.keys <| Dict.filter isMatch board -getNeighbors : Point -> Tile -> Bool +getNeighbors : Point -> List Point getNeighbors ( x, y ) = Set.toList <| Set.remove ( x, y ) <| @@ -231,19 +194,6 @@ getNeighbors ( x, y ) = ] -type alias Entry = - ( Point, Tile ) - - -checkTile : String -> Point -> Tile -> Tile -checkTile guessLetter location tile = - { tile | match = (guessLetter == tile.letter) } - - -type alias BoardDict = - Dict Point Tile - - getBoardDict : Board -> BoardDict getBoardDict board = let From fba76416567f287a379737e679e12481c52bb23a Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Sat, 19 Nov 2016 23:27:25 -0700 Subject: [PATCH 03/23] almost working at path finding somehow --- src/elm/Main.elm | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/elm/Main.elm b/src/elm/Main.elm index 4fea18c..fe1be79 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -6,6 +6,7 @@ import Html.Events exposing (onClick, onInput) import Dict exposing (Dict) import Set exposing (Set) import Array exposing (Array) +import Debug exposing (..) -- APP @@ -120,6 +121,20 @@ update msg model = matchFirstLetter point tile = checkTile (firstLetter guess) tile + findPath : List Point + findPath = + log "stuff" + (List.concatMap + (\point -> (log "path" (explorePath model.board [ point ] guess))) + <| + Dict.keys firstLetterMatches + ) + + firstLetterMatches : BoardDict + firstLetterMatches = + Dict.filter isMatching <| + Dict.map matchFirstLetter model.board + isMatching : Point -> Tile -> Bool isMatching _ tile = tile.match @@ -133,7 +148,7 @@ update msg model = findNeighbors : Point -> Tile -> Tile findNeighbors point tile = - if List.member point neighborList then + if List.member point (log "fn path" findPath) then { tile | match = True } else tile @@ -160,10 +175,10 @@ explorePath board path word = travel : BoardDict -> String -> Path -> Path travel board word path = - List.append (matchingNeighbors board (lastPoint path) (firstLetter word)) path + List.append (log "matching neighbors" (matchingNeighbors board (lastPoint path) (firstLetter word))) path in if String.length word > 0 then - explorePath board (travel board word path) <| shortenedWord word + log "path" (explorePath board (travel board word path) <| shortenedWord word) else path @@ -171,11 +186,16 @@ explorePath board path word = matchingNeighbors : BoardDict -> Maybe Point -> String -> List Point matchingNeighbors board point letter = let - isMatch : Point -> Tile -> Bool - isMatch point tile = - (List.member point <| getNeighbors point) && tile.letter == letter + isMatch : Point -> Point -> Tile -> Bool + isMatch origin point tile = + (List.member point <| getNeighbors origin) && (tile.letter == letter) in - Dict.keys <| Dict.filter isMatch board + case point of + Just value -> + Dict.keys <| Dict.filter (isMatch value) board + + Nothing -> + [] getNeighbors : Point -> List Point From 01436b41816feea7c72bc9c61edbf20ce84d03fc Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Sat, 19 Nov 2016 23:35:10 -0700 Subject: [PATCH 04/23] small refactor --- src/elm/Main.elm | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/elm/Main.elm b/src/elm/Main.elm index fe1be79..0bd955d 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -148,14 +148,20 @@ update msg model = findNeighbors : Point -> Tile -> Tile findNeighbors point tile = + if List.member point neighborList then + { tile | match = True } + else + tile + + findMatches : Point -> Tile -> Tile + findMatches point tile = if List.member point (log "fn path" findPath) then { tile | match = True } else tile - -- findMatches : Point -> Tile -> Path newDict = - Dict.map findNeighbors board + Dict.map findMatches board in { model | currentGuess = guess From dad62c59f739180476d36ab46472523cdb42b845 Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Sat, 19 Nov 2016 23:45:07 -0700 Subject: [PATCH 05/23] this works as long as all letters are unique --- src/elm/Main.elm | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/elm/Main.elm b/src/elm/Main.elm index 0bd955d..c2fe83d 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -146,13 +146,6 @@ update msg model = Dict.filter isMatching <| Dict.map matchFirstLetter model.board - findNeighbors : Point -> Tile -> Tile - findNeighbors point tile = - if List.member point neighborList then - { tile | match = True } - else - tile - findMatches : Point -> Tile -> Tile findMatches point tile = if List.member point (log "fn path" findPath) then @@ -174,7 +167,7 @@ explorePath board path word = let lastPoint : Path -> Maybe Point lastPoint path = - Array.get ((List.length path) - 1) (Array.fromList path) + Array.get 0 (Array.fromList path) shortenedWord word = String.dropLeft 1 word From e5995aa1b83504a38179e234e1e6ff911c5a082f Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Sun, 20 Nov 2016 00:56:46 -0700 Subject: [PATCH 06/23] find paths awesomely. make board bigger --- src/elm/Main.elm | 50 ++++++++++++++++++++++++------------- src/static/styles/main.scss | 4 ++- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/src/elm/Main.elm b/src/elm/Main.elm index c2fe83d..f13abd2 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -6,7 +6,6 @@ import Html.Events exposing (onClick, onInput) import Dict exposing (Dict) import Set exposing (Set) import Array exposing (Array) -import Debug exposing (..) -- APP @@ -64,14 +63,19 @@ model = boardWidth : Int boardWidth = - 3 + 5 board : BoardDict board = let letters = - [ [ "a", "b", "a" ], [ "a", "d", "k" ], [ "p", "w", "z" ] ] + [ [ "l", "r", "e", "o", "s" ] + , [ "e", "d", "i", "w", "f" ] + , [ "j", "e", "m", "w", "e" ] + , [ "a", "f", "l", "t", "r" ] + , [ "o", "s", "a", "h", "h" ] + ] tilesForRow : List String -> Row tilesForRow row = @@ -121,11 +125,11 @@ update msg model = matchFirstLetter point tile = checkTile (firstLetter guess) tile - findPath : List Point - findPath = - log "stuff" - (List.concatMap - (\point -> (log "path" (explorePath model.board [ point ] guess))) + findPaths : List Path + findPaths = + List.concat <| + (List.map + (\point -> (explorePath model.board [ point ] (shortenedWord guess))) <| Dict.keys firstLetterMatches ) @@ -148,7 +152,7 @@ update msg model = findMatches : Point -> Tile -> Tile findMatches point tile = - if List.member point (log "fn path" findPath) then + if List.member point (List.concat findPaths) then { tile | match = True } else tile @@ -162,24 +166,35 @@ update msg model = } -explorePath : BoardDict -> Path -> String -> Path +shortenedWord : String -> String +shortenedWord word = + String.dropLeft 1 word + + +explorePath : BoardDict -> Path -> String -> List Path explorePath board path word = let lastPoint : Path -> Maybe Point lastPoint path = Array.get 0 (Array.fromList path) - shortenedWord word = - String.dropLeft 1 word - - travel : BoardDict -> String -> Path -> Path + travel : BoardDict -> String -> Path -> List Path travel board word path = - List.append (log "matching neighbors" (matchingNeighbors board (lastPoint path) (firstLetter word))) path + List.map + (\match -> + if (not <| List.member match path) then + List.append [ match ] path + else + [] + ) + (matchingNeighbors board (lastPoint path) (firstLetter word)) + + -- TODO only append neighbors that don't already exist in if String.length word > 0 then - log "path" (explorePath board (travel board word path) <| shortenedWord word) + List.concatMap (\aPath -> (explorePath board aPath <| shortenedWord word)) (travel board word path) else - path + [ path ] matchingNeighbors : BoardDict -> Maybe Point -> String -> List Point @@ -247,5 +262,4 @@ view model = [ input [ placeholder "Guess away!", onInput UpdateGuess, value model.currentGuess ] [] , button [ onClick ScoreWord ] [ text "Check" ] ] - , div [] [ text <| toString model.board ] ] diff --git a/src/static/styles/main.scss b/src/static/styles/main.scss index 6e7b25c..5a31e79 100644 --- a/src/static/styles/main.scss +++ b/src/static/styles/main.scss @@ -5,7 +5,7 @@ $icon-font-path: '~bootstrap-sass/assets/fonts/bootstrap/'; // can add Boostrap overrides, additional Sass/CSS below... .boardContainer { - width: 200px; + width: 350px; } .letter { display: inline-block; @@ -15,6 +15,8 @@ $icon-font-path: '~bootstrap-sass/assets/fonts/bootstrap/'; text-transform: uppercase; border: 1px solid blue; background-color: #EEE; + height: 60px; + width: 60px; } .letter--highlighted { background-color: #cc33ff; From f5dbc580ee707a252f00c978538709c4fc01ddcc Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Sun, 20 Nov 2016 00:58:05 -0700 Subject: [PATCH 07/23] todo is done --- src/elm/Main.elm | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/elm/Main.elm b/src/elm/Main.elm index f13abd2..f29ac65 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -188,8 +188,6 @@ explorePath board path word = [] ) (matchingNeighbors board (lastPoint path) (firstLetter word)) - - -- TODO only append neighbors that don't already exist in if String.length word > 0 then List.concatMap (\aPath -> (explorePath board aPath <| shortenedWord word)) (travel board word path) From 543e291baa43d7c33088787dabf0f7d1fc076044 Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Sun, 20 Nov 2016 01:02:19 -0700 Subject: [PATCH 08/23] only highlight the first match --- src/elm/Main.elm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/elm/Main.elm b/src/elm/Main.elm index f29ac65..f8b3221 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -152,7 +152,7 @@ update msg model = findMatches : Point -> Tile -> Tile findMatches point tile = - if List.member point (List.concat findPaths) then + if List.member point (Maybe.withDefault [] (List.head findPaths)) then { tile | match = True } else tile From ec741d4d21261e2e53bc6a42a9da699e70903867 Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Sat, 3 Dec 2016 16:33:16 -0700 Subject: [PATCH 09/23] score valid guesses --- src/elm/Main.elm | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/elm/Main.elm b/src/elm/Main.elm index f8b3221..ccce6c1 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -21,7 +21,7 @@ main = type alias Model = - { board : BoardDict, score : Int, currentGuess : String } + { board : BoardDict, score : Int, currentGuess : String, foundWords : List String, hasMatch : Bool } type alias Board = @@ -58,7 +58,7 @@ type alias BoardDict = model : Model model = - { board = board, score = 0, currentGuess = "" } + { board = board, score = 0, currentGuess = "", foundWords = [], hasMatch = False } boardWidth : Int @@ -111,7 +111,16 @@ update msg model = ScoreWord -> { model - | score = model.score + (String.length model.currentGuess) + | score = + if model.hasMatch then + model.score + (String.length model.currentGuess) + else + model.score + , foundWords = + if model.hasMatch then + model.currentGuess :: model.foundWords + else + model.foundWords , currentGuess = "" } @@ -127,12 +136,13 @@ update msg model = findPaths : List Path findPaths = - List.concat <| - (List.map - (\point -> (explorePath model.board [ point ] (shortenedWord guess))) - <| - Dict.keys firstLetterMatches - ) + List.filter (\path -> List.length path == String.length guess) <| + List.concat <| + (List.map + (\point -> (explorePath model.board [ point ] (shortenedWord guess))) + <| + Dict.keys firstLetterMatches + ) firstLetterMatches : BoardDict firstLetterMatches = @@ -163,6 +173,7 @@ update msg model = { model | currentGuess = guess , board = newDict + , hasMatch = not <| Dict.isEmpty (Dict.filter (\key tile -> tile.match == True) newDict) } @@ -260,4 +271,6 @@ view model = [ input [ placeholder "Guess away!", onInput UpdateGuess, value model.currentGuess ] [] , button [ onClick ScoreWord ] [ text "Check" ] ] + , div [] [ text <| toString model.board ] + , text (toString model.foundWords) ] From 71d28ce177bdd204fbf10f57918e0c4a93bee43c Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Fri, 27 Jan 2017 15:49:46 -0700 Subject: [PATCH 10/23] wip - things turn green. focus stuff in here is bs --- elm-package.json | 1 + src/elm/Main.elm | 40 +++++++++++++++++++++++++++---------- src/static/styles/main.scss | 12 +++++++++++ 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/elm-package.json b/elm-package.json index 2fdb466..81bf85f 100644 --- a/elm-package.json +++ b/elm-package.json @@ -9,6 +9,7 @@ "exposed-modules": [], "dependencies": { "elm-lang/core": "5.0.0 <= v < 6.0.0", + "elm-lang/dom": "1.1.1 <= v < 2.0.0", "elm-lang/html": "2.0.0 <= v < 3.0.0", "elm-lang/http": "1.0.0 <= v < 2.0.0", "evancz/elm-markdown": "3.0.1 <= v < 4.0.0" diff --git a/src/elm/Main.elm b/src/elm/Main.elm index ccce6c1..9ae8c16 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -1,11 +1,13 @@ module Main exposing (..) +import Platform exposing (Task) import Html exposing (..) import Html.Attributes exposing (placeholder, value, classList, class) import Html.Events exposing (onClick, onInput) import Dict exposing (Dict) import Set exposing (Set) import Array exposing (Array) +import Dom exposing (focus, Error) -- APP @@ -21,7 +23,7 @@ main = type alias Model = - { board : BoardDict, score : Int, currentGuess : String, foundWords : List String, hasMatch : Bool } + { board : BoardDict, score : Int, currentGuess : String, foundWords : List String, hasMatch : Bool, guessed : Bool, correct : Bool, doFocus : Task Dom.Error () } type alias Board = @@ -58,7 +60,15 @@ type alias BoardDict = model : Model model = - { board = board, score = 0, currentGuess = "", foundWords = [], hasMatch = False } + { board = board + , score = 0 + , currentGuess = "" + , foundWords = [] + , hasMatch = False + , guessed = False + , correct = False + , doFocus = Dom.focus "guess-input" + } boardWidth : Int @@ -112,16 +122,18 @@ update msg model = ScoreWord -> { model | score = - if model.hasMatch then + if model.hasMatch && not (List.member model.currentGuess model.foundWords) then model.score + (String.length model.currentGuess) else model.score , foundWords = - if model.hasMatch then + if model.hasMatch && not (List.member model.currentGuess model.foundWords) then model.currentGuess :: model.foundWords else model.foundWords , currentGuess = "" + , guessed = True + , correct = model.hasMatch } UpdateGuess guess -> @@ -174,6 +186,7 @@ update msg model = | currentGuess = guess , board = newDict , hasMatch = not <| Dict.isEmpty (Dict.filter (\key tile -> tile.match == True) newDict) + , guessed = False } @@ -263,14 +276,21 @@ view model = makeTile tile = span [ classList [ ( "letter", True ), ( "letter--highlighted", tile.match ) ] ] [ text tile.letter ] + + makeFoundWord word = + div [ class "foundWord" ] [ text word ] in div [] - [ h2 [] [ text <| toString model.score ] - , div [ class "boardContainer" ] (List.map makeTile <| Dict.values model.board) - , div [] - [ input [ placeholder "Guess away!", onInput UpdateGuess, value model.currentGuess ] [] - , button [ onClick ScoreWord ] [ text "Check" ] + [ div [ classList [ ( "game", True ), ( "guessed", model.guessed ), ( "correct", model.correct ) ] ] + [ div [] + [ h2 [] [ text <| "Score: " ++ toString model.score ] + , div [ class "boardContainer" ] (List.map makeTile <| Dict.values model.board) + , div [] + [ input [ Html.Attributes.id "guess-input", placeholder "Guess away!", onInput UpdateGuess, value model.currentGuess ] [] + , button [ onClick ScoreWord ] [ text "Check" ] + ] + ] + , div [ class "foundWordContainer" ] <| [ h2 [] [ text "Found Words" ] ] ++ (List.map makeFoundWord model.foundWords) ] , div [] [ text <| toString model.board ] - , text (toString model.foundWords) ] diff --git a/src/static/styles/main.scss b/src/static/styles/main.scss index 5a31e79..1415a07 100644 --- a/src/static/styles/main.scss +++ b/src/static/styles/main.scss @@ -3,6 +3,13 @@ $icon-font-path: '~bootstrap-sass/assets/fonts/bootstrap/'; @import '~bootstrap-sass/assets/stylesheets/_bootstrap.scss'; // can add Boostrap overrides, additional Sass/CSS below... +.game { + display: flex; +} + +.guessed .letter--highlighted { + background-color: #8cc174; +} .boardContainer { width: 350px; @@ -21,3 +28,8 @@ $icon-font-path: '~bootstrap-sass/assets/fonts/bootstrap/'; .letter--highlighted { background-color: #cc33ff; } + +.foundWordContainer { + font-size: 20px; + padding-left: 50px; +} From f92f8742911f9e6fd1d4937db5147d7468dd5a39 Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Fri, 27 Jan 2017 16:41:37 -0700 Subject: [PATCH 11/23] awesomesauce --- src/elm/Main.elm | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/elm/Main.elm b/src/elm/Main.elm index 9ae8c16..5aaba3c 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -1,6 +1,6 @@ module Main exposing (..) -import Platform exposing (Task) +import Task exposing (Task) import Html exposing (..) import Html.Attributes exposing (placeholder, value, classList, class) import Html.Events exposing (onClick, onInput) @@ -15,7 +15,12 @@ import Dom exposing (focus, Error) main : Program Never Model Msg main = - Html.beginnerProgram { model = model, view = view, update = update } + Html.program { init = init, subscriptions = subscriptions, view = view, update = update } + + +subscriptions : Model -> Sub Msg +subscriptions model = + Sub.none @@ -23,7 +28,7 @@ main = type alias Model = - { board : BoardDict, score : Int, currentGuess : String, foundWords : List String, hasMatch : Bool, guessed : Bool, correct : Bool, doFocus : Task Dom.Error () } + { board : BoardDict, score : Int, currentGuess : String, foundWords : List String, hasMatch : Bool, guessed : Bool, correct : Bool } type alias Board = @@ -67,7 +72,6 @@ model = , hasMatch = False , guessed = False , correct = False - , doFocus = Dom.focus "guess-input" } @@ -113,14 +117,19 @@ firstLetter string = String.slice 0 1 string -update : Msg -> Model -> Model +init : ( Model, Cmd Msg ) +init = + ( model, Cmd.none ) + + +update : Msg -> Model -> ( Model, Cmd Msg ) update msg model = case msg of NoOp -> - model + ( model, Cmd.none ) ScoreWord -> - { model + ( { model | score = if model.hasMatch && not (List.member model.currentGuess model.foundWords) then model.score + (String.length model.currentGuess) @@ -134,7 +143,9 @@ update msg model = , currentGuess = "" , guessed = True , correct = model.hasMatch - } + } + , Task.attempt (always NoOp) (Dom.focus "guess-input") + ) UpdateGuess guess -> let @@ -182,12 +193,14 @@ update msg model = newDict = Dict.map findMatches board in - { model + ( { model | currentGuess = guess , board = newDict , hasMatch = not <| Dict.isEmpty (Dict.filter (\key tile -> tile.match == True) newDict) , guessed = False - } + } + , Cmd.none + ) shortenedWord : String -> String @@ -292,5 +305,4 @@ view model = ] , div [ class "foundWordContainer" ] <| [ h2 [] [ text "Found Words" ] ] ++ (List.map makeFoundWord model.foundWords) ] - , div [] [ text <| toString model.board ] ] From 0890c23af884f8e645f0ae87398c55e428e0fa37 Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Fri, 24 Feb 2017 09:55:31 -0700 Subject: [PATCH 12/23] update readme --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 316832a..af2fbf7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ -# elm-webpack-starter +# LADY BOGGLE + +Boggle written in elm by ladies + A simple Webpack setup for writing [Elm](http://elm-lang.org/) apps: From 2b8c9b3216e52003d4be71a676c7310af46ebda8 Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Fri, 24 Feb 2017 12:03:27 -0700 Subject: [PATCH 13/23] enter key submits the word --- elm-package.json | 1 + src/elm/Main.elm | 37 ++++++++++++++++++++++++++++++++----- src/favicon.ico | Bin 1150 -> 1150 bytes src/static/index.html | 6 +++--- 4 files changed, 36 insertions(+), 8 deletions(-) diff --git a/elm-package.json b/elm-package.json index 81bf85f..49cc74a 100644 --- a/elm-package.json +++ b/elm-package.json @@ -12,6 +12,7 @@ "elm-lang/dom": "1.1.1 <= v < 2.0.0", "elm-lang/html": "2.0.0 <= v < 3.0.0", "elm-lang/http": "1.0.0 <= v < 2.0.0", + "elm-lang/keyboard": "1.0.1 <= v < 2.0.0", "evancz/elm-markdown": "3.0.1 <= v < 4.0.0" }, "elm-version": "0.18.0 <= v < 0.19.0" diff --git a/src/elm/Main.elm b/src/elm/Main.elm index 5aaba3c..41e37b1 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -3,11 +3,20 @@ module Main exposing (..) import Task exposing (Task) import Html exposing (..) import Html.Attributes exposing (placeholder, value, classList, class) -import Html.Events exposing (onClick, onInput) +import Html.Events exposing (onClick, onInput, on) import Dict exposing (Dict) import Set exposing (Set) import Array exposing (Array) import Dom exposing (focus, Error) +import Json.Decode as Json +import Keyboard exposing (presses) +import Char exposing (fromCode) + + +onKeypress : msg -> Attribute msg +onKeypress message = + on "keypress" (Json.succeed message) + -- APP @@ -20,7 +29,7 @@ main = subscriptions : Model -> Sub Msg subscriptions model = - Sub.none + Keyboard.presses (\code -> Presses (Char.fromCode code)) @@ -109,7 +118,9 @@ board = type Msg = NoOp | ScoreWord - | UpdateGuess String + | UpdateGuessWord String + | CheckKey + | Presses Char firstLetter : String -> String @@ -125,6 +136,12 @@ init = update : Msg -> Model -> ( Model, Cmd Msg ) update msg model = case msg of + Presses code -> + if code == '\x0D' then + (update ScoreWord model) + else + (update NoOp model) + NoOp -> ( model, Cmd.none ) @@ -147,7 +164,7 @@ update msg model = , Task.attempt (always NoOp) (Dom.focus "guess-input") ) - UpdateGuess guess -> + UpdateGuessWord guess -> let checkTile : String -> Tile -> Tile checkTile guessLetter tile = @@ -202,6 +219,9 @@ update msg model = , Cmd.none ) + CheckKey -> + ( model, Cmd.none ) + shortenedWord : String -> String shortenedWord word = @@ -299,7 +319,14 @@ view model = [ h2 [] [ text <| "Score: " ++ toString model.score ] , div [ class "boardContainer" ] (List.map makeTile <| Dict.values model.board) , div [] - [ input [ Html.Attributes.id "guess-input", placeholder "Guess away!", onInput UpdateGuess, value model.currentGuess ] [] + [ input + [ Html.Attributes.id "guess-input" + , onKeypress CheckKey + , placeholder "Guess away!" + , onInput UpdateGuessWord + , value model.currentGuess + ] + [] , button [ onClick ScoreWord ] [ text "Check" ] ] ] diff --git a/src/favicon.ico b/src/favicon.ico index ad6e719a405327b248d4a2cad30896d17bf1ca03..df8564f8cedd37aa34b94f451219e316f8cb5be6 100644 GIT binary patch literal 1150 zcmbW0%MHRX5CvZ(3do5w;zTn!(*gz13UwgS1VvB)Qtq6?ZnPsI%fTN<&aCWsUJ@tL zV8=LWZI_+2x9ViwhYr?<^=yUBW!f>udg;rjaJ14h$-Rc7mSp)d>RUKUBqNvq2*(z2 zlbOqZh9f1;n*3KdAg-4DcjD;D$I+9|y~CD#@>143KRH|c_x|yhnA?B6wfz15@U_yn Un1865%OcU|yYx9rC33y<3)*W`K>z>% literal 1150 zcmds%-%FEW6vrQ(mqPzZ@Zh|0ZZcZskj4mp)5z>WVbM|Y!OWC{8 z+I019E9S=BLYFzI=C3eV$tvigcJb+XUmGo`7+&_gocBC@&-tE*=X?*35DoHcX%X^& zNStmG!YqX7lqMmGY~#`iA!8jfs9SY4sty`$r^ro^JNJ&(eOkmo~Qz>m567o^y0e zIJlCSB$7+=I34Hk%`VIy8~Z(79PwQw_GX@`Y@BSdz_V95l-VdFA%(FgD)$m$)U?LK zjD|n=oKks<+Y*oFGYm%+UT(alxVgc#8HKNvZ+x#*m`Y5e&T3?r7s)Iwu)6t<_0oH; z&UpForOe#oJcae5tQkXJG|E0Y^Fdb2B~Ew;Xb$$#r1oNxeccssax!*<)LMa4{t--*JqA{d zAJqFV`MN*$bcj8{enY3~Jm{M3eRQ7VnhQ&4z{oZ9(lz_3pPp-I>+g}XVE@BBNbO}z t&#BfmI5qrQyxx87`So&Y^Zpn9?m*vfeXYIYzxMk5+ovy6eFt{xe*l(~Y~KI? diff --git a/src/static/index.html b/src/static/index.html index 0a666cc..73ea69e 100644 --- a/src/static/index.html +++ b/src/static/index.html @@ -3,9 +3,9 @@ - elm-webpack-starter - - + Boggle + + From b0cb6d26cf4c6ea1bd2a6d5c10ce4ac40e867a26 Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Fri, 24 Feb 2017 15:03:50 -0700 Subject: [PATCH 14/23] boggle looks up words and reacts accordingly --- package.json | 3 ++ src/elm/Main.elm | 102 +++++++++++++++++++++++++++++------- src/static/styles/main.scss | 8 +++ 3 files changed, 95 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index ce77c82..a05fbb3 100644 --- a/package.json +++ b/package.json @@ -34,5 +34,8 @@ "webpack": "^1.13.1", "webpack-dev-server": "^1.14.1", "webpack-merge": "^0.16.0" + }, + "dependencies": { + "glob": "^7.1.1" } } diff --git a/src/elm/Main.elm b/src/elm/Main.elm index 41e37b1..32da514 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -8,17 +8,12 @@ import Dict exposing (Dict) import Set exposing (Set) import Array exposing (Array) import Dom exposing (focus, Error) -import Json.Decode as Json +import Http +import Json.Decode as Decode import Keyboard exposing (presses) import Char exposing (fromCode) -onKeypress : msg -> Attribute msg -onKeypress message = - on "keypress" (Json.succeed message) - - - -- APP @@ -27,17 +22,60 @@ main = Html.program { init = init, subscriptions = subscriptions, view = view, update = update } + +-- SUBSCRIPTIONS + + subscriptions : Model -> Sub Msg subscriptions model = Keyboard.presses (\code -> Presses (Char.fromCode code)) +-- HTTP + + +authenticatedGet : String -> Decode.Decoder String -> Http.Request String +authenticatedGet url decoder = + Http.request + { method = "GET" + , headers = [ Http.header "X-Mashape-Key" "7RhzLqB7x0mshfh5YE2afEP7Ngkxp1xigQqjsnKy6oDuQ7CfkC" ] + , body = Http.emptyBody + , url = url + , expect = Http.expectJson decoder + , timeout = Nothing + , withCredentials = False + } + + +lookUpWord : String -> Cmd Msg +lookUpWord word = + let + url = + "https://wordsapiv1.p.mashape.com/words/" ++ word + in + Http.send DefineWord (authenticatedGet url decodeGifUrl) + + +decodeGifUrl : Decode.Decoder String +decodeGifUrl = + Decode.at [ "word" ] Decode.string + + + -- MODEL type alias Model = - { board : BoardDict, score : Int, currentGuess : String, foundWords : List String, hasMatch : Bool, guessed : Bool, correct : Bool } + { board : BoardDict + , score : Int + , currentGuess : String + , foundWords : List String + , hasMatch : Bool + , guessed : Bool + , correct : Maybe Bool + , definition : Maybe String + } type alias Board = @@ -80,7 +118,8 @@ model = , foundWords = [] , hasMatch = False , guessed = False - , correct = False + , correct = Nothing + , definition = Nothing } @@ -119,8 +158,8 @@ type Msg = NoOp | ScoreWord | UpdateGuessWord String - | CheckKey | Presses Char + | DefineWord (Result Http.Error String) firstLetter : String -> String @@ -146,20 +185,51 @@ update msg model = ( model, Cmd.none ) ScoreWord -> + -- TODO add a let to encapsulate this hasmatch not member stuffff ( { model | score = if model.hasMatch && not (List.member model.currentGuess model.foundWords) then model.score + (String.length model.currentGuess) else model.score - , foundWords = + , guessed = True + , currentGuess = if model.hasMatch && not (List.member model.currentGuess model.foundWords) then + model.currentGuess + else + "" + , correct = + if (List.member model.currentGuess model.foundWords) then + Just True + else + Nothing + } + , (if model.hasMatch && not (List.member model.currentGuess model.foundWords) then + lookUpWord model.currentGuess + else + Cmd.none + ) + ) + + DefineWord (Ok definition) -> + ( { model + | definition = Just (definition) + , currentGuess = "" + , correct = Just model.hasMatch + , foundWords = + if not (List.member model.currentGuess model.foundWords) then model.currentGuess :: model.foundWords else model.foundWords + } + , Task.attempt (always NoOp) (Dom.focus "guess-input") + ) + + DefineWord (Err _) -> + ( { model + | definition = Nothing , currentGuess = "" - , guessed = True - , correct = model.hasMatch + , correct = Just False } , Task.attempt (always NoOp) (Dom.focus "guess-input") ) @@ -219,9 +289,6 @@ update msg model = , Cmd.none ) - CheckKey -> - ( model, Cmd.none ) - shortenedWord : String -> String shortenedWord word = @@ -314,14 +381,13 @@ view model = div [ class "foundWord" ] [ text word ] in div [] - [ div [ classList [ ( "game", True ), ( "guessed", model.guessed ), ( "correct", model.correct ) ] ] + [ div [ classList [ ( "game", True ), ( "guessed", model.guessed ), ( "pending", model.correct == Nothing ), ( "correct", model.correct == Just True ) ] ] [ div [] [ h2 [] [ text <| "Score: " ++ toString model.score ] , div [ class "boardContainer" ] (List.map makeTile <| Dict.values model.board) , div [] [ input [ Html.Attributes.id "guess-input" - , onKeypress CheckKey , placeholder "Guess away!" , onInput UpdateGuessWord , value model.currentGuess diff --git a/src/static/styles/main.scss b/src/static/styles/main.scss index 1415a07..7d39133 100644 --- a/src/static/styles/main.scss +++ b/src/static/styles/main.scss @@ -8,9 +8,17 @@ $icon-font-path: '~bootstrap-sass/assets/fonts/bootstrap/'; } .guessed .letter--highlighted { + background-color: #f2ac9f; +} + +.correct.guessed .letter--highlighted { background-color: #8cc174; } +.pending.guessed .letter--highlighted { + background-color: #f8ffc6; +} + .boardContainer { width: 350px; } From f01941421ed9d8664fde1c9af2e2a1f3547207b4 Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Sat, 25 Feb 2017 11:37:46 -0700 Subject: [PATCH 15/23] add a board randomizer that is seeded with the current time when the app is loaded --- src/elm/BoardRandomizer.elm | 131 ++++++++++++++++++++++++++++++++++++ src/elm/Main.elm | 68 ++++++++++++++----- src/static/index.js | 2 +- src/static/styles/main.scss | 2 +- 4 files changed, 185 insertions(+), 18 deletions(-) create mode 100644 src/elm/BoardRandomizer.elm diff --git a/src/elm/BoardRandomizer.elm b/src/elm/BoardRandomizer.elm new file mode 100644 index 0000000..ae41c9f --- /dev/null +++ b/src/elm/BoardRandomizer.elm @@ -0,0 +1,131 @@ +port module BoardRandomizer exposing (createRandomBoard) + +import Html +import Random exposing (int, initialSeed, generate, step) + + +createRandomBoard : Int -> Int -> List (List String) +createRandomBoard width seed = + List.map + (\row -> List.map decodeNumberToLetter row) + ((groupInto width + (randomSequence width seed) + ) + ) + + +randomSequence : Int -> Int -> List Int +randomSequence width seed = + let + gen = + Random.list (width * width) (Random.int 0 150) + + s = + initialSeed seed + + ( res, ns ) = + step gen s + in + res + + +groupInto : Int -> List a -> List (List a) +groupInto groups initial = + let + len = + List.length initial + + n = + len // groups + in + List.repeat groups [] + |> List.indexedMap + (\i _ -> + List.take n (List.drop (n * i) initial) + ) + + +decodeNumberToLetter : Int -> String +decodeNumberToLetter num = + if num < 19 then + "e" + else if num < 32 then + "t" + else if num < 44 then + "a" + else if num < 56 then + "r" + else if num < 67 then + "i" + else if num < 78 then + "n" + else if num < 89 then + "o" + else if num < 98 then + "s" + else if num < 104 then + "d" + else if num < 109 then + "c" + else if num < 114 then + "h" + else if num < 119 then + "l" + else if num < 123 then + "f" + else if num < 127 then + "m" + else if num < 131 then + "p" + else if num < 135 then + "u" + else if num < 138 then + "g" + else if num < 141 then + "y" + else if num < 143 then + "w" + else if num < 144 then + "b" + else if num < 145 then + "j" + else if num < 146 then + "k" + else if num < 147 then + "q" + else if num < 148 then + "v" + else if num < 149 then + "x" + else + "z" + + + +--frequencies +-- 19 e +-- 13 t 32 +-- 12 a 44 +-- 12 r 56 +-- 11 i 67 +-- 11 n 78 +-- 11 o 89 +-- 9 s 98 +-- 6 d 104 +-- 5 c 109 +-- 5 h 114 +-- 5 l 119 +-- 4 f 123 +-- 4 m 127 +-- 4 p 131 +-- 4 u 135 +-- 3 g 138 +-- 3 y 141 +-- 2 w 143 +-- 1 b 144 +-- 1 j 145 +-- 1 k 146 +-- 1 q 147 +-- 1 v 148 +-- 1 x 149 +-- 1 z 150 diff --git a/src/elm/Main.elm b/src/elm/Main.elm index 32da514..cbedc42 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -12,14 +12,15 @@ import Http import Json.Decode as Decode import Keyboard exposing (presses) import Char exposing (fromCode) +import BoardRandomizer -- APP -main : Program Never Model Msg +main : Program Flags Model Msg main = - Html.program { init = init, subscriptions = subscriptions, view = view, update = update } + Html.programWithFlags { init = init, subscriptions = subscriptions, view = view, update = update } @@ -78,6 +79,11 @@ type alias Model = } +type alias Flags = + { startTime : Int + } + + type alias Board = List Row @@ -112,7 +118,20 @@ type alias BoardDict = model : Model model = - { board = board + { board = + let + letters = + [ [ "" ] ] + + tilesForRow : List String -> Row + tilesForRow row = + List.map tileForLetter row + + tileForLetter : String -> Tile + tileForLetter letter = + { letter = letter, match = False } + in + getBoardDict <| List.map tilesForRow letters , score = 0 , currentGuess = "" , foundWords = [] @@ -128,16 +147,16 @@ boardWidth = 5 -board : BoardDict -board = + +-- board : BoardDict +-- board = + + +createBoard : Int -> BoardDict +createBoard seed = let letters = - [ [ "l", "r", "e", "o", "s" ] - , [ "e", "d", "i", "w", "f" ] - , [ "j", "e", "m", "w", "e" ] - , [ "a", "f", "l", "t", "r" ] - , [ "o", "s", "a", "h", "h" ] - ] + BoardRandomizer.createRandomBoard boardWidth seed tilesForRow : List String -> Row tilesForRow row = @@ -167,9 +186,13 @@ firstLetter string = String.slice 0 1 string -init : ( Model, Cmd Msg ) -init = - ( model, Cmd.none ) +init : Flags -> ( Model, Cmd Msg ) +init flags = + ( { model + | board = createBoard flags.startTime + } + , Cmd.none + ) update : Msg -> Model -> ( Model, Cmd Msg ) @@ -278,10 +301,11 @@ update msg model = tile newDict = - Dict.map findMatches board + Dict.map findMatches <| clearBoard model.board in ( { model - | currentGuess = guess + | currentGuess = + guess , board = newDict , hasMatch = not <| Dict.isEmpty (Dict.filter (\key tile -> tile.match == True) newDict) , guessed = False @@ -290,6 +314,18 @@ update msg model = ) +clearBoard : BoardDict -> BoardDict +clearBoard board = + let + clearTile : Point -> Tile -> Tile + clearTile point tile = + { tile + | match = False + } + in + Dict.map clearTile board + + shortenedWord : String -> String shortenedWord word = String.dropLeft 1 word diff --git a/src/static/index.js b/src/static/index.js index 0d1a0ad..e57fd1c 100644 --- a/src/static/index.js +++ b/src/static/index.js @@ -5,4 +5,4 @@ require( '../../node_modules/bootstrap-sass/assets/javascripts/bootstrap.js' ); // inject bundled Elm app into div#main var Elm = require( '../elm/Main' ); -Elm.Main.embed( document.getElementById( 'main' ) ); +var app = Elm.Main.fullscreen({startTime: Date.now()}) diff --git a/src/static/styles/main.scss b/src/static/styles/main.scss index 7d39133..7fba039 100644 --- a/src/static/styles/main.scss +++ b/src/static/styles/main.scss @@ -16,7 +16,7 @@ $icon-font-path: '~bootstrap-sass/assets/fonts/bootstrap/'; } .pending.guessed .letter--highlighted { - background-color: #f8ffc6; + background-color: #aa1ed8; } .boardContainer { From bdae72d0b41a804ef622f88e93f72036ba4e06be Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Sat, 25 Feb 2017 12:40:24 -0700 Subject: [PATCH 16/23] add timer and a little polish --- src/elm/Main.elm | 110 ++++++++++++++++++++++-------------- src/static/styles/main.scss | 38 +++++++++++++ 2 files changed, 105 insertions(+), 43 deletions(-) diff --git a/src/elm/Main.elm b/src/elm/Main.elm index cbedc42..96ffd58 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -13,6 +13,7 @@ import Json.Decode as Decode import Keyboard exposing (presses) import Char exposing (fromCode) import BoardRandomizer +import Time -- APP @@ -29,7 +30,11 @@ main = subscriptions : Model -> Sub Msg subscriptions model = - Keyboard.presses (\code -> Presses (Char.fromCode code)) + Sub.batch + [ Keyboard.presses + (\code -> Presses (Char.fromCode code)) + , Time.every Time.second Tick + ] @@ -76,6 +81,7 @@ type alias Model = , guessed : Bool , correct : Maybe Bool , definition : Maybe String + , ticks : Int } @@ -139,6 +145,7 @@ model = , guessed = False , correct = Nothing , definition = Nothing + , ticks = 0 } @@ -170,20 +177,7 @@ createBoard seed = --- UPDATE - - -type Msg - = NoOp - | ScoreWord - | UpdateGuessWord String - | Presses Char - | DefineWord (Result Http.Error String) - - -firstLetter : String -> String -firstLetter string = - String.slice 0 1 string +-- INIT init : Flags -> ( Model, Cmd Msg ) @@ -195,6 +189,19 @@ init flags = ) + +-- UPDATE + + +type Msg + = NoOp + | ScoreWord + | UpdateGuessWord String + | Presses Char + | DefineWord (Result Http.Error String) + | Tick Time.Time + + update : Msg -> Model -> ( Model, Cmd Msg ) update msg model = case msg of @@ -204,41 +211,48 @@ update msg model = else (update NoOp model) + Tick time -> + ( { model + | ticks = model.ticks + 1 + } + , Cmd.none + ) + NoOp -> ( model, Cmd.none ) ScoreWord -> - -- TODO add a let to encapsulate this hasmatch not member stuffff - ( { model - | score = - if model.hasMatch && not (List.member model.currentGuess model.foundWords) then - model.score + (String.length model.currentGuess) - else - model.score - , guessed = True - , currentGuess = - if model.hasMatch && not (List.member model.currentGuess model.foundWords) then - model.currentGuess - else - "" - , correct = - if (List.member model.currentGuess model.foundWords) then + let + isValidGuess = + model.hasMatch && not (List.member model.currentGuess model.foundWords) + + isCorrect = + if isValidGuess then Just True else Nothing - } - , (if model.hasMatch && not (List.member model.currentGuess model.foundWords) then - lookUpWord model.currentGuess - else - Cmd.none - ) - ) + in + ( { model + | guessed = True + , currentGuess = + if isValidGuess then + model.currentGuess + else + "" + , correct = isCorrect + } + , if isValidGuess then + lookUpWord model.currentGuess + else + Cmd.none + ) DefineWord (Ok definition) -> ( { model | definition = Just (definition) , currentGuess = "" - , correct = Just model.hasMatch + , correct = Just True + , score = model.score + (String.length model.currentGuess) , foundWords = if not (List.member model.currentGuess model.foundWords) then model.currentGuess :: model.foundWords @@ -326,6 +340,11 @@ clearBoard board = Dict.map clearTile board +firstLetter : String -> String +firstLetter string = + String.slice 0 1 string + + shortenedWord : String -> String shortenedWord word = String.dropLeft 1 word @@ -416,20 +435,25 @@ view model = makeFoundWord word = div [ class "foundWord" ] [ text word ] in - div [] - [ div [ classList [ ( "game", True ), ( "guessed", model.guessed ), ( "pending", model.correct == Nothing ), ( "correct", model.correct == Just True ) ] ] + div [ class "gameRoot" ] + [ div [ class "header" ] + [ h2 [ class "timer" ] [ text <| "" ++ toString (model.ticks) ] + , h1 [ class "title" ] [ text "Elm Boggle" ] + ] + , div [ classList [ ( "game", True ), ( "guessed", model.guessed ), ( "pending", model.correct == Nothing ), ( "correct", model.correct == Just True ) ] ] [ div [] [ h2 [] [ text <| "Score: " ++ toString model.score ] , div [ class "boardContainer" ] (List.map makeTile <| Dict.values model.board) - , div [] + , div [ class "controls" ] [ input - [ Html.Attributes.id "guess-input" + [ class "guesser" , placeholder "Guess away!" , onInput UpdateGuessWord , value model.currentGuess + , Html.Attributes.autofocus True ] [] - , button [ onClick ScoreWord ] [ text "Check" ] + , button [ class "checker", onClick ScoreWord ] [ text "Check" ] ] ] , div [ class "foundWordContainer" ] <| [ h2 [] [ text "Found Words" ] ] ++ (List.map makeFoundWord model.foundWords) diff --git a/src/static/styles/main.scss b/src/static/styles/main.scss index 7fba039..5a1468f 100644 --- a/src/static/styles/main.scss +++ b/src/static/styles/main.scss @@ -3,10 +3,48 @@ $icon-font-path: '~bootstrap-sass/assets/fonts/bootstrap/'; @import '~bootstrap-sass/assets/stylesheets/_bootstrap.scss'; // can add Boostrap overrides, additional Sass/CSS below... +.controls { + width: 340px; + margin-left: 5px; + display: flex; + flex-direction: column; +} + +.guesser { + height: 50px; + width: 100%; + font-size: 24px; +} + +.checker { + height: 50px; + width: 100px; + font-size: 24px; + margin-top: 5px; + align-self: flex-end; +} + +.gameRoot { + padding-left: 30px; +} .game { display: flex; } +.header { + display: flex; +} + +.title { + position: absolute; + margin-left: 150px; +} + +.timer { + margin-top: 50px; + margin-bottom: 0; +} + .guessed .letter--highlighted { background-color: #f2ac9f; } From 18e25e574f56ac952a26feb270561e75e5a9ec1e Mon Sep 17 00:00:00 2001 From: Jeanette Date: Sat, 25 Feb 2017 13:47:29 -0700 Subject: [PATCH 17/23] Update README.md --- README.md | 48 +----------------------------------------------- 1 file changed, 1 insertion(+), 47 deletions(-) diff --git a/README.md b/README.md index af2fbf7..4081f48 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,6 @@ # LADY BOGGLE -Boggle written in elm by ladies - - -A simple Webpack setup for writing [Elm](http://elm-lang.org/) apps: - -* Dev server with live reloading, HMR -* Support for CSS/SCSS (with Autoprefixer), image assets -* Bootstrap 3.3+ (Sass version) -* Bundling and minification for deployment -* Basic app scaffold, using `Html.beginnerProgram` -* A snippet of example code to get you started! +Boggle written in elm by ladies. ### Install: @@ -52,39 +42,3 @@ npm run build * Files are saved into the `/dist` folder * To check it, open `dist/index.html` - -### Changelog - -**Ver 0.8.0** -* Update to Elm 0.18, use `debug=true` on webpack loader (PR by [douglascorrea](https://github.com/moarwick/elm-webpack-starter/pull/33)) -* Add a script for one-step installs -* Update to latest packages - -**Ver 0.7.1** -* Fix favicon issues, per [Issue 30](https://github.com/moarwick/elm-webpack-starter/issues/30) - -**Ver 0.7.0** -* Modify project structure, per [Issue 26](https://github.com/moarwick/elm-webpack-starter/issues/26) -* Include Bootstrap JS, per [Issue 28](https://github.com/moarwick/elm-webpack-starter/issues/28) -* More helpful install steps in README, per [Issue 29](https://github.com/moarwick/elm-webpack-starter/issues/29) -* Update to latest packages - -**Ver 0.6.2** -* Use `copy-webpack-plugin` instead of `cp` to copy files (Windows compatible) - -**Ver 0.6.0** -* `elm-hot-loader` is back (no Elm code changes required!) -* Switch to [bootstrap-sass](https://www.npmjs.com/package/bootstrap-sass) to demo CSS - -**Ver 0.5.0** -* Update to Elm 0.17.0 (and other latest modules) -* Upgrade starter code per [upgrade-docs](https://github.com/elm-lang/elm-platform/blob/master/upgrade-docs/0.17.md) -* Remove `elm-hot-loader` (for now) - -**Ver 0.4.0** -* Add [elm-hot-loader](https://github.com/fluxxu/elm-hot-loader) for HMR support (PR by [fluxxu](https://github.com/fluxxu)) - -**Ver 0.3.0** -* Use `html-webpack-plugin` to generate `index.html` -* Apply hash filenames for bundled JS and CSS (prevents caching) -* Image and favicon assets copied to `dist/` From dddfd81959be1952c19c47cbe898ecb0ba4e33d1 Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Sat, 25 Feb 2017 14:25:44 -0700 Subject: [PATCH 18/23] add footer --- src/elm/Main.elm | 9 ++++++++- src/static/styles/main.scss | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/elm/Main.elm b/src/elm/Main.elm index 96ffd58..d842f2e 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -438,7 +438,10 @@ view model = div [ class "gameRoot" ] [ div [ class "header" ] [ h2 [ class "timer" ] [ text <| "" ++ toString (model.ticks) ] - , h1 [ class "title" ] [ text "Elm Boggle" ] + , h1 [ class "title" ] + [ a [ Html.Attributes.href "http://elm-lang.org/" ] [ text "Elm" ] + , text " Boggle" + ] ] , div [ classList [ ( "game", True ), ( "guessed", model.guessed ), ( "pending", model.correct == Nothing ), ( "correct", model.correct == Just True ) ] ] [ div [] @@ -458,4 +461,8 @@ view model = ] , div [ class "foundWordContainer" ] <| [ h2 [] [ text "Found Words" ] ] ++ (List.map makeFoundWord model.foundWords) ] + , div [ class "footer" ] + [ a [ Html.Attributes.href "https://github.com/jeanettehead/lady-boggle" ] [ text "See the code on GitHub" ] + , a [ Html.Attributes.href "http://iamjea.net" ] [ text "My Website" ] + ] ] diff --git a/src/static/styles/main.scss b/src/static/styles/main.scss index 5a1468f..ae8370e 100644 --- a/src/static/styles/main.scss +++ b/src/static/styles/main.scss @@ -3,6 +3,16 @@ $icon-font-path: '~bootstrap-sass/assets/fonts/bootstrap/'; @import '~bootstrap-sass/assets/stylesheets/_bootstrap.scss'; // can add Boostrap overrides, additional Sass/CSS below... +.footer { + display: flex; + flex-direction: column; + font-size: 18px; + width: 100%; + border-top: 2px solid #ddd; + margin-top: 50px; + padding-top: 10px; +} + .controls { width: 340px; margin-left: 5px; @@ -26,6 +36,7 @@ $icon-font-path: '~bootstrap-sass/assets/fonts/bootstrap/'; .gameRoot { padding-left: 30px; + padding-right: 30px; } .game { display: flex; @@ -36,10 +47,19 @@ $icon-font-path: '~bootstrap-sass/assets/fonts/bootstrap/'; } .title { + color: #1c818e; position: absolute; margin-left: 150px; + a { + color: #1c818e; + } + a:hover { + color: #125a63; + text-decoration: none; + } } + .timer { margin-top: 50px; margin-bottom: 0; From 47c7e1b6cee4a87f68a924827a2546c11cc870fc Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Sat, 25 Feb 2017 16:55:06 -0700 Subject: [PATCH 19/23] Much needed refactor --- src/elm/BoardRandomizer.elm | 2 +- src/elm/Main.elm | 144 +----------------------------------- src/elm/PathFinder.elm | 104 ++++++++++++++++++++++++++ src/elm/Types.elm | 35 +++++++++ 4 files changed, 144 insertions(+), 141 deletions(-) create mode 100644 src/elm/PathFinder.elm create mode 100644 src/elm/Types.elm diff --git a/src/elm/BoardRandomizer.elm b/src/elm/BoardRandomizer.elm index ae41c9f..ce208a4 100644 --- a/src/elm/BoardRandomizer.elm +++ b/src/elm/BoardRandomizer.elm @@ -1,4 +1,4 @@ -port module BoardRandomizer exposing (createRandomBoard) +module BoardRandomizer exposing (createRandomBoard) import Html import Random exposing (int, initialSeed, generate, step) diff --git a/src/elm/Main.elm b/src/elm/Main.elm index d842f2e..85b369a 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -5,15 +5,15 @@ import Html exposing (..) import Html.Attributes exposing (placeholder, value, classList, class) import Html.Events exposing (onClick, onInput, on) import Dict exposing (Dict) -import Set exposing (Set) -import Array exposing (Array) import Dom exposing (focus, Error) import Http import Json.Decode as Decode import Keyboard exposing (presses) import Char exposing (fromCode) -import BoardRandomizer import Time +import BoardRandomizer +import PathFinder exposing (findPaths) +import Types exposing (..) -- APP @@ -90,38 +90,6 @@ type alias Flags = } -type alias Board = - List Row - - -type alias Tile = - { letter : String, match : Bool } - - -type alias Point = - ( Int, Int ) - - -type alias Row = - List Tile - - -type alias StartingPoints = - List Point - - -type alias Path = - List Point - - -type alias Paths = - List Path - - -type alias BoardDict = - Dict Point Tile - - model : Model model = { board = @@ -154,11 +122,6 @@ boardWidth = 5 - --- board : BoardDict --- board = - - createBoard : Int -> BoardDict createBoard seed = let @@ -273,43 +236,9 @@ update msg model = UpdateGuessWord guess -> let - checkTile : String -> Tile -> Tile - checkTile guessLetter tile = - { tile | match = (guessLetter == tile.letter) } - - matchFirstLetter : Point -> Tile -> Tile - matchFirstLetter point tile = - checkTile (firstLetter guess) tile - - findPaths : List Path - findPaths = - List.filter (\path -> List.length path == String.length guess) <| - List.concat <| - (List.map - (\point -> (explorePath model.board [ point ] (shortenedWord guess))) - <| - Dict.keys firstLetterMatches - ) - - firstLetterMatches : BoardDict - firstLetterMatches = - Dict.filter isMatching <| - Dict.map matchFirstLetter model.board - - isMatching : Point -> Tile -> Bool - isMatching _ tile = - tile.match - - neighborList : List Point - neighborList = - List.concatMap getNeighbors <| - Dict.keys <| - Dict.filter isMatching <| - Dict.map matchFirstLetter model.board - findMatches : Point -> Tile -> Tile findMatches point tile = - if List.member point (Maybe.withDefault [] (List.head findPaths)) then + if List.member point (Maybe.withDefault [] (List.head <| findPaths boardWidth model.board guess)) then { tile | match = True } else tile @@ -340,71 +269,6 @@ clearBoard board = Dict.map clearTile board -firstLetter : String -> String -firstLetter string = - String.slice 0 1 string - - -shortenedWord : String -> String -shortenedWord word = - String.dropLeft 1 word - - -explorePath : BoardDict -> Path -> String -> List Path -explorePath board path word = - let - lastPoint : Path -> Maybe Point - lastPoint path = - Array.get 0 (Array.fromList path) - - travel : BoardDict -> String -> Path -> List Path - travel board word path = - List.map - (\match -> - if (not <| List.member match path) then - List.append [ match ] path - else - [] - ) - (matchingNeighbors board (lastPoint path) (firstLetter word)) - in - if String.length word > 0 then - List.concatMap (\aPath -> (explorePath board aPath <| shortenedWord word)) (travel board word path) - else - [ path ] - - -matchingNeighbors : BoardDict -> Maybe Point -> String -> List Point -matchingNeighbors board point letter = - let - isMatch : Point -> Point -> Tile -> Bool - isMatch origin point tile = - (List.member point <| getNeighbors origin) && (tile.letter == letter) - in - case point of - Just value -> - Dict.keys <| Dict.filter (isMatch value) board - - Nothing -> - [] - - -getNeighbors : Point -> List Point -getNeighbors ( x, y ) = - Set.toList <| - Set.remove ( x, y ) <| - Set.fromList - [ ( max (x - 1) 0, max (y - 1) 0 ) - , ( max (x - 1) 0, y ) - , ( max (x - 1) 0, min (y + 1) boardWidth ) - , ( x, max (y - 1) 0 ) - , ( x, min (y + 1) boardWidth ) - , ( min (x + 1) boardWidth, max (y - 1) 0 ) - , ( min (x + 1) boardWidth, y ) - , ( min (x + 1) boardWidth, min (y + 1) boardWidth ) - ] - - getBoardDict : Board -> BoardDict getBoardDict board = let diff --git a/src/elm/PathFinder.elm b/src/elm/PathFinder.elm new file mode 100644 index 0000000..d2d1d39 --- /dev/null +++ b/src/elm/PathFinder.elm @@ -0,0 +1,104 @@ +module PathFinder exposing (findPaths) + +import Types exposing (..) +import Dict exposing (Dict) +import Array exposing (Array) +import Set exposing (Set) + + +findPaths : Int -> BoardDict -> String -> List Path +findPaths boardWidth board guess = + List.filter (\path -> List.length path == String.length guess) <| + List.concat <| + (List.map + (\point -> (explorePath boardWidth board [ point ] (shortenedWord guess))) + <| + Dict.keys <| + firstLetterMatches guess board + ) + + +firstLetterMatches : String -> BoardDict -> BoardDict +firstLetterMatches guess board = + let + matchFirstLetter : Point -> Tile -> Tile + matchFirstLetter point tile = + checkTile (firstLetter guess) tile + in + Dict.filter isMatching <| + Dict.map matchFirstLetter board + + +firstLetter : String -> String +firstLetter string = + String.slice 0 1 string + + +shortenedWord : String -> String +shortenedWord word = + String.dropLeft 1 word + + +checkTile : String -> Tile -> Tile +checkTile guessLetter tile = + { tile | match = (guessLetter == tile.letter) } + + +isMatching : Point -> Tile -> Bool +isMatching _ tile = + tile.match + + +explorePath : Int -> BoardDict -> Path -> String -> List Path +explorePath boardWidth board path word = + let + lastPoint : Path -> Maybe Point + lastPoint path = + Array.get 0 (Array.fromList path) + + travel : BoardDict -> String -> Path -> List Path + travel board word path = + List.map + (\match -> + if (not <| List.member match path) then + List.append [ match ] path + else + [] + ) + (matchingNeighbors boardWidth board (lastPoint path) (firstLetter word)) + in + if String.length word > 0 then + List.concatMap (\aPath -> (explorePath boardWidth board aPath <| shortenedWord word)) (travel board word path) + else + [ path ] + + +matchingNeighbors : Int -> BoardDict -> Maybe Point -> String -> List Point +matchingNeighbors boardWidth board point letter = + let + isMatch : Point -> Bool + isMatch point = + (Maybe.withDefault { letter = "", match = False } <| Dict.get point board).letter == letter + in + case point of + Just value -> + List.filter isMatch (getNeighbors boardWidth value) + + Nothing -> + [] + + +getNeighbors : Int -> Point -> List Point +getNeighbors boardWidth ( x, y ) = + Set.toList <| + Set.remove ( x, y ) <| + Set.fromList + [ ( max (x - 1) 0, max (y - 1) 0 ) + , ( max (x - 1) 0, y ) + , ( max (x - 1) 0, min (y + 1) boardWidth ) + , ( x, max (y - 1) 0 ) + , ( x, min (y + 1) boardWidth ) + , ( min (x + 1) boardWidth, max (y - 1) 0 ) + , ( min (x + 1) boardWidth, y ) + , ( min (x + 1) boardWidth, min (y + 1) boardWidth ) + ] diff --git a/src/elm/Types.elm b/src/elm/Types.elm new file mode 100644 index 0000000..23d116f --- /dev/null +++ b/src/elm/Types.elm @@ -0,0 +1,35 @@ +module Types exposing (..) + +import Dict exposing (Dict) + + +type alias Board = + List Row + + +type alias Tile = + { letter : String, match : Bool } + + +type alias Point = + ( Int, Int ) + + +type alias Row = + List Tile + + +type alias StartingPoints = + List Point + + +type alias Path = + List Point + + +type alias Paths = + List Path + + +type alias BoardDict = + Dict Point Tile From 256152c62ca115da789dee74fa68e9a624770ca7 Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Sat, 25 Feb 2017 17:08:46 -0700 Subject: [PATCH 20/23] rename function --- src/elm/Main.elm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/elm/Main.elm b/src/elm/Main.elm index 85b369a..4f9083f 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -60,11 +60,11 @@ lookUpWord word = url = "https://wordsapiv1.p.mashape.com/words/" ++ word in - Http.send DefineWord (authenticatedGet url decodeGifUrl) + Http.send DefineWord (authenticatedGet url decodeResponse) -decodeGifUrl : Decode.Decoder String -decodeGifUrl = +decodeResponse : Decode.Decoder String +decodeResponse = Decode.at [ "word" ] Decode.string From 27fbc97c9c816e27e22da1864ec3857e3d75845f Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Sat, 25 Feb 2017 17:10:18 -0700 Subject: [PATCH 21/23] refactor initial board --- src/elm/Main.elm | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/elm/Main.elm b/src/elm/Main.elm index 4f9083f..3e9795f 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -92,20 +92,7 @@ type alias Flags = model : Model model = - { board = - let - letters = - [ [ "" ] ] - - tilesForRow : List String -> Row - tilesForRow row = - List.map tileForLetter row - - tileForLetter : String -> Tile - tileForLetter letter = - { letter = letter, match = False } - in - getBoardDict <| List.map tilesForRow letters + { board = getBoardDict <| [ [ { letter = "", match = False } ] ] , score = 0 , currentGuess = "" , foundWords = [] From d5dbaf0b5370634089d6670256bbb1a91b57ab3b Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Sat, 25 Feb 2017 17:12:04 -0700 Subject: [PATCH 22/23] reordering --- src/elm/Main.elm | 88 ++++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/src/elm/Main.elm b/src/elm/Main.elm index 3e9795f..500b5d5 100644 --- a/src/elm/Main.elm +++ b/src/elm/Main.elm @@ -38,37 +38,6 @@ subscriptions model = --- HTTP - - -authenticatedGet : String -> Decode.Decoder String -> Http.Request String -authenticatedGet url decoder = - Http.request - { method = "GET" - , headers = [ Http.header "X-Mashape-Key" "7RhzLqB7x0mshfh5YE2afEP7Ngkxp1xigQqjsnKy6oDuQ7CfkC" ] - , body = Http.emptyBody - , url = url - , expect = Http.expectJson decoder - , timeout = Nothing - , withCredentials = False - } - - -lookUpWord : String -> Cmd Msg -lookUpWord word = - let - url = - "https://wordsapiv1.p.mashape.com/words/" ++ word - in - Http.send DefineWord (authenticatedGet url decodeResponse) - - -decodeResponse : Decode.Decoder String -decodeResponse = - Decode.at [ "word" ] Decode.string - - - -- MODEL @@ -109,6 +78,19 @@ boardWidth = 5 + +-- INIT + + +init : Flags -> ( Model, Cmd Msg ) +init flags = + ( { model + | board = createBoard flags.startTime + } + , Cmd.none + ) + + createBoard : Int -> BoardDict createBoard seed = let @@ -127,19 +109,6 @@ createBoard seed = --- INIT - - -init : Flags -> ( Model, Cmd Msg ) -init flags = - ( { model - | board = createBoard flags.startTime - } - , Cmd.none - ) - - - -- UPDATE @@ -317,3 +286,34 @@ view model = , a [ Html.Attributes.href "http://iamjea.net" ] [ text "My Website" ] ] ] + + + +-- HTTP + + +authenticatedGet : String -> Decode.Decoder String -> Http.Request String +authenticatedGet url decoder = + Http.request + { method = "GET" + , headers = [ Http.header "X-Mashape-Key" "7RhzLqB7x0mshfh5YE2afEP7Ngkxp1xigQqjsnKy6oDuQ7CfkC" ] + , body = Http.emptyBody + , url = url + , expect = Http.expectJson decoder + , timeout = Nothing + , withCredentials = False + } + + +lookUpWord : String -> Cmd Msg +lookUpWord word = + let + url = + "https://wordsapiv1.p.mashape.com/words/" ++ word + in + Http.send DefineWord (authenticatedGet url decodeResponse) + + +decodeResponse : Decode.Decoder String +decodeResponse = + Decode.at [ "word" ] Decode.string From ee8febbb9868aa41b32f7f70917cedfec2aee71d Mon Sep 17 00:00:00 2001 From: Jeanette Head Date: Sat, 25 Feb 2017 22:13:02 -0700 Subject: [PATCH 23/23] fix overflow issue with found words --- src/static/styles/main.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/static/styles/main.scss b/src/static/styles/main.scss index ae8370e..067e438 100644 --- a/src/static/styles/main.scss +++ b/src/static/styles/main.scss @@ -98,4 +98,6 @@ $icon-font-path: '~bootstrap-sass/assets/fonts/bootstrap/'; .foundWordContainer { font-size: 20px; padding-left: 50px; + max-height: 500px; + overflow: scroll; }