diff --git a/.github/workflows/generate-listings.yml b/.github/workflows/generate-listings.yml
new file mode 100644
index 0000000..a803ccc
--- /dev/null
+++ b/.github/workflows/generate-listings.yml
@@ -0,0 +1,30 @@
+name: Generate Listings
+on:
+ push:
+ paths:
+ - 'emoji/**'
+ - 'create_listing.py'
+ branches:
+ - master
+jobs:
+ generate:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout Repo
+ uses: actions/checkout@v4
+
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.12'
+
+ - name: Generate listings
+ run: python3 create_listing.py
+
+ - name: Commit changes
+ run: |
+ git config --local user.email "github-actions[bot]@users.noreply.github.com"
+ git config --local user.name "github-actions[bot]"
+ git add README.md index.html
+ git diff --staged --quiet || git commit -m "Update listings"
+ git push
diff --git a/README.md b/README.md
index 27b8b6f..15d401d 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
- |
+ |
 |
 |
 |
@@ -19,7 +19,8 @@
 |
 |
 |
- |
+ |
+ |
@@ -214,7 +215,6 @@
 |
 |
 |
- |
@@ -656,7 +656,7 @@
 |
 |
 |
- |
+ |
 |
 |
 |
@@ -1058,16 +1058,15 @@
 |
 |
 |
- |
 |
 |
 |
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -1077,9 +1076,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -1089,9 +1088,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -1101,9 +1100,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -1113,9 +1112,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -1125,9 +1124,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -1137,10 +1136,9 @@
 |
 |
 |
+ |
- |
- |
 |
 |
 |
@@ -1149,10 +1147,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -1160,22 +1158,24 @@
 |
 |
 |
- |
-
-
+ |
 |
 |
+
+
 |
 |
 |
 |
 |
- |
- |
- |
+ |
+ |
+ |
+ |
+ |
- |
+ |
@@ -1196,7 +1196,7 @@
 |
- |
+ |
 |
 |
 |
@@ -1228,7 +1228,7 @@
 |
 |
 |
- |
+ |
 |
@@ -1253,8 +1253,6 @@
 |
- |
- |
 |
 |
 |
@@ -1263,10 +1261,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -1275,10 +1273,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -1287,10 +1285,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -1299,6 +1297,8 @@
 |
 |
 |
+ |
+ |
@@ -1313,15 +1313,15 @@
 |
 |
 |
- |
+ |
 |
 |
 |
 |
- |
- |
+ |
+ |
 |
 |
 |
@@ -1336,26 +1336,24 @@
 |
 |
 |
- |
- |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
 |
 |
 |
- |
 |
+ |
+ |
+ |
- |
- |
 |
 |
 |
@@ -1364,10 +1362,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -1376,10 +1374,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -1388,10 +1386,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -1400,10 +1398,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -1412,10 +1410,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -1424,10 +1422,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -1436,11 +1434,13 @@
 |
 |
 |
-
-
 |
 |
- |
+
+
+ |
+ |
+ |
@@ -1524,7 +1524,7 @@
 |
 |
 |
- |
+ |
@@ -1546,7 +1546,7 @@
 |
 |
- |
+ |
 |
 |
 |
@@ -1582,7 +1582,7 @@
 |
 |
- |
+ |
 |
 |
 |
@@ -1621,7 +1621,7 @@
 |
 |
 |
- |
+ |
 |
 |
 |
@@ -1716,17 +1716,14 @@
 |
 |
 |
- |
+ |
 |
 |
- |
- |
- |
-
-
 |
 |
 |
+
+
 |
 |
 |
@@ -1734,22 +1731,25 @@
 |
 |
 |
-
-
 |
 |
 |
+
+
 |
 |
 |
 |
 |
 |
- |
+ |
+ |
+ |
+ |
- |
- |
+ |
+ |
@@ -1776,12 +1776,11 @@
 |
 |
 |
- |
 |
 |
+ |
- |
 |
 |
 |
@@ -1791,9 +1790,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -1803,9 +1802,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -1815,9 +1814,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -1826,10 +1825,10 @@
 |
 |
 |
