User Tools

Site Tools


judoshiai-en:lua-en

TOC

JudoShiai Lua

JudoShiai Lua is intended to be used with the SVG functionality. Lua is a powerful, efficient, lightweight, embeddable scripting language. It supports procedural programming, object-oriented programming, functional programming, data-driven programming, and data description. Learn Lua here: https://www.lua.org/

Introduction

There are many ways to express the same thing, like competitor’s points. For example, if a competitor has lost you may not want to display “0” but text “LOSS”. Or if there is hikiwake you may want to show text “DRAW”. JudoShiai is quite flexible, but there are limits to what can be done. JudoShiai Lua introduces some extra help.

You may want to have reports not provided by the JudoShiai at the moment. You can create Lua scripts to create SVG pages with the required data.

Example: You want to show the text “LOSS” if the competitor has lost. Now you can do that by writing to SVG file text

%m23p1-1==0'LOSS'

Here

%m Match related text
23 Match number
p Points
1 1 = white, 2 = blue competitor
-1==0’LOSS’Print LOSS if points are 0

What if that is not enough? How to print DRAW in case of hikiwake and still print LOSS? Perhaps you want to have text IPPON flashing red? That is possible by using Lua. The SVG text above is replaced by %, a Lua expression, and match identification:

%[require 'points']m23

Lua code in the example is

require 'points'

m23 sets global Lua variables to values related to match #23.

You have a file points.lua that can write anything on the SVG sheet.

JudoShiai Lua

There are many ways to use Lua scripts.

Use code in SVG files. Example:

Hello %[JS.writesvg('World!')]

SVG file will have text Hello World! It is unpractical to write long pieces of code to the SVG sheet. It is better to have Lua code in a separate file. Example:

Hello %[require 'myhello']

File myhello.lua has a line

JS.writesvg('World!')

Again you will display text Hello World! File must be in one of the directories

HOMEDIR/lualib
/home/myname/lualib   (Linux)
C:\Users\myname\lualib (Windows)

HOMEDIR/lualib/lib
  (for example /home/myname/lualib/lib or C:\Users\myname\lualib\lib)

JudoShiai/svg-lua
  (for example /usr/lib/judoshiai/svg-lua or C:\Program Files\JudoShiai\svg-lua)

JudoShiai/svg-lua/lib
  (for example /usr/lib/judoshiai/svg-lua/lib or
   C:\Program Files\JudoShiai\svg-lua/lib)

You can have Lua file anywhere, but then you must give the whole path:

Hello %[@/PATH/TO/myhello.lua]

Note: @-character indicates that rest of the text is a path to a file. Also on Windows you must use forward slashes.

Global variables defined by JudoShiai

There are some predefined read-only variables that you can use after their values are set. To set match related variables call your Lua function from an SVG page like this:

%[require 'handle_match']m23

m23 sets the following global predefined read-only variables for the match #23 before running Lua file handle_match:

JS_category Index of the category. This has not much use except in SQL command.
JS_number Number of the match.
JS_comp_1 Internal index of the white competitor.
JS_comp_2 Blue competitor. Indexes have not much use except in SQL commands.
JS_score_1 White competitor’s scores (ippons, waza-aris, shidos)
JS_score_2 Scores for the blue competitor.
JS_points_1 Value of the win for the white (ippon = 10 points).
JS_points_2 Blue competitor’s winning points.
JS_match_time Match time in seconds.
JS_comment Match is forced to be next or preparing or delayed.
JS_tatami Default contest area for the match.
JS_group Group number category belongs to.
JS_flags Misc. flags.
JS_forcedtatamiContest area where fight has been moved manually.
JS_forcednumberNumber of the fight, if moved manually.
JS_date Date information of the match as seconds since the Epoch.
JS_legend Legend for the match.
JS_roundnum Round number of the match (first round, repechage, etc.).

To set competitor related variables call your Lua function like this:

%[require 'print_name']m23-1

This will first set white competitor’s name and other data to global variables and then run your Lua file. The following competitor’s variables are set:

