Minesweeper with Tables and Gemini |> Table Contest

Minesweeper with Tables and Gemini

Authors: Jinhwan Kim
linkedin
github

Full Description:

You can see below with independent manual page

A. Purpose of this submission

:smiley: 1. Enjoyable table

I was thinking about what table to create for the table contest 2024, I wanted to create a use case for a table that could be enjoyed without context or understanding of the data.

So, although I am not a professional game developer, I created a :gear: "Minesweeper" game using tables and shiny.

:art: 2. Various table

I wanted to showcase the capabilities of different tables.

There are a lot of packages available for working with tables in R, each with their own strengths and weaknesses. I haven't used all of them, but I didn't want to limit myself to just one package.

I used reactable, which is my favourite, DT, which was the first one I started using, and finally gt, which has recently been getting a lot of love in the clinical domain.

Of course, there are other valuable packages like flextable and data.table, but I don't have time to cover them all.

:sparkles: 3. Interactive table

Since I'm using shiny for this submission, I wanted to create some interaction with the user or external services in the table, so I threw in a little bit of LLM functionality, which is all the rage these days.

B. How to play mine-sweeper

This can be followed as Guide with Cicerone in Shiny application


2
3
4

C. How to use Gemini

I skipped using Gemini in here, but you can check in quarto page I've made

D. Code explanation

1. libraries

I used 11 R packages in this mine.tables

# tables
library(reactable)
library(DT)
library(gt)

# shiny
library(shiny)
library(shinyWidgets)
library(bslib)
library(bsicons)
library(shinyjs)
library(cicerone)

# gemini
library(magrittr)
library(gemini.R)

First 3 is for table work,
and next 6 is for shiny application,
and last 2 is for API call gemini.

2. Shiny UI

Since you may see Every code, I attached image of key functions

3. Shiny server

r logic is consisted with 5 major parts. and I only cover some part of it in here.
if you're interested to detailed code, see my code

  1. mine sweeper game
  • Randomly generate data with given size and mine (START)
  • Get click input from user
  • Check if it is mine or not and show results
  1. reactable
  • To get clicked cell from user with reactable, I used onClick parameter of reactable to create "Shiny.setInputValue" (Javascript Event
  • render mine count, and mine emoji with color_text function which return HTML element with color.
reactable(
      board_df,
      onClick = JS("function(rowInfo, column) {
        Shiny.setInputValue('cell_click', { row: rowInfo.index + 1, column: column.id });
      }"),
      defaultColDef = colDef(
        align = "center",
        vAlign = "center",
        html = TRUE
      ),
      columns = list(
        .rownames = colDef(
          width = 50,
          html = TRUE,
          cell = function(value) {
            sprintf('<span style="font-weight: 600;">%s</span>', value)
          }
        )
      ),
      pagination = FALSE,
      sortable = FALSE,
      bordered = TRUE,
      highlight = TRUE,
      theme = reactableTheme(tableBodyStyle = list(flex = "auto"))
    )
  1. DT
  • To implement Button-like table with DT. used escape parameter to use HTML tag.
  • In cell element (Button) it uses onclick to open github repository.
  • The pagination doesn't affect functionality, but I left it on purpose because without it, it's hard to tell it's a table.
output$about.dt <- renderDataTable({
    datatable(
      data.frame(c('<button 
                      type="button" 
                      class="btn btn-primary" 
                      style="width:100%"
                      onclick="window.open(`https://github.com/jhk0530/mine.tables`)"
                      >See code</button>')),
      escape = FALSE,
      colnames = NULL,
      options = list(
        dom = "tp",
        ordering = FALSE,
        searching = FALSE
      ),
      rownames = FALSE,
      caption = htmltools::tags$caption(
        style = "caption-side: bottom; text-align: center;",
        "Table 3: Code Button with DT"
      )
    )
  })
  1. gt
  • Also, to implement Button-like table with gt, I used HTML in tab_header to button. (Which has onclick for this document)
  • However, gt seems must show body so I used column to button and body to just show empty.
  output$document.gt <- render_gt({
    data.frame(intToUtf8(160)) |>
      gt() |>
      tab_header(
        title = gt::html('<button type="button" class="btn btn-primary" style="width:100%" onclick="Shiny.setInputValue(`foo`, {priority: `event`});">Documents</button>')
      ) |>
      tab_options(
        column_labels.hidden = TRUE
      ) |>
      tab_style(
        style = cell_borders(sides = "all", weight = px(0)),
        locations = cells_body()
      ) |>
      tab_footnote("Table 4: Document button with gt")
  })

  observeEvent(input$foo, {
    shinyjs::runjs('window.open("https://jhk0530.github.io/mine.tables/")')
  })
  1. gemini and cicerone
  • See their own repo please.

E. Summary

I made little game-like shiny application with various table R package, and I hope you enjoy it.


Table Type: interactive-Shiny
Submission Type: Single Table Example
Table: mines.tables - shinyapps.io
Code: GitHub - jhk0530/mine.tables
Language: R
Industries: -
Packages: reactable, DT, and gt

1 Like