Implement grid construction with given puzzle - crossword.koplugin - Unnamed repository; edit this file 'description' to name the repository.
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) Submodules
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 1dc559aef64abdc2dd6effc6e857586f839c9e20
 (DIR) parent caa49f4813c63862a41952e3500481f429cfc04c
 (HTM) Author: Scarlett <social@scarlettmcallister.com>
       Date:   Fri, 10 Dec 2021 21:47:33 -0400
       
       Implement grid construction with given puzzle
       
       - Includes letters and numbers (wow!)
       - Also have settings setup.
       
       Diffstat:
         A .gitmodules                         |       3 +++
         M main.lua                            |     101 ++++++++++++++++++++++++++++---
         A nyt_crosswords                      |       1 +
         D puzzle.lua                          |      83 -------------------------------
         M puzzlerow.lua                       |       5 ++---
         M puzzlesquare.lua                    |      76 +++++++++++++++++++++++++------
         A puzzleview.lua                      |     120 +++++++++++++++++++++++++++++++
       
       7 files changed, 283 insertions(+), 106 deletions(-)
       ---
 (DIR) diff --git a/.gitmodules b/.gitmodules
       @@ -0,0 +1,3 @@
       +[submodule "nyt_crosswords"]
       +        path = nyt_crosswords
       +        url = https://github.com/doshea/nyt_crosswords
 (DIR) diff --git a/main.lua b/main.lua
       @@ -5,16 +5,24 @@ This is a debug plugin to test Plugin functionality.
        --]]--
        
        -- This is a debug plugin, remove the following if block to enable it
       -
       +local DataStorage = require("datastorage")
        local Dispatcher = require("dispatcher")  -- luacheck:ignore
        local InfoMessage = require("ui/widget/infomessage")
       +local LuaSettings = require("frontend/luasettings")
        local UIManager = require("ui/uimanager")
        local WidgetContainer = require("ui/widget/container/widgetcontainer")
       +local LuaSettings = require("frontend/luasettings")
        local logger = require("logger")
       +local json = require("json")
        local _ = require("gettext")
        
        local Crossword = WidgetContainer:new{
            name = "crossword",
       +    settings = nil,
       +    settings_keys = {
       +        puzzles_dir = "puzzles_dir"
       +    },
       +    puzzles_dir = nil,
        }
        
        function Crossword:init()
       @@ -25,16 +33,95 @@ function Crossword:addToMainMenu(menu_items)
            menu_items.crossword = {
                text = _("Crossword"),
                -- a callback when tapping
       -        sorting_hint = "tools",
       -        callback = function()
       -            self:gameView();
       -        end,
       +        sub_item_table_func = function()
       +            return self:getSubMenuItems()
       +        end
       +    }
       +end
       +
       +function Crossword:getSubMenuItems()
       +    self:lazyInitialization()
       +    return {
       +        {
       +            text = _("Play"),
       +            callback = function()
       +                self:gameView()
       +            end
       +        },
       +        {
       +            text = _("Settings"),
       +            sub_item_table = {
       +                {
       +                    text = _("Set puzzles folder"),
       +                    keep_menu_open = true,
       +                    callback = function()
       +                        self:setPuzzlesDirectory()
       +                    end
       +                }
       +            }
       +        }
            }
        end
        
       +function Crossword:lazyInitialization()
       +    -- Load the settings
       +    self.settings = LuaSettings:open(("%s/%s"):format(DataStorage:getSettingsDir(), "crossword_settings.lua"))
       +    -- Load the puzzle directory value
       +    self.puzzle_dir = self.settings_keys.puzzle_dir and
       +        self.settings:readSetting(self.settings_keys.puzzle_dir) or
       +        ("%s/plugins/crossword.koplugin/nyt_crosswords"):format(
       +            DataStorage:getFullDataDir())
       +end
       +
       +function Crossword:setPuzzlesDirectory()
       +    local downloadmgr = require("ui/downloadmgr")
       +    downloadmgr:new{
       +        onConfirm = function(path)
       +            self.settings:saveSetting(self.settings_keys.puzzles_dir, ("%s/"):format(path))
       +            self.settings:flush()
       +        end
       +    }:chooseDir()
       +    self:lazyInitialization()
       +end
       +
        function Crossword:gameView()
       -    local Puzzle = require("puzzle"):new{}
       -    UIManager:show(Puzzle)
       +    local file_path = ("%s/%s"):format(self.puzzle_dir, "/1990/01/01.json")
       +    local file, err = io.open(file_path, "rb")
       +
       +    if not file then
       +        return _("Could not load crossword")
       +    end
       +
       +    local file_content = file:read("*all")
       +    file:close()
       +
       +    local puzzle = json.decode(file_content)
       +    logger.dbg(puzzle)
       +    -- Create the grid, which contains the letters for
       +    -- each row.
       +    local grid = {}
       +    local row = {}
       +    for i, letter in ipairs(puzzle.grid) do
       +        table.insert(row, {
       +                letter = letter,
       +                number = puzzle.gridnums[i],
       +        })
       +        if i % 15 == 0 then
       +            table.insert(grid, row)
       +            row = {}
       +        end
       +    end
       +
       +    local PuzzleView = require("puzzleview")
       +    PuzzleView = PuzzleView:new{
       +        size = {
       +            cols = puzzle.size.cols,
       +            rows = puzzle.size.rows
       +        },
       +        grid = grid
       +    }
       +
       +    UIManager:show(PuzzleView)
        end
        
        return Crossword
 (DIR) diff --git a/nyt_crosswords b/nyt_crosswords
       @@ -0,0 +1 @@
       +Subproject commit 623e72e99b25a524c85b56bf832dd7cd8c2a34a9
 (DIR) diff --git a/puzzle.lua b/puzzle.lua
       @@ -1,83 +0,0 @@
       -local Blitbuffer = require("ffi/blitbuffer")
       -local Device = require("device")
       -local Screen = Device.screen
       -local Size = require("ui/size")
       -local Geom = require("ui/geometry")
       -local FrameContainer = require("ui/widget/container/framecontainer")
       -local InputContainer = require("ui/widget/container/inputcontainer")
       -local OverlapGroup = require("ui/widget/overlapgroup")
       -local VerticalGroup = require("ui/widget/verticalgroup")
       -local HorizontalGroup = require("ui/widget/horizontalgroup")
       -local logger = require("logger")
       -
       -local PuzzleRow = require("puzzlerow")
       -local PuzzleSquare = require("puzzlesquare")
       -
       -
       -local PuzzleView = InputContainer:new{
       -    width = nil,
       -    height = nil,
       -}
       -
       -function PuzzleView:init()
       -    self.dimen = Geom:new{
       -        w = self.width or Screen:getWidth(),
       -        h = self.height or Screen:getHeight(),
       -    }
       -    self.outer_padding = Size.padding.large
       -    self.inner_padding = Size.padding.small
       -    self.inner_dimen = Geom:new{
       -        w = self.dimen.w - 2 * self.outer_padding,
       -        h = self.dimen.h - self.outer_padding, -- no bottom padding
       -    }
       -    self.content_width = self.inner_dimen.w
       -    -- The size of the game board
       -    self.grid = {
       -        cols = 10,
       -        rows = 10,
       -    }
       -    self.main_content = VerticalGroup:new{}
       -
       -    -- self.populate_items
       -    -- Add the squares
       -
       -    self.square_width = math.floor((self.dimen.w - (2 * self.outer_padding) - (2 * self.inner_padding)) / self.grid.cols)
       -
       -    logger.dbg(self.square_width)
       -    
       -    local row = PuzzleRow:new{
       -        width = self.inner_dimen.w,
       -        height = 20
       -    }
       -
       -    for index = 0, self.grid.cols, 1 do
       -        local square = PuzzleSquare:new{
       -            width = self.square_width,
       -            height = 20,
       -        }
       -        row:addSquare(square)
       -    end
       -
       -    row:update()
       -       
       -    table.insert(self.main_content, row)
       -    
       -    
       -    local content = VerticalGroup:new{
       -            align = "left",
       -            self.main_content,
       -    }
       -
       -    self[1] = FrameContainer:new{
       -        width = self.dimen.w,
       -        height = self.dimen.h,
       -        padding = self.outer_padding,
       -        padding_bottom = 0,
       -        margin = 0,
       -        bordersize = 0,
       -        background = Blitbuffer.COLOR_GRAY,
       -        content
       -    }        
       -end
       -
       -return PuzzleView
 (DIR) diff --git a/puzzlerow.lua b/puzzlerow.lua
       @@ -7,8 +7,6 @@ local Row = InputContainer:new{
            width = nil,
            height = nil,
            padding = nil,
       -    font_size = 10,
       -    font_face = "xx_smallinfofont",
        }
        
        function Row:init()
       @@ -24,13 +22,14 @@ function Row:update()
        
            for num, square in ipairs(self.squares) do
                table.insert(hori, square)
       -        table.insert(hori, HorizontalSpan:new{ width = self.padding, })
            end
        
            self[1] = FrameContainer:new{
                width = self.width,
                height = self.height,
       +        bordersize = 0,
                padding = 0,
       +        margin = 0,
                hori
            }
        end
 (DIR) diff --git a/puzzlesquare.lua b/puzzlesquare.lua
       @@ -4,39 +4,89 @@ local InputContainer = require("ui/widget/container/inputcontainer")
        local Font = require("ui/font")
        local Geom = require("ui/geometry")
        local FrameContainer = require("ui/widget/container/framecontainer")
       +local OverlapGroup = require("ui/widget/overlapgroup")
        local TextWidget = require("ui/widget/textwidget")
       +local TextBoxWidget = require("ui/widget/textboxwidget")
        
        local logger = require("logger")
        
        local PuzzleSquare = InputContainer:new{
       -    font_face = "xx_smallinfofont",
       -    font_size = 10,
       +    letter_font_face = "infofont",
       +    letter_font_size = nil,
       +    number_font_face = "infont",
       +    number_font_size = nil,
       +    margin = nil,
       +    solve = nil,
        }
        
        function PuzzleSquare:init()
       +    -- Lazy check to see if solve is set.
       +    if not self.solve then
       +        logger.dbg("PuzzleSquare: solve not set for square")
       +        return
       +    end
       +
       +    -- Set up the right bg color, letter, etc.
       +    local bg_color = self.solve.letter ~= "." and
       +        Blitbuffer.COLOR_WHITE or
       +        Blitbuffer.COLOR_BLACK
       +    local letter = self.solve.letter and
       +        self.solve.letter or
       +        ""
       +    local number = self.solve.number ~= 0 and
       +        tostring(self.solve.number) or
       +        ""
       +
       +    self.letter_font_size = TextBoxWidget:getFontSizeToFitHeight(self.height, 1, 0.3)
       +    self.number_font_size = self.letter_font_size / 2
       +
       +    -- This is the letter input by the player.
            self.letter = TextWidget:new{
       -        text = "A",
       -        face = Font:getFace(self.font_face, self.font_size),
       +        text = letter,
       +        face = Font:getFace(self.letter_font_face, self.letter_font_size),
                fgcolor = Blitbuffer.COLOR_BLACK,
                padding = 0,
                bold = true,
            }
       -
       -    logger.dbg(self.width)
       -
       +    -- This is the number that corresponds to the question.
       +    -- Note that the number is not always set!
       +    self.number = TextWidget:new{
       +        text = number,
       +        face = Font:getFace(self.number_font_face, self.number_font_size),
       +        fgcolor = Blitbuffer.COLOR_BLACK,
       +        padding = 0,
       +        bold = true,
       +    }
       +    -- This is the container for the letter and number.
            self[1] = FrameContainer:new{
                width = self.width,
                height = self.height,
                color = Blitbuffer.COLOR_WHITE,
       +        background = bg_color,
                padding = 0,
       -        CenterContainer:new{
       -            dimen = Geom:new{
       -                w = self.width,
       -                h = self.height,
       +        margin = self.margin or 0,
       +        bordersize = 0,
       +        OverlapGroup:new{
       +            dimen = { w = self.width },
       +            padding = 0,
       +            -- Keep the letter centered
       +            CenterContainer:new{
       +                dimen = Geom:new{
       +                    w = self.width,
       +                    h = self.height,
       +                },
       +                padding = 0,
       +                -- Add the letter
       +                self.letter,
                    },
       -            self.letter,
       -        }
       +            -- Add the number
       +            self.number,
       +        },
            }
        end
        
       +function PuzzleSquare:onTap()
       +    logger.dbg("TA________________P")
       +end
       +
        return PuzzleSquare
 (DIR) diff --git a/puzzleview.lua b/puzzleview.lua
       @@ -0,0 +1,120 @@
       +local Blitbuffer = require("ffi/blitbuffer")
       +local Device = require("device")
       +local Screen = Device.screen
       +local Size = require("ui/size")
       +local Geom = require("ui/geometry")
       +local FrameContainer = require("ui/widget/container/framecontainer")
       +local InputContainer = require("ui/widget/container/inputcontainer")
       +local OverlapGroup = require("ui/widget/overlapgroup")
       +local VerticalGroup = require("ui/widget/verticalgroup")
       +local HorizontalGroup = require("ui/widget/horizontalgroup")
       +local logger = require("logger")
       +
       +local PuzzleRow = require("puzzlerow")
       +local PuzzleSquare = require("puzzlesquare")
       +
       +
       +local PuzzleView = InputContainer:new{
       +    width = nil,
       +    height = nil,
       +    size = {
       +        cols = nil,
       +        rows = nil,
       +    }
       +}
       +
       +function PuzzleView:init()
       +
       +    -- Temp! This will be the puzzle object, eventually.
       +    local letters = {
       +        {"A","B",".","C","D","E"},
       +        {"B",".","C","D","E","C"},
       +    }
       +
       +    local puzzle_cols = #letters[1]
       +    local puzzle_rows = #letters
       +
       +    self.dimen = Geom:new{
       +        w = self.width or Screen:getWidth(),
       +        h = self.height or Screen:getHeight(),
       +    }
       +    self.outer_padding = Size.padding.large
       +    self.inner_padding = Size.padding.small
       +    self.inner_dimen = Geom:new{
       +        w = self.dimen.w - 2 * self.outer_padding,
       +        h = self.dimen.h - self.outer_padding, -- no bottom padding
       +    }
       +    self.content_width = self.inner_dimen.w
       +    -- The grid dimensions of the puzzle.
       +    --self.grid = {
       +    --    cols = puzzle_cols,
       +    --    rows = puzzle_rows,
       +    --}
       +    -- The pixel dimensions of the squares. Calculate the initial width based on the size
       +    -- of the device and the number of columns. Then make a minor adjustment to account for
       +    -- the margins. To do this, divide margin in 4 and multiply by the number of columns.
       +    self.square_margin = Size.border.window
       +    self.square_width = math.floor(
       +        (self.dimen.w - (2 * self.outer_padding) - (2 * self.inner_padding))
       +        / self.size.cols) - ((self.square_margin / 4) * (puzzle_cols))
       +    self.square_height = self.square_width
       +
       +    ------------------
       +    -- Add the squares
       +    self.rows_group = VerticalGroup:new{ border = 0 }
       +
       +    for i, l in ipairs(self.grid) do
       +        table.insert(self.rows_group, self:buildRow(l))
       +    end
       +
       +    ---------------
       +    -- Build the container
       +
       +    self[1] = FrameContainer:new{
       +        width = self.dimen.w,
       +        height = self.dimen.h,
       +        padding = self.outer_padding,
       +        padding_bottom = 0,
       +        margin = 0,
       +        bordersize = 0,
       +        background = Blitbuffer.COLOR_BLACK,
       +        VerticalGroup:new{
       +            align = "center",
       +            background = Blitbuffer.COLOR_GRAY,
       +            -- Add the rows vertical group.
       +            self.rows_group,
       +        }
       +    }
       +end
       +
       +function PuzzleView:create()
       +
       +end
       +
       +-- Given a table containing letters, build a row containing
       +-- squares with said letters.
       +function PuzzleView:buildRow(squares)
       +    local row = PuzzleRow:new{
       +        width = self.inner_dimen.w,
       +        height = self.square_height,
       +    }
       +    for i, square in ipairs(squares) do
       +        -- This needs a better name. It should be a combination of the user's input,
       +        -- plus also like the square solve thing (hints, etc.)
       +        local solve = {
       +            letter = square.letter,
       +            number = square.number,
       +        }
       +        local square = PuzzleSquare:new{
       +            width = self.square_width,
       +            height = self.square_height,
       +            margin = self.square_margin,
       +            solve = solve,
       +        }
       +        row:addSquare(square)
       +    end
       +    row:update()
       +    return row
       +end
       +
       +return PuzzleView