about summary refs log blame commit diff stats
path: root/chesstv.tlv
blob: 97766534a7edc6c6a9bb59d403fca99298cbb116 (plain) (tree)
1
2
3
4
5
6
7
8
9
                  
   

                             
                 



                                    

    

                             



                       

                             
                      
               







                                                                          






             

    

                             
                     
                                 
                                                  



                                  

    

                             
                        
                                    
                                                  



                                  

    

                             
                        




                                         

    

                             
                        






                                                                                           
                            
                   
                                           

                  
                                           
     


                                                      

                                 

    

                             
                          
                                                             



                                  
        





                                                                                               
                                

                                        
                                                 

                                        
                                                 



                                       
                                                 

                                       
                                                 
           
         
                                                                         




                                     

    

                             
                      




                                                         

    

                             
                       
                                   

                                                                         
                                               
                                     
                    
                   
                                                                                    
       
                                                                                                 

                                                   
                                      
        

    

                             
                   








                                                                     

    

                             
                 
                      


                              

                                                                                                         



                              



                                                            


                                                        

                  

    

                             
                      
                      


                       



                                     








                                                           
        

    

                             
               

               











                                            
        

    

                             
               

















                                                                                   

    

                             
                





                           
        

    

                             
               












                                                                             
    
 
teliva_program = {
  {
    __teliva_timestamp = [==[
original]==],
    window = [==[
window = curses.stdscr()
-- animation-based app
window:nodelay(true)
lines, cols = window:getmaxyx()]==],
  },
  {
    __teliva_timestamp = [==[
original]==],
    current_game = [==[
current_game = {}]==],
  },
  {
    __teliva_timestamp = [==[
original]==],
    piece_glyph = [==[
piece_glyph = {
  -- for legibility, white pieces also use unicode glyphs for black pieces
  -- we rely on colors to distinguish them
  K = 0x265a,
  Q = 0x265b,
  R = 0x265c,
  B = 0x265d,
  N = 0x265e,
  P = 0x265f,
  k = 0x265a,
  q = 0x265b,
  r = 0x265c,
  b = 0x265d,
  n = 0x265e,
  p = 0x265f,
}]==],
  },
  {
    __teliva_timestamp = [==[
original]==],
    top_player = [==[
function top_player(current_game)
  if current_game.players[1].color == "black" then
    return current_game.players[1]
  end
  return current_game.players[2]
end]==],
  },
  {
    __teliva_timestamp = [==[
original]==],
    bottom_player = [==[
function bottom_player(current_game)
  if current_game.players[1].color == "white" then
    return current_game.players[1]
  end
  return current_game.players[2]
end]==],
  },
  {
    __teliva_timestamp = [==[
original]==],
    render_player = [==[
function render_player(y, x, player)
  curses.mvaddstr(y, x, player.user.name)
  curses.addstr(" ยท ")
  curses.addstr(tostring(player.rating))
end]==],
  },
  {
    __teliva_timestamp = [==[
original]==],
    render_square = [==[
function render_square(current_game, rank, file, highlighted_squares)
  -- decide whether to highlight
  local hl = 0
  if (rank == highlighted_squares.from.rank and file == highlighted_squares.from.file)
      or (rank == highlighted_squares.to.rank and file == highlighted_squares.to.file) then
    hl = 4
  end
  if (rank+file)%2 == 1 then
    -- light square
    curses.attrset(curses.color_pair(1+hl))
  else
    -- dark square
    curses.attrset(curses.color_pair(3+hl))
  end
  curses.mvaddstr((8 - rank + 1)*3,   file*5, "     ")
  curses.mvaddstr((8 - rank + 1)*3+1, file*5, "     ")
  curses.mvaddstr((8 - rank + 1)*3+2, file*5, "     ")
  curses.attrset(curses.A_NORMAL)
end]==],
  },
  {
    __teliva_timestamp = [==[
original]==],
    render_fen_rank = [==[
function render_fen_rank(rank, fen_rank, highlighted_squares)
  local file = 1
  for x in fen_rank:gmatch(".") do
    if x:match("%d") then
      file = file + tonumber(x)
    else
      -- decide whether to highlight
      local hl = 0
      if (rank == highlighted_squares.from.rank and file == highlighted_squares.from.file)
          or (rank == highlighted_squares.to.rank and file == highlighted_squares.to.file) then
        hl = 4
      end
      if (rank+file)%2 == 1 then
        if x < 'Z' then
          -- white piece on light square
          curses.attrset(curses.color_pair(1+hl))
        else
          -- black piece on light square
          curses.attrset(curses.color_pair(2+hl))
        end
      else
        if x < 'Z' then
          -- white piece on dark square
          curses.attrset(curses.color_pair(3+hl))
        else
          -- black piece on dark square
          curses.attrset(curses.color_pair(4+hl))
        end
      end
      curses.mvaddstr((8 - rank + 1)*3+1, file*5+2, utf8(piece_glyph[x]))
      curses.attrset(curses.A_NORMAL)
      file = file + 1
    end
  end
end]==],
  },
  {
    __teliva_timestamp = [==[
original]==],
    render_time = [==[
function render_time(y, x, seconds)
  if seconds == nil then return end
  curses.mvaddstr(y, x, tostring(math.floor(seconds/60)))
  curses.addstr(string.format(":%02d", seconds%60))
end]==],
  },
  {
    __teliva_timestamp = [==[
original]==],
    render_board = [==[
function render_board(current_game)
--?   curses.mvaddstr(1, 50, dump(current_game.fen))
--?   curses.mvaddstr(6, 50, dump(current_game.previously_moved_squares))
  render_player(2, 5, top_player(current_game))
  render_time(2, 35, current_game.bc)
  for rank=8,1,-1 do
    for file=1,8 do
      render_square(current_game, rank, file, current_game.previously_moved_squares)
    end
    render_fen_rank(rank, current_game.fen_rank[8-rank+1], current_game.previously_moved_squares)
  end
  render_player(27, 5, bottom_player(current_game))
  render_time(27, 35, current_game.wc)
end]==],
  },
  {
    __teliva_timestamp = [==[
original]==],
    parse_lm = [==[
function parse_lm(move)
--?   curses.mvaddstr(4, 50, move)
  local file1 = string.byte(move:sub(1, 1)) - 96  -- 'a'-1
  local rank1 = string.byte(move:sub(2, 2)) - 48  -- '0'
  local file2 = string.byte(move:sub(3, 3)) - 96  -- 'a'-1
  local rank2 = string.byte(move:sub(4, 4)) - 48  -- '0'
--?   curses.mvaddstr(5, 50, dump({{rank1, file1}, {rank2, file2}}))
  return {from={rank=rank1, file=file1}, to={rank=rank2, file=file2}}
end]==],
  },
  {
    __teliva_timestamp = [==[
original]==],
    render = [==[
function render(chunk)
  local o = json.decode(chunk)
  if o.t == "featured" then
    current_game = o.d
--?     current_game.lm = "__"
    current_game.previously_moved_squares = {from={rank=0, file=0}, to={rank=0, file=0}}  -- no highlight
  else
    current_game.fen = o.d.fen
    current_game.wc = o.d.wc
    current_game.bc = o.d.bc
--?     current_game.lm = o.d.lm
    current_game.previously_moved_squares = parse_lm(o.d.lm)
--?     window:nodelay(false)
--?     curses.mvaddstr(3, 50, "paused")
  end
  current_game.fen_rank = split(current_game.fen, "%w+")
  render_board(current_game)
  curses.refresh()
end]==],
  },
  {
    __teliva_timestamp = [==[
original]==],
    init_colors = [==[
function init_colors()
  -- colors
  local light_piece = 1
  local dark_piece = 0
  local light_square = 252
  local dark_square = 242
  local light_last_moved_square = 229
  local dark_last_moved_square = 226
  -- initialize colors
  curses.init_pair(1, light_piece, light_square)
  curses.init_pair(2, dark_piece, light_square)
  curses.init_pair(3, light_piece, dark_square)
  curses.init_pair(4, dark_piece, dark_square)
  curses.init_pair(5, light_piece, light_last_moved_square)
  curses.init_pair(6, dark_piece, light_last_moved_square)
  curses.init_pair(7, light_piece, dark_last_moved_square)
  curses.init_pair(8, dark_piece, dark_last_moved_square)
end]==],
  },
  {
    __teliva_timestamp = [==[
original]==],
    main = [==[
function main()
  init_colors()
  local request = {
    url = "https://lichess.org/api/tv/feed",
    sink = function(chunk, err)
             if chunk then
               curses.clear()
               render(chunk)
               curses.getch()
             end
             return 1
           end,
  }
  http.request(request)
end]==],
  },
  {
    __teliva_timestamp = [==[
original]==],
    utf8 = [==[
-- https://stackoverflow.com/questions/7983574/how-to-write-a-unicode-symbol-in-lua
function utf8(decimal)
  local bytemarkers = { {0x7FF,192}, {0xFFFF,224}, {0x1FFFFF,240} }
  if decimal<128 then return string.char(decimal) end
  local charbytes = {}
  for bytes,vals in ipairs(bytemarkers) do
    if decimal<=vals[1] then
      for b=bytes+1,2,-1 do
        local mod = decimal%64
        decimal = (decimal-mod)/64
        charbytes[b] = string.char(128+mod)
      end
      charbytes[1] = string.char(vals[2]+decimal)
      break
    end
  end
  return table.concat(charbytes)
end]==],
  },
  {
    __teliva_timestamp = [==[
original]==],
    split = [==[
function split(s, pat)
  result = {}
  for x in s:gmatch(pat) do
    table.insert(result, x)
  end
  return result
end]==],
  },
  {
    __teliva_timestamp = [==[
original]==],
    dump = [==[
-- https://stackoverflow.com/questions/9168058/how-to-dump-a-table-to-console
function dump(o)
  if type(o) == 'table' then
    local s = '{ '
    for k,v in pairs(o) do
      if type(k) ~= 'number' then k = '"'..k..'"' end
      s = s .. '['..k..'] = ' .. dump(v) .. ','
    end
    return s .. '} '
  else
    return tostring(o)
  end
end]==],
  },
}