# Preston Metadata module

Ports the standalone Python "Preston XML to CSV Converter" v1.3.0
(`com.32thirteen.xmltocsvconverter`). CSV output must stay
byte-for-byte-equivalent with that app — don't "fix" the formulas.

## Input schema

Repeating `<data>` elements at any depth (`.//data`), each with a
`<time>` child and a `<lens>` child holding hex strings (optional
`0x` prefix):

```xml
<data>
  <time>01:00:00:00</time>
  <lens><iris>0000</iris><focus>1388</focus><zoom>0000</zoom><aux>00FF</aux></lens>
</data>
```

Rows missing `<time>` or `<lens>` are skipped; missing lens sub-tags
default to `"0"`; empty timecode becomes `00:00:00:00`. Hex parse
failures decode to 0.

## Conversion constants (authoritative, in PrestonMetadataEngine)

- Focus feet: `round(d / 500, 2)`
- Focus meters: `round(focusFeet * 0.3048, 2)` — two-step rounding,
  applied to the already-rounded feet value on purpose
- Iris T-stop: `d == 0 → 1.4`, else `round(1.4 + d/65535 * (22 − 1.4), 1)`
- Zoom mm: `Int(round(18 + d/65535 * (100 − 18)))`
- Aux: raw decimal

## Output

Five columns, header first; the focus header follows the unit toggle:

```
Timecode,Focus (ft),Iris (T),Zoom(mm),Aux   (Imperial)
Timecode,Focus (m),Iris (T),Zoom(mm),Aux    (Metric)
```

`\r\n` line terminators (Python `csv.writer` default) and Python
`str(float)` number formatting (`10.0`, `6.1`, `3.05`). Output names:
a trailing `..._YYYYMMDD_HHMMSS` (dashes stripped) in the input name
yields `{prefix}{date}_{time}_{unit}.csv`, else `{name}_{unit}.csv`.

The verified test vector lives in
`DIToolsTests/PrestonMetadataEngineTests.swift`; both unit modes
assert exact CSV strings.