JS_first First name.
JS_last Last name.
JS_club Club.
JS_country Country.
JS_comment Comment text.
JS_compid Competitor’s ID.
JS_coachid Competitor’s coach ID.
JS_compix Internal index. Used with SQL commands.
JS_birthyear Year of birth.
JS_grade Grade as an integer. Default: 0 = unknown, 1 = 6. kyu, 2 = 5. kyu, … 7 = 1. dan, 8 = 2. dan, …
JS_regcategoryRegistered category.
JS_category Real category.
JS_weight Weight in grams.
JS_seeding Seeding 1-8.
JS_clubseedingClubseeding.
JS_gender Gender. Male = 1, female = 2.

For the blue competitor the Lua call would be:

%[require 'print_name']m23-2

Lua code is the one surrounded by brackets. You can have any name and arguments.

Other global read-only variables:

InstallationDirInstallation directory of the JudoShiai software.
LuaScriptDir Directory where the script is run.

Functions defined by JudoShiai

There are useful functions that start with JS.:

  JS.sqlrows(sqlcmd)
    Run SQL command.
    Parameters
      sqlrow String. Sql command to perform.
    Returns
      Table of tables.

  JS.writesvg(str)
    Writes SVG code on canvas.
    Parameters
      str    String. SVG code to write to the document.
    Returns
      Nothing.

  JS.getdata(index)
    Get data of competitor or category using index.
    Parameters
      index  Integer. Index of the competitor or category.
    Returns
      Table of data.

  JS.getmatchbytatami(tatami, number)
    Get data about match.
    Parameters
      tatami   Integer. Number of the tatami (1...)
      number   Integer. Number of the match (1...)
    Returns
      Table of data.

  JS.getroundname(round)
    Get round name of a match.
    Parameters
      round  Integer. Round code from database or getmatchbytatami().
    Returns
      String that describes the round.

  JS.setpages(numpages)
    Set total number of pages.
    Parameters
      numpages   Integer. Number of pages in the SVG document.
    Returns
      Nothing.

  JS.getpage()
    Get the current page number. First page is 1.
    Parameters
      None
    Returns
      Current page number (integer) starting from 1.

  JS.flag2base64(country)
    Writes flag of a country as base64 string to SVG document. Data is from\\
  JudoShiai/etc/flags-ioc.
    Parameters
      country  String. IOC abbreviation of the country.
    Returns
      Nothing.

  JS.error(message)
    Opens a window and shows error text.
    Parameters
      message  String. Error text.
    Returns
      Nothing.

  JS.print(text)
    Prints texts to an open window.
    Parameters
      text   String. Text to print.
    Returns
      Nothing.

  JS.getcatdefs()
    Get defined category names.
    Parameters
      None.
    Returns
      Table of categories for men and women.
    Example:
      m, w = JS.getcatdefs()
      returns table m for men:
        {
          [1] = "MenU18",
          [2] = "MenU21",
          [3] = "M",
          numentries = 3,
        }
      and w for women:
        {
          [1] = "WomenU18",
          [2] = "WomenU21",
          [3] = "W",
          numentries = 3,
        }
      Tables have entries 'numentries' that tell the lengths of the tables.

  JS.getsvgbyid(filename, id)
    Returns group whose id is id.
    Parameters
      filename   String. Path to the SVG file
      id         String. Id of the <g id="xxx">...</g>
    Returns
      String that contains the group data.
    Example
      svg = JS.getsvgbyid(InstallationDir .. '/svg-lua/lib/mypage.svg',\\
                        'header')

  JS.getsvggeometry(filename, id)
    Returns position and size of a svg element.
    Parameters
      filename   String. Path to the SVG file
      id         String. Id of the <g id="xxx">...</g>
    Returns
      X and y coordinates of the svg element.
      Width and height of the svg element.
    Example
      local x, y, w, h = JS.getsvggeometry(InstallationDir ..\\
                                         '/svg-lua/lib/mypage.svg', 'header')

  JS.askoption(title, options)
    Asks user to select one of the options. NOTE: Opened window is modal.
    While asking all the other functionality is blocked.
    Please make your selection without delay.
    Parameters
      title    String. Question to ask.
      options  String. Options to select from. Options are\\
                      separated by slashes.
    Returns
      Number of the selected option starting from 1.
    Example
      local color = JS.askoption('Select a color', 'Red/Green/Blue')
      Color will be 1 for Red, 2 for Green, and 3 for Blue.

Example

