1
0
This repository has been archived on 2026-03-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Timmy-time-dashboard/tests/timmy/test_gematria.py

293 lines
8.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Tests for the gematria computation engine (issue #234).
Alexander Whitestone = 222 in Simple English Gematria.
This is not trivia. It is foundational.
"""
from __future__ import annotations
import pytest
from timmy.gematria import (
CIPHERS,
NOTABLE_NUMBERS,
analyze_number,
compute_all,
compute_value,
factorize,
gematria,
letter_breakdown,
reduce_number,
)
# ── Core cipher computation ──────────────────────────────────────────────────
class TestSimpleCipher:
"""Simple English: A=1, B=2, ..., Z=26."""
def test_single_letter_a(self):
assert compute_value("A", "simple") == 1
def test_single_letter_z(self):
assert compute_value("Z", "simple") == 26
def test_alexander_whitestone(self):
"""The foundational identity — Alexander Whitestone = 222."""
assert compute_value("Alexander Whitestone", "simple") == 222
def test_case_insensitive(self):
assert compute_value("hello", "simple") == compute_value("HELLO", "simple")
def test_ignores_non_alpha(self):
assert compute_value("A-B!C", "simple") == compute_value("ABC", "simple")
def test_empty_string(self):
assert compute_value("", "simple") == 0
def test_spaces_only(self):
assert compute_value(" ", "simple") == 0
def test_numbers_in_text_ignored(self):
assert compute_value("ABC123", "simple") == compute_value("ABC", "simple")
class TestReductionCipher:
"""Full Reduction: each letter reduced to single digit."""
def test_a_is_1(self):
assert compute_value("A", "reduction") == 1
def test_j_is_1(self):
# J=10 → 1+0=1
assert compute_value("J", "reduction") == 1
def test_s_is_1(self):
# S=19 → 1+9=10 → 1+0=1
assert compute_value("S", "reduction") == 1
def test_z_is_8(self):
# Z=26 → 2+6=8
assert compute_value("Z", "reduction") == 8
class TestReverseCipher:
"""Reverse Ordinal: A=26, B=25, ..., Z=1."""
def test_a_is_26(self):
assert compute_value("A", "reverse") == 26
def test_z_is_1(self):
assert compute_value("Z", "reverse") == 1
def test_m_is_14(self):
# M is 13th letter → reverse = 27-13 = 14
assert compute_value("M", "reverse") == 14
class TestSumerianCipher:
"""Sumerian: Simple × 6."""
def test_a_is_6(self):
assert compute_value("A", "sumerian") == 6
def test_z_is_156(self):
assert compute_value("Z", "sumerian") == 156
def test_is_six_times_simple(self):
text = "Alexander Whitestone"
assert compute_value(text, "sumerian") == compute_value(text, "simple") * 6
class TestHebrewCipher:
"""Hebrew-mapped: traditional Hebrew values on Latin alphabet."""
def test_a_is_1(self):
assert compute_value("A", "hebrew") == 1
def test_j_is_10(self):
assert compute_value("J", "hebrew") == 10
def test_k_is_20(self):
assert compute_value("K", "hebrew") == 20
def test_t_is_200(self):
assert compute_value("T", "hebrew") == 200
class TestUnknownCipher:
def test_raises_on_unknown(self):
with pytest.raises(ValueError, match="Unknown cipher"):
compute_value("test", "klingon")
# ── compute_all ──────────────────────────────────────────────────────────────
class TestComputeAll:
def test_returns_all_ciphers(self):
result = compute_all("ABC")
assert set(result.keys()) == set(CIPHERS.keys())
def test_values_are_ints(self):
result = compute_all("test")
for v in result.values():
assert isinstance(v, int)
# ── letter_breakdown ─────────────────────────────────────────────────────────
class TestLetterBreakdown:
def test_simple_breakdown(self):
result = letter_breakdown("AB", "simple")
assert result == [("A", 1), ("B", 2)]
def test_strips_non_alpha(self):
result = letter_breakdown("A B!", "simple")
assert result == [("A", 1), ("B", 2)]
def test_unknown_cipher_raises(self):
with pytest.raises(ValueError):
letter_breakdown("test", "nonexistent")
# ── reduce_number ────────────────────────────────────────────────────────────
class TestReduceNumber:
def test_single_digit(self):
assert reduce_number(7) == 7
def test_double_digit_to_master(self):
# 29 → 2+9=11 → master number, preserved
assert reduce_number(29) == 11
def test_double_digit_non_master(self):
# 28 → 2+8=10 → 1+0=1
assert reduce_number(28) == 1
def test_222_reduces_to_6(self):
assert reduce_number(222) == 6 # 2+2+2=6
def test_master_11(self):
assert reduce_number(11) == 11
def test_master_22(self):
assert reduce_number(22) == 22
def test_master_33(self):
assert reduce_number(33) == 33
def test_zero(self):
assert reduce_number(0) == 0
def test_negative(self):
assert reduce_number(-42) == 6 # abs(-42)=42 → 4+2=6
def test_large_number(self):
assert reduce_number(9999) == 9 # 9+9+9+9=36 → 3+6=9
# ── factorize ────────────────────────────────────────────────────────────────
class TestFactorize:
def test_prime(self):
assert factorize(7) == [7]
def test_composite(self):
assert factorize(12) == [2, 2, 3]
def test_222(self):
assert factorize(222) == [2, 3, 37]
def test_one(self):
assert factorize(1) == [1]
def test_zero(self):
assert factorize(0) == []
def test_large_prime(self):
assert factorize(997) == [997]
# ── analyze_number ───────────────────────────────────────────────────────────
class TestAnalyzeNumber:
def test_222(self):
result = analyze_number(222)
assert result["value"] == 222
assert result["numerological_reduction"] == 6
assert result["prime_factors"] == [2, 3, 37]
assert result["is_prime"] is False
assert result["significance"] == NOTABLE_NUMBERS[222]
def test_prime_detection(self):
assert analyze_number(17)["is_prime"] is True
assert analyze_number(18)["is_prime"] is False
def test_perfect_square(self):
assert analyze_number(144)["is_perfect_square"] is True
assert analyze_number(143)["is_perfect_square"] is False
def test_triangular(self):
assert analyze_number(6)["is_triangular"] is True # 1+2+3
assert analyze_number(7)["is_triangular"] is False
def test_angel_number(self):
assert analyze_number(333).get("angel_number") is True
assert analyze_number(123).get("angel_number") is None
def test_master_number(self):
assert analyze_number(22).get("master_number") is True
# ── gematria tool function (the main interface) ─────────────────────────────
class TestGematriaTool:
"""Test the main gematria() tool function that Timmy calls."""
def test_phrase_mode(self):
result = gematria("Alexander Whitestone")
assert "222" in result
assert "Simple" in result
def test_number_mode(self):
result = gematria("222")
assert "Analysis of 222" in result
assert "Alexander Whitestone" in result
def test_compare_mode(self):
result = gematria("compare: ABC, DEF")
assert "Comparison" in result
assert "ABC" in result
assert "DEF" in result
def test_compare_needs_two(self):
result = gematria("compare: alone")
assert "at least two" in result.lower()
def test_empty_input(self):
result = gematria("123 456")
assert "No alphabetic" in result
def test_whitespace_handling(self):
result = gematria(" ABC ")
assert "Simple" in result
def test_letter_breakdown_in_output(self):
result = gematria("ABC")
assert "Breakdown" in result
assert "A(1)" in result
def test_notable_number_flagged(self):
result = gematria("Alexander Whitestone")
assert "" in result or "222" in result
def test_numerological_root_shown(self):
result = gematria("ABC")
assert "root" in result.lower() or "reduction" in result.lower()