Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

romannumdemo.gno

3.72 Kb · 111 lines
  1// Package romannumdemo is a small gnoweb demo of the Roman-numeral converter
  2// provided by the [p/moul/x/daily/romannum](/p/moul/x/daily/romannum/v0)
  3// library: it renders a table of worked examples and interactive
  4// integer→Roman and Roman→integer conversions.
  5//
  6// It contains no conversion logic of its own — everything comes from
  7// romannum.ToRoman and romannum.FromRoman.
  8package romannumdemo
  9
 10import (
 11	"strconv"
 12	"strings"
 13
 14	"gno.land/p/g1magld5ptgzaktqcexxq0pgq5lmdf0kz6re8hlv/md/v0"
 15	"gno.land/p/g1magld5ptgzaktqcexxq0pgq5lmdf0kz6re8hlv/x/daily/romannum/v0"
 16)
 17
 18// examples are the classic milestones shown by the root Render.
 19var examples = []int{1, 4, 9, 14, 40, 49, 90, 400, 900, 1994, 2024, 3888, 3999}
 20
 21// Render drives gnoweb:
 22//   - ""        or "/"          → a table of example conversions
 23//   - "/<n>"                    → integer → Roman
 24//   - "/r/<roman>"              → Roman → integer
 25func Render(path string) string {
 26	arg := strings.Trim(strings.TrimSpace(path), "/")
 27
 28	switch {
 29	case arg == "":
 30		return renderTable()
 31	case strings.HasPrefix(strings.ToLower(arg), "r/"):
 32		return renderFromRoman(arg[2:])
 33	default:
 34		return renderToRoman(arg)
 35	}
 36}
 37
 38func renderToRoman(arg string) string {
 39	n, err := strconv.Atoi(strings.TrimSpace(arg))
 40	if err != nil {
 41		return "# Roman numeral converter\n\nCould not parse " + md.InlineCode(arg) +
 42			"` as an integer.\n\n" + usage()
 43	}
 44	if n < 1 || n > 3999 {
 45		return "# Roman numeral converter\n\n`" + strconv.Itoa(n) +
 46			"` is out of range — Roman numerals here cover **1..3999**.\n\n" + usage()
 47	}
 48	var b strings.Builder
 49	b.WriteString("# " + strconv.Itoa(n) + " → " + romannum.ToRoman(n) + "\n\n")
 50	b.WriteString("| decimal | roman |\n|---:|:---|\n")
 51	b.WriteString("| " + strconv.Itoa(n) + " | **" + romannum.ToRoman(n) + "** |\n\n")
 52	if n > 1 {
 53		b.WriteString("[« " + strconv.Itoa(n-1) + "](/r/moul/x/daily/romannumdemo/v0:" +
 54			strconv.Itoa(n-1) + ") · ")
 55	}
 56	if n < 3999 {
 57		b.WriteString("[" + strconv.Itoa(n+1) + " »](/r/moul/x/daily/romannumdemo/v0:" +
 58			strconv.Itoa(n+1) + ")")
 59	}
 60	b.WriteString("\n\n" + usage())
 61	return b.String()
 62}
 63
 64func renderFromRoman(arg string) string {
 65	arg = strings.TrimSpace(arg)
 66	n, ok := tryFromRoman(arg)
 67	if !ok {
 68		return "# Roman numeral converter\n\n" + md.InlineCode(arg) +
 69			" is not a valid Roman numeral (1..3999).\n\n" + usage()
 70	}
 71	up := strings.ToUpper(arg)
 72	var b strings.Builder
 73	b.WriteString("# " + up + " → " + strconv.Itoa(n) + "\n\n")
 74	b.WriteString("| roman | decimal |\n|:---|---:|\n")
 75	b.WriteString("| **" + up + "** | " + strconv.Itoa(n) + " |\n\n")
 76	b.WriteString(usage())
 77	return b.String()
 78}
 79
 80// tryFromRoman wraps the panic-on-invalid romannum.FromRoman in a panic-free
 81// (value, ok) shape, so the demo can report a friendly error for bad input.
 82func tryFromRoman(s string) (n int, ok bool) {
 83	defer func() {
 84		if recover() != nil {
 85			n, ok = 0, false
 86		}
 87	}()
 88	return romannum.FromRoman(s), true
 89}
 90
 91func renderTable() string {
 92	var b strings.Builder
 93	b.WriteString("# Roman numeral converter\n\n")
 94	b.WriteString("A tiny demo of the [`p/moul/x/daily/romannum`](/p/moul/x/daily/romannum/v0) ")
 95	b.WriteString("library — the classic `ToRoman` / `FromRoman` kata. ")
 96	b.WriteString("Pure and deterministic.\n\n")
 97	b.WriteString("## Examples\n\n")
 98	b.WriteString("| decimal | roman |\n|---:|:---|\n")
 99	for _, n := range examples {
100		b.WriteString("| [" + strconv.Itoa(n) + "](/r/moul/x/daily/romannumdemo/v0:" +
101			strconv.Itoa(n) + ") | " + romannum.ToRoman(n) + " |\n")
102	}
103	b.WriteString("\n" + usage())
104	return b.String()
105}
106
107func usage() string {
108	return "## Try it\n\n" +
109		"- `:/<n>` — integer → Roman, e.g. `:/2024` → " + romannum.ToRoman(2024) + "\n" +
110		"- `:/r/<roman>` — Roman → integer, e.g. `:/r/MMXXIV` → 2024\n"
111}