In the beginning we had a problem how to print competitor’s points. Requirements:

  • Write nothing if the match has not been fought.
  • If match ends up hikiwake (draw) write DRAW.
  • Write LOSS if competitor has no points.
  • We want to write 5 for waza-ari win. Database marks that with number 7.
  • Otherwise, write the database points value.

We have to modify the SVG file. Write text %[require 'pts'; pts(1)]m<n> if you want to print the points of the white competitor and %[require 'pts'; pts(2)]m<n> for the blue competitor (<n> is the match number).

Make a file pts.lua. Start with function pts:

function pts(who)                                   -- line 1
    if JS_points_1 > 0 or JS_points_2 > 0 then      -- line 2
        if JS_points_1 == JS_points_2 then          -- line 3
            JS.writesvg('DRAW')                     -- line 4
        else                                        -- line 5
            if who == 1 then                        -- line 6
                print_points(JS_points_1)           -- line 7
            else                                    -- line 8
                print_points(JS_points_2)           -- line 9
            end
        end
    end
end

Explanation line by line:

1. Define function pts. It has one argument, who. If who is 1 it means white competitor, 2 means blue competitor.

2. Check if the match has been fought. Either white or blue must have points.
JS_points_1 > 0 is true if white has more points than 0. Or is true if blue or white have points.

3. If previous test was true check if the points are the same. This means hikiwake or draw.

4. This line is executed if the points are the same. Write DRAW on the SVG page.

6. Otherwise, check if who is 1.

7. If who is 1 (= white) call function print_points with the white points as its argument.

9. If who was not white call function print_points with the blue points as its argument.

Finally implement function print_points:

function print_points(p)                -- line 1
    if p == 0 then                      -- line 2
        JS.writesvg('LOSS')             -- line 3
    elseif p == 7 then                  -- line 4
        JS.writesvg('5')                -- line 5
    elseif p == 11 then                 -- line 6
        JS.writesvg('DRAW')             -- line 7
    else                                -- line 8
        JS.writesvg(tostring(p))        -- line 9
    end
end

Explanation:

1. Function print_pts has one argument p, the points to print.

2, 3. If p is 0 print LOSS.

4, 5. Otherwise, if p is 7 print 5. In this case a national rule says that waza-ari scores 5 points.

6, 7. Otherwise, if p is 11 print DRAW. In principle draw was detected in the previous function, but let’s have it here too for completion.

9. Otherwise, print points as is.

Points in the database can have the following values:

1: Win by shido

2: Win in golden score when that always scores 1 point

3: Win by koka (not used)

5: Win by yuko (not used)

7: Win by waza-ari

10: Win by ippon

11: Hikiwake

Real points and how they are shown depend on the national rules.

SVG + Lua scripts

There are two ways to run Lua scripts:

  • Embed code to SVG sheets. Lua code is embedded to text by using format %[lua_code_here]
  • Run Lua file. There will be a default SVG file where all the printing goes. Note: The default file has no Inkscape specific definitions. When creating SVG files to include them save them as plain SVG.

Lua embedded in SVG sheets

You can create and print pages generated from SVG files that contain embedded Lua code. Usually Lua code is divided in the two parts:

  • Simple code in the SVG file, that calls the more complicated functions.
  • Code in a Lua file that contains most of the code.

JudoShiai is delivered with example code in directory svg-lua.

There are two ways to use embedded Lua code:

  • Lua in the bracket sheets to use for example non-standard name formats.
  • Separate SVG file that can display for example statistics. In JudoShiai select Tournament → SQL Dialog → Run Script. Select an SVG file to show.

Whenever JudoShiai finds text like %[lua code] the Lua code will be executed. Lua code writes whatever you like, and the output will replace the original %[…].