- |
+ |
+ |
- |
 |
 |
 |
@@ -1839,9 +1838,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -1851,9 +1850,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -1861,8 +1860,9 @@
 |
 |
 |
- |
- |
+ |
+ |
+ |
@@ -2021,7 +2021,7 @@
 |
 |
- |
+ |
 |
 |
 |
@@ -2134,12 +2134,11 @@
 |
 |
 |
- |
 |
 |
+ |
- |
 |
 |
 |
@@ -2149,9 +2148,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2161,9 +2160,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2173,10 +2172,11 @@
 |
 |
 |
+ |
- |
- |
+ |
+ |
@@ -2222,7 +2222,6 @@
 |
 |
- |
 |
 |
 |
@@ -2230,9 +2229,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2242,9 +2241,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2254,9 +2253,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2266,9 +2265,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2278,9 +2277,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2290,9 +2289,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2302,9 +2301,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2314,6 +2313,7 @@
 |
 |
 |
+ |
@@ -2383,7 +2383,6 @@
 |
 |
- |
 |
 |
 |
@@ -2391,9 +2390,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2402,22 +2401,22 @@
 |
 |
 |
- |
+ |
+ |
- |
 |
 |
 |
 |
 |
 |
- |
+ |
 |
- |
+ |
+ |
- |
 |
 |
 |
@@ -2427,9 +2426,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2439,9 +2438,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2451,9 +2450,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2463,9 +2462,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2475,9 +2474,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2487,9 +2486,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2499,9 +2498,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2511,9 +2510,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2523,9 +2522,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2535,9 +2534,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2547,9 +2546,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2559,9 +2558,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2571,9 +2570,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2583,9 +2582,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2595,9 +2594,9 @@
 |
 |
 |
+ |
- |
 |
 |
 |
@@ -2606,6 +2605,7 @@
 |
 |
 |
+ |
@@ -2613,7 +2613,7 @@
- |
+ |
 |
 |
 |
@@ -2650,8 +2650,6 @@
 |
- |
- |
 |
 |
 |
@@ -2659,10 +2657,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2671,10 +2669,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2683,10 +2681,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2695,10 +2693,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2707,10 +2705,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2719,10 +2717,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2731,10 +2729,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2743,10 +2741,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2755,10 +2753,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2767,10 +2765,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2779,10 +2777,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2791,10 +2789,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2803,10 +2801,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2815,10 +2813,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2827,10 +2825,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2839,10 +2837,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2851,10 +2849,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2863,10 +2861,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2875,12 +2873,14 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
+ |
+ |
@@ -2938,18 +2938,16 @@
 |
 |
- |
- |
 |
 |
 |
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2958,10 +2956,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2970,10 +2968,10 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
@@ -2982,15 +2980,17 @@
 |
 |
 |
-
-
 |
 |
+
+
 |
 |
 |
 |
 |
+ |
+ |
@@ -3107,7 +3107,7 @@
 |
 |
 |
- |
+ |
 |
 |
 |
