• Townie
    AI
  • Blog
  • Docs
  • Pricing
  • We’re hiring!
Log inSign up
bao

bao

cipher

Public
Like
cipher
Home
Code
24
.git
9
.vscode
1
.gitignore
.vtignore
AnotherRound.tsx
App.tsx
GameLink.tsx
GameResult.tsx
KnownTextWarning.tsx
Loading.tsx
Notice.tsx
PUNCTUATION_FEATURE.md
README.md
api.ts
bridge.ts
cipherHelpers.ts
constants.ts
gameHelpers.ts
H
main.tsx
nativeToWeb.ts
networkHelpers.ts
substitutionCipher.test.ts
substitutionCipher.ts
wordHelpers.ts
Branches
5
Pull requests
Remixes
History
Environment variables
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Sign up now
Code
/
PUNCTUATION_FEATURE.md
Code
/
PUNCTUATION_FEATURE.md
Search
10/11/2025
Viewing readonly version of main branch: v504
View latest version
PUNCTUATION_FEATURE.md

Punctuation Preservation Feature

Summary

Successfully implemented punctuation preservation for Aristocrat ciphers while maintaining punctuation stripping for Patristocrat ciphers.

Changes Made

1. substitutionCipher.ts

  • Line 148-158: Updated aristocrat encoding to preserve all punctuation and spacing
  • Line 174: Fixed TypeScript type annotation for encodedLetterCounts

Key Logic:

  • Aristocrat: Encode only letters (/[A-Z]/), preserve everything else (spaces, punctuation)
  • Patristocrat: Strip all non-letters, group into 5-letter blocks (no change from before)

2. App.tsx

Updated to handle letter-only indexing while displaying punctuation:

New Helper Functions (Lines 503-534):

  • visualIndexFor(): Maps group/char position to visual position in encoded string
  • letterIndexFromVisual(): Converts visual position to letter-only array index
  • isLetterAtVisual(): Checks if character at position is a letter

Updated Functions:

  • handleLetterChange(): Works with letter-only indices, finds matching encoded letters
  • handleKeyDown(): Backspace handling with letter-only indices
  • handleClear(): Clears only letter positions
  • isDuplicated(): Checks duplicates using letter-only indices
  • attemptedOriginalFor(): Maps encoded letters to attempted decryption
  • attemptedEncodedFor(): Maps attempted letters to encoded letters

Initialization (Lines 92-98, 169-175):

  • decryptionAttempt now only tracks letters: cipher.encoded.replace(/[^A-Z]/g, '')
  • Input refs array sized for letters only

Rendering (Lines 609-682):

  • Display layer: Shows all characters including punctuation
  • Input layer: Only creates input boxes for letters, displays punctuation as text

3. substitutionCipher.test.ts (New File)

Comprehensive test suite with 8 tests:

  1. Aristocrat - preserves punctuation and spacing: Verifies commas, periods, exclamation marks, etc. are preserved
  2. Aristocrat - letters are properly substituted: Validates correct substitution with apostrophes
  3. Patristocrat - strips punctuation and groups into 5-letter blocks: Ensures no punctuation in output
  4. Patristocrat - same substitution but different formatting: Confirms both use same cipher
  5. Caesar cipher - aristocrat preserves punctuation: Tests Caesar as K1 with empty keyword
  6. Letter counts - only counts letters: Verifies punctuation doesn't affect frequency analysis
  7. cleanOriginal - only contains letters: Ensures answer checking works correctly
  8. Various punctuation marks: Tests hyphens, ellipses, parentheses, etc.

All tests pass! ✅

How It Works

Data Structure

  • cipher.encoded: Full string with letters, spaces, and punctuation (aristocrat) or letters + spaces only (patristocrat)
  • decryptionAttempt[]: Array of only letters (no punctuation or spaces)
  • Mapping: Helper functions convert between visual positions and letter-only array indices

Example Flow

Input: "Hello, World!"

Aristocrat Mode:

  • cipher.encoded: "KHOOR, ZRUOG!" (letters encoded, punctuation preserved)
  • decryptionAttempt: ["", "", "", "", "", "", "", "", "", ""] (10 letters only)
  • User sees: K H O O R , W R U O G ! with inputs only under letters

Patristocrat Mode:

  • cipher.encoded: "KHOOR ZRUOG" (punctuation stripped, grouped)
  • decryptionAttempt: ["", "", "", "", "", "", "", "", "", ""] (same 10 letters)
  • User sees: KHOOR ZRUOG with inputs under all characters

Benefits

  1. More authentic: Real cryptograms preserve punctuation
  2. Better hints: Punctuation provides clues about sentence structure
  3. Cleaner code: Separation between display (with punctuation) and state (letters only)
  4. Backward compatible: Patristocrat unchanged, existing games work
  5. Well tested: Comprehensive test coverage ensures correctness

Testing

Run tests:

deno test substitutionCipher.test.ts

All 8 tests pass with type checking enabled.

FeaturesVersion controlCode intelligenceCLI
Use cases
TeamsAI agentsSlackGTM
DocsShowcaseTemplatesNewestTrendingAPI examplesNPM packages
PricingNewsletterBlogAboutCareers
We’re hiring!
Brandhi@val.townStatus
X (Twitter)
Discord community
GitHub discussions
YouTube channel
Bluesky
Open Source Pledge
Terms of usePrivacy policyAbuse contact
© 2025 Val Town, Inc.