However, this way you cannot draw graphics since the output from the Lua code will be surrounded by <text…> and </text> tags. Solution is to have one (and only one) command that is called in the end of the SVG file. Text has an exclamation mark between the “%” and “[“:

%![lua code to the end]

Lua file with the default SVG

You can run a Lua script by selecting Results → Run Script. Everything you write goes between main <g> and </g> tags. Next example code draws a 50×60 mm rectangle at position 10, 10:

JS.writesvg("<rect x='10' y='10' height='50' width='60' />")

Normally there are many more parameters, like colors, line style, etc. However, it is not necessary to know the SVG format. You can draw a file and name the objects and import the objects one by one. In the following example we assume you have your Lua code in JudoShiai/svg-lua/mytest.lua and SVG file in JudoShiai/svg-lua/svg/mytest.svg.

Use Inkscape to draw a rectangle. Set its id = myrect. Save it using Save As → Plain SVG (important!) to mytest.svg. Your file looks like this:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http:%%//%%www.inkscape.org/) -->

<svg
   width="210mm"
   height="297mm"
   viewBox="0 0 210 297"
   version="1.1"
   id="svg5"
   xmlns="http:%%//%%www.w3.org/2000/svg"
   xmlns:svg="http:%%//%%www.w3.org/2000/svg">
  <defs
     id="defs2" />
  <g
     id="layer1">
    <rect
       style="fill:#d5e5ff;stroke:#000000;stroke-width:0.3;...MORE..."
       id="myrect"
       width="23.7"
       height="18.4"
       x="11.9"
       y="11.5" />
  </g>
</svg>

Style is a long line. Note the id=“myrect”. Write the following lines to your Lua file:

local rect = JS.getsvgbyid(LuaScriptDir .. '/svg/mytest.svg', 'myrect')

Function JS.getsvgbyid reads object myrect to local variable rect. You can draw it on the SVG canvas simply like this:

JS.writesvg(rect)

It will appear at position 11.9, 11.5. Maybe you want to have another one next to it. First you have to know its dimensions:

local x, y, width, height = JS.getsvggeometry(LuaScriptDir .. '/svg/mytest.svg',\\
                          'myrect')

Now you can draw a copy shifted by width:

JS.writesvg(string.format('<g transform="translate(%d, 0)">', width))
JS.writesvg(rect)
JS.writesvg('</g>')

This way you can make lists just by creating one line that is copied.

string.format replaces %d with the corresponding integer. Why integer since width is a float? Using floats can be dangerous. More in the next paragraph.

Float values in Lua

A decimal separator is a symbol used to separate the integer part from the fractional part of a number written in decimal form (e.g., “.” in 3.14). Different countries officially designate different symbols for use as the separator. Separator can be a dot or a comma. Example:

print(string.format('%f', 3.14))

In many countries this will print 3.14, but in the others 3,14. SVG accepts only the dot as a decimal separator. To be on the safe side it is better to convert the float to a string and then replace possible comma with a dot. Function FloatToStr does that:

function FloatToStr(a)
  local r = tostring(a)
  return r:gsub(',', '.')
end

Now, instead of %f you will use %s for a string. The previous translate line

JS.writesvg(string.format('<g transform="translate(%d, 0)">', width))

changes to

JS.writesvg(string.format('<g transform="translate(%s, 0)">',\\
                        FloatToStr(width))

Page size

The default page size is A4 (210mm x 297mm). You can define your own size by having a comment on the first line of the Lua file:

-- paper width=300 height=200

It is possible to have many sizes for the same Lua code. Create a base file. Then include that in the other files:

-- paper width=300 height=200
paper_w = 300
paper_h = 200\\
require 'mybase'

Use paper_w and paper_h for layout design in mybase.lua.

Multiple pages

SVG has no standard for multiple pages. However, you can draw as many pages as you wish and send them to a printer that can be a PDF file, too.

Set the total number of pages first:

JS.setpages(3)

Next draw you page based on the current page number:

current_page = JS.getpage()
if current_page == 1 then
  print_first_page()
else
  print_something_else()
end

Page changes when you click the visible SVG page with the left or right mouse button. In printer dialog you can select the pages as usual.

SQL commands

Example: Print members of category M-90:

local numrows, tbl = JS.sqlrows(
    'select last,first from competitors where category="M-90"')

Numrows tells how many rows tbl has. Tbl looks like this:

{
  1=    {
      last= "SCHMIDT",
      first= "Leon",
    },
  2=    {
      last= "NEUMANN",
      first= "Maximilian",
    },
  3=    {
      last= "CHRISTENSEN",
      first= "Frederik",
    },
}

There are three rows. You can get last name of the second competitor like this:

last_name = tbl['2']['last']
judoshiai-en/lua-en.txt · Last modified: 2025/01/04 00:20 by hjokinen