@@ -3156,4 +3156,4 @@
- Generated: 2024-04-22T16:38:56+00:00
\ No newline at end of file
+ Generated: 2025-12-15T07:43:56.715401+00:00
\ No newline at end of file
diff --git a/_create-listing.php b/_create-listing.php
deleted file mode 100644
index 689b48a..0000000
--- a/_create-listing.php
+++ /dev/null
@@ -1,66 +0,0 @@
- $icons) {
- $contents .= sprintf("## %s\n\n", $header);
-
- $chunks = array_chunk($icons, $per_row);
-
- $contents .= '' . "\n";
-
- foreach ($chunks as $chunk_icons) {
- $contents .= "\n";
-
- foreach ($chunk_icons as $icon) {
- $file = $icon;
- [$name, $ext] = explode('.', get_basename($icon), 2);
-
- $format = ' | ';
- $contents .= sprintf($format, $per_row_width, $file, $name) . "\n";
- }
-
- $contents .= "
\n";
- }
-
- $contents .= "
\n\n";
-}
-
-$contents .= "\n\n Generated: " . date('c');
-
-file_put_contents($output, $contents);
diff --git a/create_listing.py b/create_listing.py
new file mode 100644
index 0000000..720c414
--- /dev/null
+++ b/create_listing.py
@@ -0,0 +1,231 @@
+#!/usr/bin/env python3
+"""Generate README.md and index.html with emoji listings."""
+
+import html
+import re
+from collections import defaultdict
+from datetime import datetime, timezone
+from pathlib import Path
+from urllib.parse import quote
+
+PER_ROW = 10
+EMOJI_DIR = Path("emoji")
+EXTENSIONS = (".png", ".gif", ".jpg", ".jpeg")
+
+
+def generate_readme(files: list[Path]) -> None:
+ """Generate README.md with HTML tables of all emoji images."""
+ listing = defaultdict(list)
+ for file in files:
+ first_char = file.name[0].lower()
+ if not re.match(r"[a-z]", first_char):
+ first_char = r"\[^a-zA-Z:\]"
+ listing[first_char].append(file)
+
+ per_row_width = f"{100 // PER_ROW}%"
+ contents = "# Emotes\n\n"
+
+ for header in sorted(listing.keys(), key=lambda x: (not x.startswith("\\"), x)):
+ icons = listing[header]
+ contents += f"## {header}\n\n"
+ contents += '\n'
+
+ for i in range(0, len(icons), PER_ROW):
+ chunk = icons[i:i + PER_ROW]
+ contents += "\n"
+
+ for icon in chunk:
+ name = icon.stem
+ encoded_path = f"emoji/{quote(icon.name)}"
+ display_path = f"emoji/{icon.name}"
+
+ contents += (
+ f""
+ f" | \n"
+ )
+
+ contents += "
\n"
+
+ contents += "
\n\n"
+
+ contents += f"\n\n Generated: {datetime.now(timezone.utc).isoformat()}"
+
+ Path("README.md").write_text(contents, encoding="utf-8")
+ print(f"Generated README.md with {len(files)} emojis")
+
+
+def generate_html(files: list[Path]) -> None:
+ """Generate index.html with searchable emoji grid grouped alphabetically."""
+ # Group files by first character
+ listing = defaultdict(list)
+ for file in files:
+ first_char = file.name[0].lower()
+ if not re.match(r"[a-z]", first_char):
+ first_char = "#"
+ listing[first_char].append(file)
+
+ # Build grouped HTML
+ sections = []
+ for header in sorted(listing.keys(), key=lambda x: (x != "#", x)):
+ display_header = "0-9 / Special" if header == "#" else header.upper()
+ emoji_items = []
+ for file in listing[header]:
+ name = file.stem
+ encoded_path = f"emoji/{quote(file.name)}"
+ escaped_name = html.escape(name)
+ emoji_items.append(
+ f' '
+ f'

'
+ )
+ sections.append(
+ f' \n'
+ f' {display_header}
\n'
+ f' \n{chr(10).join(emoji_items)}\n
\n'
+ f' '
+ )
+
+ contents = f'''
+
+
+
+
+ Emotes
+
+
+
+
+
+ {len(files)} emojis
+
+{chr(10).join(sections)}
+
+
+
+
+'''
+
+ Path("index.html").write_text(contents, encoding="utf-8")
+ print(f"Generated index.html with {len(files)} emojis")
+
+
+def main():
+ files = sorted(
+ f for f in EMOJI_DIR.iterdir()
+ if f.suffix.lower() in EXTENSIONS
+ )
+
+ if not files:
+ raise SystemExit("No images to continue with.")
+
+ generate_readme(files)
+ generate_html(files)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..8bc4d27
--- /dev/null
+++ b/index.html
@@ -0,0 +1,2750 @@
+
+
+
+
+
+ Emotes
+
+
+
+
+
+ 2493 emojis
+
+
+ 0-9 / Special
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ A
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ B
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ C
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ D
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ E
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ F
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ G
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ H
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ I
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ J
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ K
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ L
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ M
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ N
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ O
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ P
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ R
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ S
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ T
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ U
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ V
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ W
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Y
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Z
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+