pax_global_header 0000666 0000000 0000000 00000000064 15227314342 0014515 g ustar 00root root 0000000 0000000 52 comment=59e16ae27ae69664f54579f6c111b625b046d187
kanarenshu-0.1.4/ 0000775 0000000 0000000 00000000000 15227314342 0013656 5 ustar 00root root 0000000 0000000 kanarenshu-0.1.4/.github/ 0000775 0000000 0000000 00000000000 15227314342 0015216 5 ustar 00root root 0000000 0000000 kanarenshu-0.1.4/.github/FUNDING.yml 0000664 0000000 0000000 00000001571 15227314342 0017037 0 ustar 00root root 0000000 0000000 # These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: nuixyz
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
thanks_dev: # Replace with a single thanks.dev username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
kanarenshu-0.1.4/.github/workflows/ 0000775 0000000 0000000 00000000000 15227314342 0017253 5 ustar 00root root 0000000 0000000 kanarenshu-0.1.4/.github/workflows/release.yml 0000664 0000000 0000000 00000004632 15227314342 0021423 0 ustar 00root root 0000000 0000000 name: release
on:
push:
tags:
- "v*"
permissions:
contents: write
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-go@v5
with:
go-version: "1.23"
- uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
version: latest
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
AUR_KEY: ${{ secrets.AUR_KEY }}
update-source-pkgbuild:
needs: goreleaser
runs-on: ubuntu-latest
steps:
- name: Set up SSH for AUR
run: |
mkdir -p ~/.ssh
echo "${{ secrets.AUR_KEY }}" > ~/.ssh/aur
chmod 600 ~/.ssh/aur
ssh-keyscan aur.archlinux.org >> ~/.ssh/known_hosts
- name: Clone kanarenshu AUR repo
run: |
GIT_SSH_COMMAND="ssh -i ~/.ssh/aur -o IdentitiesOnly=yes" \
git clone ssh://aur@aur.archlinux.org/kanarenshu.git aur-kanarenshu
- name: Bump pkgver and sha256sum
run: |
cd aur-kanarenshu
VERSION="${GITHUB_REF_NAME#v}"
URL="https://github.com/nuixyz/kanarenshu/archive/refs/tags/${GITHUB_REF_NAME}.tar.gz"
SHA=$(curl -sL "$URL" | sha256sum | cut -d' ' -f1)
if [ -z "$SHA" ]; then
echo "Failed to compute sha256sum. Aborting."
exit 1
fi
sed -i "s/^pkgver=.*/pkgver=${VERSION}/" PKGBUILD
sed -i "s/^pkgrel=.*/pkgrel=1/" PKGBUILD
sed -i "s/^sha256sums=.*/sha256sums=('${SHA}')/" PKGBUILD
echo "Updated PKGBUILD:"
cat PKGBUILD
- name: Regenerate .SRCINFO
run: |
cd aur-kanarenshu
docker run --rm -v "$PWD:/pkg" -w /pkg \
--user "$(id -u):$(id -g)" \
archlinux:base-devel \
bash -c "makepkg --printsrcinfo > .SRCINFO"
- name: Commit and push
run: |
cd aur-kanarenshu
git config user.name "nuixyz"
git config user.email "contactme@nuixyz.dev"
if git diff --quiet PKGBUILD .SRCINFO; then
echo "No changes to commit — skipping"
exit 0
fi
git add PKGBUILD .SRCINFO
git commit -m "kanarenshu: update to ${GITHUB_REF_NAME}"
GIT_SSH_COMMAND="ssh -i ~/.ssh/aur -o IdentitiesOnly=yes" git push
kanarenshu-0.1.4/.gitignore 0000664 0000000 0000000 00000000141 15227314342 0015642 0 ustar 00root root 0000000 0000000 # build output
kanarenshu
*.log
debug.log
/dist/
# test files
*_test.go
*.exe
*.out
demo.tape kanarenshu-0.1.4/.goreleaser.yaml 0000664 0000000 0000000 00000003503 15227314342 0016751 0 ustar 00root root 0000000 0000000 version: 2
before:
hooks:
- go mod tidy
builds:
- main: ./cmd/kanarenshu
env:
- CGO_ENABLED=0
ldflags:
- -s -w -X main.version={{.Version}}
goos:
- linux
- windows
- darwin
goarch:
- arm64
- amd64
archives:
- formats: [tar.gz]
name_template: >-
{{ .ProjectName }}_
{{- title .Os }}_
{{- if eq .Arch "amd64" }}x86_64
{{- else }}{{ .Arch }}{{ end }}
format_overrides:
- goos: windows
formats: [zip]
checksum:
name_template: "checksums.txt"
changelog:
sort: asc
use: git
abbrev: 7
groups:
- title: "✨ Features"
regexp: '^feat(\(.+\))?:'
order: 0
- title: "� Bug Fixes"
regexp: '^fix(\(.+\))?:'
order: 1
- title: "🧹 Chores & Refactors"
regexp: '^(chore|refactor|perf)(\(.+\))?:'
order: 2
- title: "Other"
regexp: ".*"
order: 999
format: "* {{ .Message }}"
filters:
exclude:
- "^docs:"
- "^test:"
- "^Merge pull request"
- "^Merge branch"
aurs:
- name: kanarenshu-bin
homepage: "https://github.com/nuixyz/kanarenshu"
description: "A minimal TUI application to practise Japanese from the terminal."
maintainers:
- "nuixyz"
license: "MIT"
private_key: "{{ .Env.AUR_KEY }}"
git_url: "ssh://aur@aur.archlinux.org/kanarenshu-bin.git"
provides:
- kanarenshu
conflicts:
- kanarenshu
package: |-
install -Dm755 "./kanarenshu" "${pkgdir}/usr/bin/kanarenshu"
install -Dm644 "./README.md" "${pkgdir}/usr/share/doc/kanarenshu/README.md"
install -Dm644 "./LICENSE" "${pkgdir}/usr/share/licenses/kanarenshu/LICENSE"
commit_author:
name: nuixyz
email: contactme@nuixyz.dev
commit_msg_template: "kananrenshu-bin: updated to {{ .Tag }}"
goamd64: v1
kanarenshu-0.1.4/LICENSE 0000664 0000000 0000000 00000002047 15227314342 0014666 0 ustar 00root root 0000000 0000000 MIT License
Copyright (c) 2026 nuixyz
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
kanarenshu-0.1.4/README.md 0000664 0000000 0000000 00000013223 15227314342 0015136 0 ustar 00root root 0000000 0000000
��練習 · kanarenshu
A minimal TUI application to practise Japanese kana and kanji from your terminal
---
## Features
- **Hiragana, Katakana, and Mixed** modes for kana practise.
- **Kanji mode**: Graded by JLPT level (the app supports only N5 level currently), testing on on'yomi, kun'yomi, and English meaning.
- **Weight-based character selection** - Characters you answer wrong appear more often, while mastered ones fade out.
- **Level-based progression system** - Unlock new characters as you level up.
- **Per-character stats**: Tracked separately for each mode, including each kanji tier.
- **5 built-in themes**: Tokyo Night, Catppuccin, Gruvbox, Nord, Dracula. Cycle through each theme using `ctrl + t` or get a live preview from the settings menu.
- **Configurable** - lives, hints, and theme, editable via config file or the in-app settings menu.
---
## Installation
Pre-compiled binaries are available in the [Releases](https://github.com/nuixyz/kanarenshu/releases) section.
### AUR
Using Yay:
```bash
yay -S kanarenshu
```
Using Paru:
```bash
paru -S kanarenshu
```
### Nix
Nix users can directly use this repository to get the latest kanarenshu for their system.
Add in your `flake.nix`:
```nix
inputs.kanarenshu.url = "github:nuixyz/kanarenshu";
```
Pass inputs to your modules and then in `configuration.nix`:
```nix
environment.systemPackages = [
inputs.kanarenshu.packages.${pkgs.stdenv.hostPlatform.system}.default
];
```
### Homebrew
Coming soon
### From Source
```bash
git clone https://github.com/nuixyz/kanarenshu
cd kanarenshu
go build ./cmd/kanarenshu
```
### Requirements
- Go 1.21 or later (uses `//go:embed`)
---
## Usage
```
kanarenshu
```
Use the arrow keys or `j/k` to navigate the menu,
`enter` to select.
### Keyboard shortcuts
| Key | Action |
|-----|--------|
| `enter` | Submit answer |
| `esc` | Return to menu |
| `ctrl+t` | Cycle through themes |
| `ctrl+c` | Quit |
| `q` | Quit (menu) |
| `s` | Open settings (menu) |
### Romaji input
Both strict Hepburn and common alternatives are accepted by default:
| Kana | Accepted |
|------|----------|
| � | `shi`, `si` |
| � | `chi`, `ti` |
| � | `tsu`, `tu` |
| � | `fu`, `hu` |
| � | `ji`, `zi` |
| ã‚“ | `n`, `nn` |
### Kanji mode
Select **Kanji** from the main menu, then choose a JLPT level. For each character, any of its on'yomi readings, kun'yomi readings or the English meanings are accepted as a correct answer. A wrong answer reveals the readings and meanings as a hint. Progress of each JLPT tier is tracked independently.
---
## Progression
Kana are grouped into levels of 5, kanji are grouped into levels of 10. The app uses an adaptive learning algorithm to determine how often a character appears in a group:
- A correct answer halves a character's weight.
- A wrong answer doubles it (capped at the initial weight of 400).
- A character is considered mastered once it reaches a threshold weight of 25 or below.
- A level up condition is triggered once every character in the current group is mastered.
The highest unlocked level for each mode is saved automatically and resumed on next launch.
---
## Configuration
On first run, kananrenshu creates a config file at:
```
~/.config/kanarenshu/config.toml
```
```toml
theme = "tokyo-night" # tokyo-night | catppuccin | gruvbox | nord | dracula
lives = 3 # 0 = infinite
romaji_strict = false # true = Hepburn only (e.g. "shi", not "si")
show_hints = true # show reading hint after a wrong answer
```
Changes take effect on next launch, or can be applied live via the in-app settings menu
---
## Themes
Themes can be changed in the settings menu (`s` from the main menu) or cycled in-session with `ctrl+t`. The selected theme is saved to config automatically on save.
| Name | |
|------|-|
| `tokyo-night` | Dark blue — default |
| `catppuccin` | Catppuccin Mocha |
| `gruvbox` | Gruvbox Dark |
| `nord` | Nord |
| `dracula` | Dracula |
---
## Data files
| Path | Contents |
|------|----------|
| `~/.config/kanarenshu/config.toml` | User configuration |
| `~/.local/share/kanarenshu/progress.json` | Level progress and per-character statistics |
| `~/.local/share/kanarenshu/debug.log` | Debug log |
XDG environment variables (`$XDG_CONFIG_HOME`, `$XDG_DATA_HOME`) are respected if set.
---
## Project layout
```
cmd/kanarenshu/ entry point
internal/data/ hiragana, katakana, and kanji groupings; per level pools
internal/game/ session logic, scoring, weight-based progression
internal/storage/ config and progress persistence
internal/theme/ embedded TOML theme palettes
internal/ui/ Bubble Tea screens and reusable components
pkg/romaji/ kana <-> romaji tables and answer checking
pkg/kanji/ kanji data and answer validation (readings/meanings)
```
---
## Dependencies
- [Bubble Tea](https://github.com/charmbracelet/bubbletea) — TUI framework
- [Bubbles](https://github.com/charmbracelet/bubbles) — UI components
- [Lip Gloss](https://github.com/charmbracelet/lipgloss) — Styles and layout
- [BurntSushi/toml](https://github.com/BurntSushi/toml) — TOML parsing
---
## License
MIT
kanarenshu-0.1.4/assets/ 0000775 0000000 0000000 00000000000 15227314342 0015160 5 ustar 00root root 0000000 0000000 kanarenshu-0.1.4/assets/hiragana_session.png 0000664 0000000 0000000 00001300130 15227314342 0021201 0 ustar 00root root 0000000 0000000 ‰PNG
IHDR † Æ 0gšV €IDATxœìýyÐ-Çuž| ˆ�n @�÷}ßµZ²,›–DÑ2í6éÏ3yb옞ˆ‰‰™qtÿáŽè y–ˆ^"º£»ÝnInkiË-Y²iy¡$nâ¾/â
’ E\�}ëÖ=•¿óËßɪシï½wù¡ª2Ož<™yòl•·Þ•7<êæj;xÞ‹_h¯}ýÏÚ™3W잪}üó½÷}vçï´ïÿûöÀý÷Û*(p_E]Ýpe|uЦ%8G8¹B&'SÏfZþ×xá¶Ïˆ‡íÌÆ¼Žè)F¼ñ˜Ô}YáWé³u}q„#á¡‚ºÛv¥èçzØ’ÓsÝ=D´¹ŒaÂQ¸sƒéÿðZ…·;P±‘>@Ü¥ =Ö[fGÝs„#·À‹Ã~ì¯^—ár9>;`9·E>¶ÔaÿH?Ó9Œ§ ë[õ§Æ¢pF4³úzSÕ•57ð!°¿<² ÙÂ��ß®h)^<ØT^¶'3Ú\Ðgè–êLí�†£l|æ+L÷gΜ±‡]}µÝôØGÛSžõ»í©OžiôûW¿û/ìž»ï¶#<Ô0
ÍNDž´ßéŽp6°52*sÉåšÑp¬ƒÂ„ò©,RæºÚÝë¾× 3B[÷½´Ssb6Ö/#~Æsy„#á ¶3j5™ ÂäP)yt³oçé¡_w6ÙñtZœxBg“qrÝ(ØQ‡áTƒ2{kM’ÄB–ÈÙBËñÙéŽhaÿŒEkÿnígK¢l¤[磨µU.ÑP~%×emÌú:øý�4«›¼ë›Ë«èû¨!�°”—
85E�x¥7‡<óu_t‚D[`ü™ñË ö@>°TïçtGsVVÊð¾
žFóªÊ2ü#ág
èƒZŒ-è%&g¦{üÃr¾o4
mgvÖË‚‡m9)Ô
¥Œtú–²#á‚o�B÷^gvH¦šÂæ½™?{Ùž\µ4Á2:q³°Zuÿa85çûQ}(²±ð3�%ƒÝÑ©!lÃcÌ’R~�ãÚ·[þcG•ô�@æKžÄv`ùI}é5žÕ¦T½UÈ!IÓºèíkì2&‚fœ~îtþJŸžŠî¿ï~»ãSŸ±ïÝs�ÝúäÛìñ·Ýjß»ûn+ÿáÿïÿ[¯¸âŠ}Rè}ò;ÂC¸°#¡^ÚNšýÌêÍÖñ-4Žp„ ¶ÈY&oMJœƒö“?c°eoг6YYàœúä{IS& ¬¥tûžÚº‡·Ôe{×`�¶ðš�úáG8{8lÉ-oì[y&…ºäPµ9¾è±èX®éÉ:xKzv'ˆLá”ÄrJ2d{t':Ξ\Ò6;哵=§°LõÍcÞrˆŸ×Æ�Ï#²¶™Zñ{„è:TQW“67ëR–Ū_Åî£<°‹áıe\�·Éx´ÍÊÆ³MgöÜÆûOÉŸþ¼gÙË~ô‡ì�î·3W^u•}üÃ=&…ÎxÔÌd²G ©ßûUÝ3í
YŸÜý2o*h, ^¡?Eï—°fræuYËa+_gÍ¿±¡¤Î–hÃÁO¯˜ÕO'˜–+XNHqP4ŸJZÛ!ÙžÎöx†§ö/â ^ˆ\ö´ð™uÙh½�p„#œ(kÕÖNÍmJ×Ç>i³œ8â€/îóìÔž(R§‰ê0™Ü°Žp„S·voéê8i𫎳ØÒq™þº0™TQ|nM8!¾ÿñÁ‡³I²Œ’P#üÊ|1MoÇe£¾+‡[Gx��}J\ Ž!”oš•³/ªÊÌúC%£¬]• úõl’BK™-Â7Ûñ–ÐióÕ9XÞÇ#Øisäûa”þä‡>jŸûä§÷ß™>SxÀÞü;¿oGAY¹òýÕrçƒ2te�³JÜp¹ê÷\œ0Þ0ÌÏQ£Áe$“o!Ïû-�)ý%e0€‰
²%‰¢3”½íö6ðÔ�<â&˜�N«ë=Í}°TâøJæ�höI5×X72¾l�2�Q“~«h§h3½#á[A9Dÿ´È¤´Jbcy§EðåΨë¿vÕ4BB~Õảq„S ™ƒ=��V·�hÿp–%9�n–ØPí˜vLîZ¿ªgæIáqÿø¼†;JñؘECÑÁ¶Y]¸?ª ‡ê <‹9Ï•>ÓÆ+â `X/hê9Ûð�4n ggî¯Ùèº`;ÜãH(Y—LÅoµØ¦gÇá=ô¶]ùvf:-tüÐ4<t© Íï«(Ëè)ZJp™'ˆás"”-´-TvÔ˜G˜@)Ó¨¨z¨+4H SJ;û^…¿%÷{3tŒÚþê§èÆ «�úAºþ6Ý™tú˜„rÄñ5�É%
ª:ýÁ{]íÃŽÒEØNÑÄý®xQ:ë·ÀIp�p„# d�Òü¬O﨟Õú7†]DN#&ÔÝ1uz¬Ç²Ÿ••Îïñ{ƒû£q„SÊUÇ"JpŒ’ |°€?*±„48I“Õ;/êŠ|¨v}"X'k²þi⸙÷Œ†¢Åó©pT=ó„Ó·n± ÜÛ"�¬~Ô6=
oöl“/¤J²i[µóÒýÊ r,¯Œ×Èã©#f©Ùêø¼ñò½{¾gw|ê³vÅ•»æï}ãëwÙå
œtQÁ;5e…·-–aŠÆhS¨>Š{
_Ñ6³aÖv Í»6eþN?¨=`É3–‘l–m²à�,Kƒõ/ÖÃ~Ú'&vÌÔOÌ0qÓœ T¸¶Ð2Ë>Æj�žó‹<Ä£ xçùŠ{®tzÄ ßÄó¨\é‰t0o%éOµSøŠß#á*XÌ’DüQj,gX>¼_Ú^mNc®P—ò}û�ÿœD×á ÀĕóJ¨pÒÇë'�%|Nt`{¦U*1ÃzA¹`܇ÒcÝ£@ÑQ´²²_%¶Û ¨¹•sµ¯°#\P(ËFíµŸmø�‹’26¸[7„ì¯ñ×ÙÏ}ôø’¼á6Ù®:h»¿Ï&žî»ï>+O¸ýõò<1š>}›nÊ}²«(³
´™ê¬Ì…%Iû:I�Cð|¶}�p�p:a$§ˆãPó2å!ôŒº:ýÓð0ãÞ¨��P‰ò˜½Øðº^ïhÅï‚ÀhiW4&5OùÚ˜åzä$ø[ßIõª×aûíŽp„Ëjê
®«€S¨}¯¿´Žá}Ϲ´î9ÂÚ>îñ#\| ªl
aTÏ>ÄV·à¯á©¤ô¨JäŒæfϬÞûUóx’1áBÀŸp‹Ýù›k¾hï߯Bw³À#€0ë÷G¶Ïcü¢c�–ìiÏšfÏ{W_s�ùþ÷¿o—.qU‹ß;=Ûè">6þÇí8sW¡Íáºd"íp_‰¶7?¬¼rÄJ²á–4¾@Æ¿™É ÑËxÎͶÏçQCŸ>À5�€%kr_{´¬§Òÿ‚'žG‘çŸ2dÁ�Ÿö‰�Kºm|íÙï9oá´’uÙx,3zÉÐRã%ΛÓÖß1ªÆ§ ŠÔ%
Ý—¤.òi'ë¼üe4ë ïJý)™SP’6G8Â¥ ©¹7ôIõ©Æ§é•8j?Åm:ÓûpýÅ휞R"®m]×÷ïNd& KâðÕï•ËŽ~…Š'ÕÁEÛ¯üÇ~·EÞÖ€-£Ä�)ã}Ÿ.Ïþ©±gáöy„‡
8ö²bÖ%nÔÕ,ú¥ØÖŽ™¶11áÒ³)6§$•åA<·¥µÊdÆ"Ä_F4»‘n¼Ïtû¸cfEÿã¼?¸÷ûvæ�ûï·K‹Ü•q@²…6[‹2 ‘ ±Ù&!Dí¦ê2`MÏmPX;˱ÅJdsËa´.%)?Â…Ìs’€¶òB0ø0“I 5Ê�ÿÖûDÌ�÷ÊWëõŽÛqWÛ>5$˜Z†‡ŠÉª(çóðkœz›?tmÊ5ÜÆ5ÎUióXRCÊûSy¾Ž�m³ýj‚FIÊl#Ψ/äMá×A»#áÒ å p ¦OŠ¹ì §
ì±ö=5×9¶”ó)Lì£ÑA}¤ü¦eTv„#œ*Pñéá/ìR#àžTõŒËq%'…²äÓV1*'¨8$à{¤•�IÕ#ÆU8ÙóIð9áÆå˜4ÚBï`Bmú¥ì'òÕéÓ>¥ <¦‘ø’*«„˜3‘{2[6T|N¿ÑWŠÅHûòü·Ùø�À¾m³ïñW
sÙ»¨€¿g�S oËN/¢� º5)·ƒÐpÄÇÝl´
¨É2¤hfô•Qõ2é„›IÍ·ÙÙ;v[æý”ܳEjf:CMÔ1iT8ÁÓŽP¢‚TÇ(‘×þÑÀ#(ñ;FíCÒ
÷a]‚&û^‘÷Ñ›¨Í)&Ž"¾QŸEŒ×�ý'ÂÔüÍ•v„‡T\áWå'²?Ÿù—fÛìKÕu,$£˜;>Ä£8$¾ÆøÃ žèc#ß¾ß1–a_™vÆñˆÛñ‹,1¤„H-68è�TÂQ´¹]‰øk�kV‘pÙS…ÅU×¥m…:cçîÀÒ1qÓêÚ‡âšC>�J(c#yÆ6fñctM_Xg(ðgtÑ9mkË?3 F¤€^-™Ž5â�ŸëF|u¯älMß0°î)T—õ¡€û.ƒ6eОÿ,);¶AçsBy¯Ã°>êÐàW$ô”¬+ÿ¥û©Zj7POeÿ§²ÁúýD÷]p¾úýÚ>UåHë$®ûZ;u¯Æ™ñ»–ØñveãVç
ËT½šãÝ,T›í*pŒÍ“_͆±8Û;r{£:£6Xe(´¼i³ÍÓÅñjÓ´_0D¿¿ýtLùéø¢¼uÑÛXŽ_Z¬O «8ìJ;µ€A‚ÒÐ…ðT;ÄårnCš<ËB*ÍOÚ}YäÐ<."¿½Süha‰ãa‡��wgÃu>R`kÇ÷¼ ªÚØ=¿}¹ìÜŽðPƒ’{VØXVEqÜ#s‘’E[ʘ‡^$ÕõIuz¨ÑQ2_(Y�25‹ÊØ÷›ú)îë†_‚òåþq_ã[„Ö�æÃ“]˜,Šø�Nÿq:³<9•»¦îÚ?om6ÚûFåÎÖוvf½L¢nmÇ4°LÍÓ)‚VIp±Ÿ*ð«åö¨$´Žp„퀾l,×?%Sú÷Gñm&ÿ”l‚49dYrè(ßG¸ˆ ™Ùù‘¶î9¼f{q”˜PuMA˜U§hb�×a’ǯ£~°=Óe>2þ˜NÖŸšƒl|
·dnÀÎ3d~cõ#Ÿr�þÿQVAÅÍ,l|¥ÍÐüè™?�m¿¤lÌ(–šñU�tñ>²‹ö>Úí©ø�Êœ¿¯I™%íJÒ^ihGK4>«¤ÐFˆ§j¸.œBÀÖÿFp.GÖ<È‹?EiŠ›8 šþ¬w•öôòiÏ:(çõbºG-ýÐ@“ƒöŒå¨´¼
Ê8°¨êdh¡O<Õ‚mZy§¤ÿ'í�-L¼x?œ8Šz¼ýü僡¹oÜŸq¿ª•ÓpüF½Á8ªà'Î…C4&EààµÃâkÊêN%¬qžÃ|ƒ’‰§Žö”-ëß~�{ž(½_øz.r�”íƒ‘É Z¿wjR×ä{G}x„“C3ÝEú^¾èÿ_i:�QÖã±/òi¬ZI÷ýhá§”û‹ ö3T¢ÛdáÒV4UŸX—%n�戞JÊ`Ø/‡*lâyã¾'ëûã9Tãåþx.p,Gx° ¬Ü—�mª¸¯6¶3¥/S‚‘ d†¯pöÂåݸß�¿2Ðþa³ÉxƸéaü�1ÇŒ‹u‘Õá%†ŠxFG9s”ã\WÊØq
ƒEUßï›G-£ÂŠ1€ê�§Bò…�b ås3ý�‘>¸ˆý¸óÖØŽ›Y£„Y7tK¶hl$ç«Ó•(‹6ášµC®6lÌ# SÆðzP;òâÏ™F§áT+öÓÖ´)µØM,oG!�¯–o]c#ä¨`BJ%Fâ^�ƒó¾[¿m;ïÈ[ã£éŠº�гÅ9CƒPõÍG¯ìQÄŸßµ¾ãÏß¼ïÃ_U<ôk
¼<ÅØÿ‚ܨX/«J–¼œÇŒí‹iÛ€4¸Žñ3Üu5é“yÏî×èuàzP�äUø*^>·ƒÓ€bû N�úŽK Ú‰!³õýz„#œRpQì v{27(úÖ%7O%7T¿ìrs2'ã/kÇ´3·édãRü`ƒ·ÍæFÑUa^Gót„”†1A±h#ê C†[D[á_*á
äKܼÜNO‹šßÍ͘—sà7SÍô/-¢_uB
ô²$˜L‚ÄÐÚNغS2#¯ÅËQãÖ¤½jÇÄK´ˆJË*¼ÃU9RxíOí´à�ÉúxøÔ@Ã)À"ܶ„k[pë ƒ>3.þØn
tq|Üw�¨}Ʋª6§Ú¤[åeäÛ÷ÕÖùJ[)=³á¾à}qf~b¢…?.í娣îá©Ä“EÎst6J²½c?œÌõÄKTÌŸx¢I%zŠÜÃq<~ÏÉ܈í–>NªŒ#ŸdjûJ
¶9Ìm11ëÖi¤7¬&?ŸõqvÓá–ͬ· l+§R×�æžïëJûLÂ- Ž¢i¢�¬m5ÝϨß#\.ÀÁ^Ô«ˆ§÷ñ>ÁkÊ·h~û=L¿ý6§u”Ó#\œÀ{C¸H2ô¨Â�b÷šÝiÇQ®7ó¤’9è¶«~�•r|NÈp÷©Êz]¥ùǺ¬oæ�idó}Å#<ø�ù9ʇ++tŠhƒõ"žAÿ�…
ïyóñdiãvû¥ñª÷/Æí9ÆxÅOVx_ñ¤Q+s?<01ËòS²’0ef2x9³Fø&Ú[Ònä(·Ëª¨h0ë¡V‰×ÿl$ÎAŸÉs>{áÇäŒAF¯%rðTDì£g¯ÿÉžÀ@6O㟴ðOs,´%”œJ-Z˜%Ðk|ÆyÁu Þp„xΔsn¢î°&ƒiÍ’B\¿§¶È�…ä‡+@åL8^k£j;©×žù§W¬q�0®÷‰üáÉšwæŠÕ“M~‘gâ8ÃQ‹X�ǹ¯íºt1жd,]ä¢��~¬|5‡kþã �qÇS<‘ž÷…AZq(8·Y@c@'–#ÿNW÷oOJX‡œ/¥}k&ûʤnM¾�B×ËÊ \Í£�Én[¶ñ®ÀžÃŸ'øsèñ°/\Žâ©üéUã�*¬‘ïÃÆníö*WÄÛ
øÓ0L˜¨·î¬ðÕØqL¾ïØYŠ�\«cûÅ{´ýÜÃ`¯ñ—'„[Ÿ5ôéÉ'âa_Mã'ò ÷Xs¸¿÷+[Ad*ÜW-þ];$ª‘ÖÕ&��‘fœ*ðŠÀ+üa]4Öî3|„KzŸ6ÿ˜4ãª$Rô
bÝò,ý”-r}„#œnÀ¤HYãQB†ý¾G\p½Â='¨�n†ÃcÉž3\Ž…q>wmŒjþ˜å¦q_Ž«èc®�œ³crè¼ûªœmû/…îÙW2(ËÚíšmfÞXY»Cüe¾ñŒ‡>ðÐ ÛÓvhÆGÿÚýû˜0B»ˆ}ÈóQasùë
U\³z®cP‚€‹™Ñý-ë<Ь©à~ ܪþ îêO!,þÜ
¯ã®Y�Ì4"žó‰¿áï窄q6ÎSÊ|ÝÔ6Zf|"£õG%`ËÄëS°%oFµ±•R©ÉóH>/UPsÂ{ªîá>¼«þÙË|üQ99Í~/hǪ¯³%á,_ùÍ9Ó�z 2mœçÙ÷iKÌðÜÕø]ÝW•ö‰÷]œ×>9ÃFHApQõ¶�ú)þËk±m[Ó�f2™lJ÷Z�«^fHùZúéŒ;¬…
Ðk85yf½›é;tt¸®ŠveЇ‰òbZ§*þ¶ÀÀé:‡ÌeŸC�ül{¸ÉŽë匶~Htv<“ã#áâmOsö�ø~ÔFá`âƒ]qvñX? nPöÄO6lŠxnØÏc¾³0�imY—µº#œ/`ŸÃ,÷EðŠxlCÌ´_¤6[!:XEªÊýy´Ù$DžgòÕØÇSû}zôÍ9ÞGZ_´~ðóS$ƒJˆÅÎDæa¬FõpêJ9´U‹®´÷#Â~Y‹4y¨˜… ²ÀD÷‚ÝÊ|²KÇzl_
¢�"šûÆ «Ö\¸cP¥~ãßOŸ÷áã². m‚ÒÆBPH3¶–0[¼&ÒjT’¤P‰*ËšÞˆ“¬Ý¥J#D…Úe‘ƒ™tþŠ ¨Úµ„À!&6KP+È[S^�6*9g¯]ñ÷±ñ»CÈStmÌn;ÍS+‹þòûr¸·À¼«vZ8Ak"jã‹cÆ9lãl
ç©ÍOm.*õÛæ0ÈK[/œ?¥G1éƒú°OÄÌŽ#ê]\ñžÛd¹g9õûÂG€'¿B›Èa´›€¯÷#Ö©{ƒ²2¨¯ƒ¾*Ѩ+ø–ô]D™‚|�pa¡
—eO7ïÿ@gàÛM[Ü¥£5Ö/¬ŽpVpœÂ‡jþ@½Ã‡6
ÐnãUµn\¨ó6àXÔ3÷©è2oÚ×Ó|kÝ4~Þ
Ìwö¼Ì‡áüûì‹Õ{]Ï™¯5ê÷@[m”Ðý VUqÁ>¢Ü㉣DÆ8‘Ló7Íø;Æñåû´ÎƒûÔìo»Ïßïébgø9Î]°Á®GÇ¡Ó@1êX×P
G9ëŒ×Ù�±…åœìÁ,H¨_˜ž^›;šp´ ª}ç£u[d_¾x.D0’Ù>0S€Îm¼ê_~bœxuþ8°EšÎ›d®ÛL@ÜX3»2`%1V kø#(󥿍ˆ6Õ†æO쓹¸Ñç$*¯(¿QÏ Rkûeû0â£Jþ;õ˜˜ä±ƒ®˜®�IB�àÔkËjAÿSûå?sû¢öG“cTôQÿè5l¶Š“m¶ôÓôö]h]Pïp`‡:ñêý6çgÔ
O}0é»N´Ž/³jêYâÄbÒË9¹ÄIO%ïü2A%Ä«i»Mk´½•×P+Q¯å¾EéÄuå=j2‰¤Ú³.i_©�ŸGx°�Ó¢ÎV‰ofzk¨ß¿,+('fG9I žcÝ¥èòœ&