### Install and Run Local Development Server Source: https://github.com/nthmost/rheti-python/blob/master/README.md Commands to install project dependencies, create the database, and start the Flask development server. The questions CSV is hot-reloaded on change. ```bash pip install -e . flask --app web shell -c "from web import db; db.create_all()" flask --app web run ``` -------------------------------- ### Flask Test Client Usage for Web Routes Source: https://context7.com/nthmost/rheti-python/llms.txt This example demonstrates how to use Flask's test client to simulate user interactions with the web application, including logging in, starting a test, and answering questions. It assumes the Flask app and necessary routes are configured. ```python # All routes are registered on the Flask app automatically via create_app(). # Route reference: # GET / → landing page (unauthenticated) or dashboard (authenticated) # POST /start → begin new test, clear any saved progress # POST /resume → restore saved in-progress test into session # GET/POST /question → display current question; POST records answer, advances index # GET /finish → score session answers, persist Result, redirect to /results/ # GET /types → list all 9 type profiles (public) # GET /types/ → detailed profile for one type (public) # GET /results/ → full results: ranking, wing, differentiator CTAs (auth required) # GET/POST /results//review → view/edit all answers; recalculates scores on POST # POST /results//claim/ → manually set primary type when scores are tied # GET/POST /results//differentiate?ta=X&tb=Y → motivation/wing mini-test # Example: programmatic test client usage with app.test_client() as client: # Log in client.post('/auth/login', data={'email': 'alice@example.com', 'password': 'securepassword'}) # Start a new test client.post('/start') # Answer all 144 questions from rheti import load_questions questions = load_questions() for q in questions: choice = q.random_choice().code client.post('/question', data={'choice': choice}, follow_redirects=False) # Retrieve results page resp = client.get('/finish', follow_redirects=True) print(resp.status_code) # 200 ``` -------------------------------- ### Rheti Project Deployment Script Source: https://github.com/nthmost/rheti-python/blob/master/README.md The `./deploy.sh` script automates the deployment process. It includes steps for pushing to git, pulling on the server, installing dependencies with pip, and restarting the system service. ```bash ./deploy.sh # git push → pull on zephyr → pip install → systemctl restart ``` -------------------------------- ### SQLAlchemy Database Models and Operations Source: https://context7.com/nthmost/rheti-python/llms.txt This Python snippet demonstrates the creation of database models (User, TestProgress, Result) and common operations like creating a user, verifying passwords, and inspecting saved results. It requires the Flask app context and SQLAlchemy setup. ```python from web import create_app, db from web.models import User, TestProgress, Result app = create_app({'SQLALCHEMY_DATABASE_URI': 'sqlite:///example.db'}) with app.app_context(): db.create_all() # Create a user user = User(email='alice@example.com', display_name='Alice') user.set_password('securepassword') db.session.add(user) db.session.commit() # Verify password print(user.check_password('securepassword')) # True # Manually verify email (bypass email in dev) user.email_verified = True db.session.commit() # Inspect saved results for result in user.results: print(result.top_type) # e.g. 4 print(result.scores) # {'4': 28, '5': 22, ...} print(result.n_questions) # 144 print(result.completed_at) print(result.answers[:2]) # [{'q': 'q1', 'choice': 'a', 'value': 'E'}, ...] # Check for in-progress test prog = TestProgress.query.filter_by(user_id=user.id).first() if prog: print(f"Paused at question {prog.q_index} of 144") print(prog.answers) # list of answer dicts saved so far ``` -------------------------------- ### Test Blueprint Routes Source: https://context7.com/nthmost/rheti-python/llms.txt Provides an overview of the web routes available in the Test blueprint, covering the entire test lifecycle from starting a new test to reviewing results. ```APIDOC ## Web routes — Test blueprint (`web/test.py`) ### Description The test blueprint handles the full lifecycle: start, resume, per-question GET/POST, finish (score + persist), results display, answer review, tie-claiming, and differentiator flow. Questions hot-reload from CSV on mtime change without restarting. ### Route Reference - **GET `/`**: Landing page (unauthenticated) or dashboard (authenticated). - **POST `/start`**: Begin a new test, clearing any saved progress. - **POST `/resume`**: Restore a saved in-progress test into the session. - **GET/POST `/question`**: Display the current question; POST records the answer and advances the index. - **GET `/finish`**: Score session answers, persist `Result`, and redirect to `/results/`. - **GET `/types`**: List all 9 type profiles (public). - **GET `/types/`**: Detailed profile for one type (public). - **GET `/results/`**: Full results: ranking, wing, differentiator CTAs (authentication required). - **GET/POST `/results//review`**: View or edit all answers; recalculates scores on POST. - **POST `/results//claim/`**: Manually set the primary type when scores are tied. - **GET/POST `/results//differentiate?ta=X&tb=Y`**: Motivation/wing mini-test. ### Example: Programmatic Test Client Usage ```python with app.test_client() as client: # Log in client.post('/auth/login', data={'email': 'alice@example.com', 'password': 'securepassword'}) # Start a new test client.post('/start') # Answer all 144 questions from rheti import load_questions questions = load_questions() for q in questions: choice = q.random_choice().code client.post('/question', data={'choice': choice}, follow_redirects=False) # Retrieve results page resp = client.get('/finish', follow_redirects=True) print(resp.status_code) # 200 ``` ``` -------------------------------- ### Get Enneagram Type Differentiator Source: https://context7.com/nthmost/rheti-python/llms.txt Use `get_differentiator` to find the core differences and questions for a given pair of Enneagram types. The order of types does not matter. Returns None for unsupported pairs. ```python pair = get_differentiator(4, 5) # order doesn't matter: get_differentiator(5, 4) is identical if pair: print(pair['title']) # "Type 4 or Type 5?" print(pair['intro']) # explanation of the core difference for i, q in enumerate(pair['questions']): print(f"\nQ{i+1}: {q['stem']}") for type_num, text in q['options']: print(f" [{type_num}] {text}") # Returns None for unsupported pairs print(get_differentiator(1, 7)) # None ``` ```python # Tally user responses to get a recommendation from collections import Counter user_picks = [4, 5, 4, 4, 5, 4] # type numbers chosen per question counts = Counter(user_picks) recommended = counts.most_common(1)[0][0] print(f"Recommended type: {recommended}") # e.g. 4 ``` -------------------------------- ### Score RHETI Test Answers Source: https://context7.com/nthmost/rheti-python/llms.txt Scores a list of answers (type-letter strings) to produce a result dictionary containing the dominant type, full ranking, tied types, and a type description. Includes an example of simulating answers using random choices. ```python from rheti import load_questions, score questions = load_questions() # Simulate a completed test by picking random answers answers = [q.random_choice().value for q in questions] # Or supply a real answer list from user input: # answers = ['E', 'B', 'A', 'G', ...] # one letter per question result = score(answers) print(result['top_type']) # e.g. 4 print(result['top_name']) # e.g. 'The Individualist' print(result['description']) # multi-sentence type description # Full ranking: list of (type_num, name, count) sorted by count descending for type_num, name, count in result['ranking']: print(f"Type {type_num} {name:<22s} {count}") # Tie detection if len(result['tied_types']) > 1: print("Tied types:", result['tied_types']) # e.g. [4, 5] # Raw counts: Counter mapping type number -> score print(result['counts']) # Counter({4: 22, 5: 19, 7: 17, ...}) ``` -------------------------------- ### Enneagram Type Theory Data Access Source: https://context7.com/nthmost/rheti-python/llms.txt Access comprehensive Enneagram type data including wing variants, stress/growth arrows, levels of development, centers of intelligence, and famous examples using constants from `rheti.types`. This data provides rich insights into each Enneagram type. ```python from rheti.types import ( WINGS, WING_DETAIL, ARROWS, STRESS_DESC, GROWTH_DESC, LEVELS, CENTERS, TYPE_CENTER, TYPE_NAMES, FAMOUS ) type_num = 4 # Wing variants for code, (name, summary) in WINGS[type_num].items(): print(f"{code}: {name} — {summary[:60]}...") # 4w3: The Aristocrat — A more outwardly expressive... # 4w5: The Bohemian — A more withdrawn, intellectual... # Detailed wing narrative wing = WING_DETAIL[4]['4w5'] print(wing['name']) # 'The Bohemian' print(wing['summary']) print(wing['emotion']) # emotional center analysis print(wing['stress']) # stress behavior for pattern in wing['patterns']: print('-', pattern) for check in wing['self_check']: print('?', check) # Stress and growth arrows arrows = ARROWS[type_num] print(f"Stress -> Type {arrows['stress']}: {STRESS_DESC[type_num][:80]}...") print(f"Growth -> Type {arrows['growth']}: {GROWTH_DESC[type_num][:80]}...") # Levels of development for level, desc in LEVELS[type_num].items(): print(f"{level}: {desc[:70]}...") # Center of intelligence center_key = TYPE_CENTER[type_num] # 'heart' center = CENTERS[center_key] print(center['name']) # 'Heart / Feeling Center' print(center['types']) # [2, 3, 4] print(center['desc']) # Famous examples print(FAMOUS[type_num]) # ['Frida Kahlo', 'Bob Dylan', ...] ``` -------------------------------- ### Run Development Server Source: https://context7.com/nthmost/rheti-python/llms.txt This snippet shows how to run the Flask development server. Ensure this is placed within an `if __name__ == '__main__':` block. ```python if __name__ == '__main__': app.run(debug=True) ``` -------------------------------- ### User Model Operations Source: https://context7.com/nthmost/rheti-python/llms.txt Demonstrates creating a user, verifying their password, and manually verifying their email. It also shows how to inspect saved test results and check for in-progress tests. ```APIDOC ## User Model Operations ### Description This section details how to interact with the `User` model, including creation, password management, email verification, and accessing associated test progress and results. ### Usage ```python from web import create_app, db from web.models import User, TestProgress, Result app = create_app({'SQLALCHEMY_DATABASE_URI': 'sqlite:///example.db'}) with app.app_context(): db.create_all() # Create a user user = User(email='alice@example.com', display_name='Alice') user.set_password('securepassword') db.session.add(user) db.session.commit() # Verify password print(user.check_password('securepassword')) # True # Manually verify email (bypass email in dev) user.email_verified = True db.session.commit() # Inspect saved results for result in user.results: print(result.top_type) # e.g. 4 print(result.scores) # {'4': 28, '5': 22, ...} print(result.n_questions) # 144 print(result.completed_at) print(result.answers[:2]) # [{'q': 'q1', 'choice': 'a', 'value': 'E'}, ...] # Check for in-progress test prog = TestProgress.query.filter_by(user_id=user.id).first() if prog: print(f"Paused at question {prog.q_index} of 144") print(prog.answers) # list of answer dicts saved so far ``` ``` -------------------------------- ### rheti-python Project Structure Overview Source: https://github.com/nthmost/rheti-python/blob/master/CLAUDE.md Provides a high-level overview of the rheti-python project's directory and file structure. Key components include the core library, CLI runner, data loader, scorer, and web application modules. ```text rheti/ __init__.py # Public API: load_questions(), score() __main__.py # CLI test runner loader.py # CSV → Question objects scorer.py # Type scoring + descriptions question.py # Question / Choice classes questions.csv # 144 questions — auto-reloaded on change pages/ # Individual PDF pages (for reference/editing) web/ # Flask web application (in development) extract_questions.py # Pixel-based bracket detection (dev tool) extract_text_vision.py # Vision LLM text extraction (dev tool) ``` -------------------------------- ### Flask App Factory Configuration Source: https://context7.com/nthmost/rheti-python/llms.txt Use `web.create_app()` to create and configure a Flask application. This factory function registers blueprints, initializes extensions like SQLAlchemy and Flask-Login, and supports environment variable-based configuration or custom testing configurations. ```python from web import create_app # Default config (reads from environment variables) app = create_app() # Override config for testing app = create_app({ 'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///:memory:', 'WTF_CSRF_ENABLED': False, 'MAIL_SUPPRESS_SEND': True, 'SECRET_KEY': 'test-secret', }) with app.app_context(): from web import db db.create_all() ``` -------------------------------- ### Set Production Environment Variables and Run Flask App Source: https://context7.com/nthmost/rheti-python/llms.txt This bash script sets environment variables for production and then runs the Flask application. Remember to replace placeholder values with your actual credentials. ```bash # Environment variables for production export SECRET_KEY="your-secret-key" export DATABASE_URL="sqlite:///web/rheti.db" export MAIL_SERVER="smtp.example.com" export MAIL_PORT=587 export MAIL_USERNAME="you@example.com" export MAIL_PASSWORD="yourpassword" export MAIL_DEFAULT_SENDER="rheti@example.com" flask --app web run ``` -------------------------------- ### Configure Email Verification for Local Development Source: https://github.com/nthmost/rheti-python/blob/master/README.md Environment variables required for email verification to function locally. Verification can be skipped by manually setting `user.email_verified = True` in the shell. ```bash MAIL_SERVER=your.smtp.host MAIL_PORT=587 MAIL_USERNAME=you@example.com MAIL_PASSWORD=yourpassword MAIL_DEFAULT_SENDER=you@example.com ``` -------------------------------- ### RHETI Python API Usage Source: https://github.com/nthmost/rheti-python/blob/master/README.md Demonstrates how to use the rheti Python library to load questions and score user answers. Shows how to access the top type, name, ranking, and tied types from the results. ```python from rheti import load_questions, score questions = load_questions() # list of Question objects answers = ['E', 'A', 'C', ...] # one value per question (A–I) result = score(answers) print(result['top_type']) # e.g. 4 print(result['top_name']) # e.g. 'The Individualist' print(result['ranking']) # all 9 types sorted by score print(result['tied_types']) # list of types that tied for top score ``` -------------------------------- ### Auth Blueprint Routes Source: https://context7.com/nthmost/rheti-python/llms.txt Details the web routes for user authentication, including registration, verification, login, logout, and password reset. ```APIDOC ## Web routes — Auth blueprint (`web/auth.py`) ### Description Handles registration with email verification, login/logout, and password reset. All forms use Flask-WTF CSRF protection. Email enumeration is prevented on the forgot-password endpoint by always returning the same message. ### Route Reference (prefix: `/auth`) - **GET/POST `/auth/register`**: Create account, send verification email. - **GET `/auth/verify/`**: Mark email verified and log user in. - **GET/POST `/auth/login`**: Authenticate with email and password. - **GET `/auth/logout`**: Log out the current user. - **GET/POST `/auth/forgot`**: Send password-reset or re-verification email. - **GET `/auth/results`**: List all of the current user's saved results. ### Example: Programmatic User Registration (Bypassing Email Verification) ```python with app.app_context(): from web.models import User from web import db user = User(email='bob@example.com') user.set_password('mypassword123') user.email_verified = True # skip email step in dev/test db.session.add(user) db.session.commit() print(f"Created user id={user.id}") ``` ``` -------------------------------- ### Run RHETI CLI Test Source: https://github.com/nthmost/rheti-python/blob/master/README.md Execute the RHETI test directly from the command line. Users will be prompted to answer questions, and a ranked breakdown of Enneagram types will be displayed. ```bash rheti # or python -m rheti ``` -------------------------------- ### Load RHETI Test Questions from CSV Source: https://context7.com/nthmost/rheti-python/llms.txt Loads all 144 test questions from the default CSV file or a custom path. Each question object contains choices with codes, values, and text. Demonstrates how to access question numbers, choice details, and handle invalid choices. ```python from rheti import load_questions questions = load_questions() print(len(questions)) # 144 q = questions[0] print(q.qnum) # 'q1' for c in q.choices: print(c.code, c.value, c.text) # a E "I've been romantic and imaginative" # b B "I've been pragmatic and down to earth" # Use a custom CSV (e.g. a subset for testing) subset = load_questions(path='/tmp/my_questions.csv') # Question.choose(code) returns the type-letter value or raises InvalidChoice value = q.choose('a') # returns 'E' try: q.choose('x') except Exception as e: print(e) # Code "x" does not match a Choice for this Question. # Question.random_choice() returns a random Choice object random_pick = q.random_choice() print(random_pick.value) # e.g. 'B' ``` -------------------------------- ### Programmatic User Registration (Bypassing Email Verification) Source: https://context7.com/nthmost/rheti-python/llms.txt This Python snippet shows how to programmatically register a new user, bypassing the email verification step, which is useful for development or testing environments. It requires the Flask app context and database session. ```python # Route reference (prefix: /auth): # GET/POST /auth/register → create account, send verification email # GET /auth/verify/ → mark email verified, log user in # GET/POST /auth/login → authenticate with email + password # GET /auth/logout → log out current user # GET/POST /auth/forgot → send password-reset / re-verification email # GET /auth/results → list all of the current user's saved results # Example: register a user programmatically (bypassing email verification for dev) with app.app_context(): from web.models import User from web import db user = User(email='bob@example.com') user.set_password('mypassword123') user.email_verified = True # skip email step in dev/test db.session.add(user) db.session.commit() print(f"Created user id={user.id}") ``` -------------------------------- ### Python API Usage Source: https://github.com/nthmost/rheti-python/blob/master/README.md This section details how to use the core Python functions `load_questions` and `score` to interact with the RHETI test logic. ```APIDOC ## Python API ```python from rheti import load_questions, score questions = load_questions() # list of Question objects answers = ['E', 'A', 'C', ...] # one value per question (A–I) result = score(answers) print(result['top_type']) # e.g. 4 print(result['top_name']) # e.g. 'The Individualist' print(result['ranking']) # all 9 types sorted by score print(result['tied_types']) # list of types that tied for top score ``` ### Value → type mapping | Letter | Type | Name | |--------|------|------| | A | 9 | The Peacemaker | | B | 6 | The Loyalist | | C | 3 | The Achiever | | D | 1 | The Reformer | | E | 4 | The Individualist | | F | 2 | The Helper | | G | 8 | The Challenger | | H | 5 | The Investigator | | I | 7 | The Enthusiast | ``` -------------------------------- ### load_questions() Source: https://context7.com/nthmost/rheti-python/llms.txt Loads all 144 Enneagram test questions from the default CSV file (`rheti/questions.csv`) or a custom path. Each question is returned as a Question object containing two choices. ```APIDOC ## load_questions() ### Description Loads all 144 test questions from CSV. Reads `rheti/questions.csv` and returns an ordered list of `Question` objects, each holding two `Choice` instances (code `a`/`b`, type-letter value, and display text). Accepts an optional `path` argument to load from a custom CSV location. ### Parameters #### Path Parameters - **path** (str) - Optional - Custom CSV file path. ### Returns - **list[Question]** - An ordered list of Question objects. ### Example ```python from rheti import load_questions questions = load_questions() print(len(questions)) # 144 q = questions[0] print(q.qnum) # 'q1' for c in q.choices: print(c.code, c.value, c.text) # a E "I've been romantic and imaginative" # b B "I've been pragmatic and down to earth" # Use a custom CSV (e.g. a subset for testing) subset = load_questions(path='/tmp/my_questions.csv') # Question.choose(code) returns the type-letter value or raises InvalidChoice value = q.choose('a') # returns 'E' try: q.choose('x') except Exception as e: print(e) # Code "x" does not match a Choice for this Question. # Question.random_choice() returns a random Choice object random_pick = q.random_choice() print(random_pick.value) # e.g. 'B' ``` ``` -------------------------------- ### Rheti Differentiator Questions Module Source: https://github.com/nthmost/rheti-python/blob/master/README.md The `rheti/differentiators.py` script contains question sets for 10 common type pairs. These questions are used to determine differentiators and for wing identification in user results. ```python (1,2) (1,8) (1,9) (2,3) (3,4) (4,5) (5,6) (6,7) (7,8) (8,9) ``` -------------------------------- ### Rheti CLI Runner Source: https://context7.com/nthmost/rheti-python/llms.txt Administer the full Enneagram test interactively in the terminal using the `rheti` command or `python -m rheti`. The CLI displays progress for each question and a bar-chart results summary upon completion. ```bash # Install the package pip install -e . # Run the CLI test rheti # or equivalently: python -m rheti # Example session: # ─── Question 1 of 144 ─── # a) I've been romantic and imaginative # b) I've been pragmatic and down to earth # Your choice (a/b): a # ... # ════════════════════════════════════════════════ # RESULTS # ════════════════════════════════════════════════ # Type 4 The Individualist 28 (19.4%) ████████████████████████████░░░ # Type 5 The Investigator 22 (15.3%) ██████████████████████░░░░░░░░░ # ... # Your dominant type: Type 4 — The Individualist ``` -------------------------------- ### Question and Choice Data Classes Source: https://context7.com/nthmost/rheti-python/llms.txt Utilize `Question` and `Choice` classes to manage Enneagram test questions and their associated options. `load_questions` fetches all questions, and `choose` on a `Question` object validates and returns the selected choice's value. `InvalidChoice` is raised for incorrect codes. ```python from rheti import Question, Choice, InvalidChoice from rheti import load_questions # Inspect structure questions = load_questions() q = questions[5] print(q.qnum) # 'q6' print(len(q.choices)) # 2 for choice in q.choices: print(choice.code) # 'a' or 'b' print(choice.value) # letter A–I print(choice.text) # display text print(choice.select()) # returns choice.value # choose() validates the code value = q.choose('b') # returns the value for choice 'b' # InvalidChoice is raised for bad codes try: q.choose('c') except InvalidChoice as e: print(e) # Code "c" does not match a Choice for this Question. ``` -------------------------------- ### Claude Monitor Status File Format Source: https://github.com/nthmost/rheti-python/blob/master/CLAUDE.md Defines the JSON structure for the Claude Monitor status file, used for tracking task progress. Ensure this file is kept updated during development. ```json { "task_name": "Brief description", "status": "in_progress", "progress_percent": 45, "current_step": "What's happening right now", "message": "Optional extra context", "needs_attention": false, "updated_at": "2026-03-27T12:00:00Z" } ``` -------------------------------- ### Track and Highlight Answer Changes in JavaScript Source: https://github.com/nthmost/rheti-python/blob/master/web/templates/test/review.html This JavaScript code tracks changes made to radio button selections on the review page. It highlights modified answers and displays a count of the changes. Initialize by storing the original selected values. ```javascript const original = {}; document.querySelectorAll('input[type="radio"]:checked').forEach(r => { original[r.name] = r.value; }); function updateChanges() { let changed = 0; document.querySelectorAll('input[type="radio"]').forEach(r => { if (r.checked && original[r.name] !== undefined && r.value !== original[r.name]) { changed++; } }); const el = document.getElementById('change-count'); el.textContent = changed > 0 ? changed + ' answer' + (changed === 1 ? '' : 's') + ' changed' : ''; // Update selected styling live document.querySelectorAll('.review-choice').forEach(lbl => { lbl.classList.remove('review-choice-selected', 'review-choice-changed'); }); document.querySelectorAll('input[type="radio"]:checked').forEach(r => { const lbl = r.closest('.review-choice'); if (lbl) { const wasOriginal = original[r.name] === r.value; lbl.classList.add(wasOriginal ? 'review-choice-selected' : 'review-choice-changed'); } }); } document.querySelectorAll('input[type="radio"]').forEach(r => { r.addEventListener('change', updateChanges); }); ``` -------------------------------- ### Rheti Question Data Format Source: https://github.com/nthmost/rheti-python/blob/master/README.md The `rheti/questions.csv` file contains question data. Each question is represented by two rows, one for each choice, with columns for question ID, choice identifier, the text of the choice, and its associated value. ```csv question,choice,text,value q1,a,"I've been romantic and imaginative",E q1,b,"I've been pragmatic and down to earth",B ``` -------------------------------- ### Auto-advance on Selection - JavaScript Source: https://github.com/nthmost/rheti-python/blob/master/web/templates/test/question.html This JavaScript code listens for changes on radio buttons named 'choice'. When a selection is made, it automatically submits the form with the class 'question-form'. ```javascript document.querySelectorAll('input[name="choice"]').forEach(function(radio) { radio.addEventListener('change', function() { document.querySelector('.question-form').submit(); }); }); ``` -------------------------------- ### Retrieve Enneagram Type Differentiator Mini-Test Source: https://context7.com/nthmost/rheti-python/llms.txt Fetches a mini-test designed to differentiate between two specific Enneagram types. The function is order-independent for type pairs and returns `None` if no differentiator exists for the given pair. ```python from rheti.differentiators import get_differentiator ``` -------------------------------- ### score(answers) Source: https://context7.com/nthmost/rheti-python/llms.txt Scores a completed Enneagram test based on a list of provided answers. Returns a dictionary containing the dominant type, a full ranking of all types, and a description. ```APIDOC ## score(answers) ### Description Scores a completed test. Accepts a list of type-letter strings (one per question, values `A`–`I`) and returns a result dict with the dominant type, full ranking, tied types, and a type description. Letters map to Enneagram types via `TYPE_MAP`. ### Parameters #### Path Parameters - **answers** (list[str]) - Required - A list of single-letter strings representing the user's answers to each question. ### Returns - **dict** - A dictionary containing the test results, including: - `top_type` (int): The number of the highest-scoring Enneagram type. - `top_name` (str): The name of the highest-scoring Enneagram type. - `description` (str): A multi-sentence description of the top type. - `ranking` (list[tuple]): A list of tuples, each containing (type_num, name, count), sorted by count descending. - `tied_types` (list[int]): A list of type numbers that are tied for the highest score. - `counts` (Counter): A Counter object mapping type numbers to their raw scores. ### Example ```python from rheti import load_questions, score questions = load_questions() # Simulate a completed test by picking random answers answers = [q.random_choice().value for q in questions] # Or supply a real answer list from user input: # answers = ['E', 'B', 'A', 'G', ...] # one letter per question result = score(answers) print(result['top_type']) # e.g. 4 print(result['top_name']) # e.g. 'The Individualist' print(result['description']) # multi-sentence type description # Full ranking: list of (type_num, name, count) sorted by count descending for type_num, name, count in result['ranking']: print(f"Type {type_num} {name:<22s} {count}") # Tie detection if len(result['tied_types']) > 1: print("Tied types:", result['tied_types']) # e.g. [4, 5] # Raw counts: Counter mapping type number -> score print(result['counts']) # Counter({4: 22, 5: 19, 7: 17, ...}) ``` ``` -------------------------------- ### TYPE_MAP Source: https://context7.com/nthmost/rheti-python/llms.txt A constant dictionary mapping single-letter Enneagram type codes to their corresponding type number and name. Useful for displaying type information. ```APIDOC ## TYPE_MAP ### Description A dict in `rheti.scorer` mapping the single-letter CSV values to `(type_number, type_name)` tuples. Used internally by `score()` but also useful for display logic. ### Usage Import from `rheti.scorer`. ### Example ```python from rheti.scorer import TYPE_MAP for letter, (num, name) in sorted(TYPE_MAP.items()): print(f"{letter} -> Type {num}: {name}") # A -> Type 9: The Peacemaker # B -> Type 6: The Loyalist # C -> Type 3: The Achiever # D -> Type 1: The Reformer # E -> Type 4: The Individualist # F -> Type 2: The Helper # G -> Type 8: The Challenger # H -> Type 5: The Investigator # I -> Type 7: The Enthusiast ``` ``` -------------------------------- ### RHETI Type Letter-to-Number Mapping Source: https://context7.com/nthmost/rheti-python/llms.txt Accesses the `TYPE_MAP` constant, which maps single-letter answer values to Enneagram type numbers and names. Useful for displaying type information based on scored results. ```python from rheti.scorer import TYPE_MAP for letter, (num, name) in sorted(TYPE_MAP.items()): print(f"{letter} -> Type {num}: {name}") # A -> Type 9: The Peacemaker # B -> Type 6: The Loyalist # C -> Type 3: The Achiever # D -> Type 1: The Reformer # E -> Type 4: The Individualist # F -> Type 2: The Helper # G -> Type 8: The Challenger # H -> Type 5: The Investigator # I -> Type 7: The Enthusiast ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.