# dm

Purpose: Matrix OCR/text search

## Signature
```lua
local dm = require("dm")

dm.SetPath(dictionary_directory)
dm.SetDict(dictionary_index, dictionary_file_name)
dm.LoadDict(dictionary_index, dictionary_text)
dm.UseDict(dictionary_index)

text, boxes = dm.Ocr(left, top, right, bottom, color_range, similarity)
found, x, y, boxes = dm.FindStr(left, top, right, bottom, target_text, color_range, similarity)
found, x, y, word, boxes = dm.FindMatrix(left, top, right, bottom, matrix_line_text, color_range, similarity)
```

## Example
```lua
local dm = require("dm")

local dictText = [[
4924$A$0.0.5$3.5
]]

dm.LoadDict(0, dictText)
dm.UseDict(0)

local text, boxes = dm.Ocr(100, 300, 420, 360, "FFFFFF-101010", 0.98)
nLog("dm OCR", text, boxes)
```

```lua
local dm = require("dm")

dm.SetPath(XXT_RES_PATH)
dm.SetDict(0, "dm_soft.txt")
dm.UseDict(0)

local found, x, y, boxes = dm.FindStr(0, 0, 307, 215, "Camera", "4D4226-404010", 0.98)
if found then
    touch.tap(x, y)
end
```

```lua
local dm = require("dm")

local matrix = [[
4924$A$0.0.5$3.5
]]

local found, x, y, word, boxes = dm.FindMatrix(100, 300, 420, 360, matrix, "FFFFFF-101010", 0.98)
if found then
    nLog("Matrix found", word, x, y, boxes)
end
```

```lua
local XXTDo = require("XXTDo")
local dm = require("dm")

dm.LoadDict(0, [[
4924$A$0.0.5$3.5
]])
dm.UseDict(0)

XXTDo.runloop {
    name = "dm-demo",
    log = sys.log,
    match_rules = {
        dm_text = function(self)
            local found, x, y, boxes = dm.FindStr(90, 120, 620, 180, self.word, self.color, self.sim or 0.98)
            if found then
                return true, {x = x, y = y, boxes = boxes}
            end
            return false
        end,
    },
    {
        name = "has_title_text",
        rule = "dm_text",
        word = "A",
        color = "FFFFFF-101010",
        run = function(self, index, parent, hit)
            XXTDo.log("Dictionary text hit", hit.x, hit.y)
        end,
    },
}
```

## Dictionary Loading
- `dm.LoadDict(index, text)` loads a matrix dictionary from a string. This is suitable for inline code generated by an agent or by the XXTLanControl matrix dictionary tool.
- `dm.SetPath(path)` sets the dictionary directory. The default is `XXT_RES_PATH`.
- `dm.SetDict(index, filename)` reads a file from the current dictionary directory. This is suitable after placing dictionary files under the project `res/` directory.
- `dm.UseDict(index)` switches the dictionary index used by subsequent `Ocr` / `FindStr` calls. The default index is `0`.

## Color Ranges
```lua
"FFFFFF-101010"
"FFFFFF-101010,F6D66A-080808"
"FFFFFF-101010|F6D66A-080808"
```

The color range consists of one or more `color-tolerance` entries. Both color and tolerance are hexadecimal RGB text. `,` and `|` can both separate multiple color ranges.

## Matrix Lines
```text
bits$word$left.right.match$height.width
bits$word$match$height$width
```

Prefer generating matrix lines with the XXTLanControl matrix dictionary tool. When writing or editing them manually, preserve the `$` sections. `word` is the recognized text, `match` is the number of matched pixels, and `height.width` is the matrix size.

## Returns
- `dm.Ocr` returns `text, boxes`. `boxes` is the list of recognized result regions.
- `dm.FindStr` returns `found, x, y, boxes`. On failure it returns `false, -1, -1, {}`.
- `dm.FindMatrix` returns `found, x, y, word, boxes`. On failure it returns `false, -1, -1, "", {}`.
- Coordinates in `boxes` already include the top-left offset of the search region, so they can be treated as screen coordinates directly.

## Notes
- `dm` must first be loaded with `local dm = require("dm")`. It is not a global module like `screen`, `touch`, or `app`.
- Passing `0, 0, 0, 0` for `left, top, right, bottom` means full screen.
- `target_text` can contain multiple candidates separated by `|`, for example `"OK|Confirm"`.
- `similarity` is a decimal from `0.0` to `1.0`; common values are `0.95` to `0.99`.
- `Ocr` / `FindStr` depend on the dictionary selected by the current `UseDict`.
- `FindMatrix` temporarily creates a dictionary from the provided matrix line text and does not depend on `UseDict`.
- The module also provides aliases such as `SetPath/setPath/set_path`, `Ocr/ocr`, and `FindStr/findStr/find_str`. Examples consistently use the uppercase entry points.
