├── .env
├── .prettierrc
├── src
├── react-app-env.d.ts
├── lib
│ ├── keyboard.ts
│ ├── words.ts
│ ├── share.ts
│ ├── localStorage.ts
│ ├── stats.ts
│ └── statuses.ts
├── setupTests.ts
├── App.test.tsx
├── components
│ ├── grid
│ │ ├── EmptyRow.tsx
│ │ ├── CompletedRow.tsx
│ │ ├── CurrentRow.tsx
│ │ ├── Grid.tsx
│ │ └── Cell.tsx
│ ├── mini-grid
│ │ ├── MiniGrid.tsx
│ │ ├── MiniCompletedRow.tsx
│ │ └── MiniCell.tsx
│ ├── stats
│ │ ├── Histogram.tsx
│ │ ├── Progress.tsx
│ │ └── StatBar.tsx
│ ├── modals
│ │ ├── StatsModal.tsx
│ │ ├── AboutModal.tsx
│ │ ├── InfoModal.tsx
│ │ ├── WinModal.tsx
│ │ └── BaseModal.tsx
│ ├── alerts
│ │ └── Alert.tsx
│ └── keyboard
│ │ ├── Key.tsx
│ │ └── Keyboard.tsx
├── index.css
├── reportWebVitals.ts
├── index.tsx
├── App.css
├── logo.svg
├── App.tsx
└── constants
│ └── wordlist.ts
├── public
├── robots.txt
├── favicon.ico
├── logo192.png
├── logo512.png
├── manifest.json
└── index.html
├── Dockerfile
├── .vscode
└── settings.json
├── postcss.config.js
├── tailwind.config.js
├── .gitignore
├── tsconfig.json
├── README.md
├── LICENSE
└── package.json
/.env:
--------------------------------------------------------------------------------
1 | CI= npm run build
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | singleQuote: true
2 | semi: false
3 |
--------------------------------------------------------------------------------
/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LukeRoantree4815162342/wordle/main/public/favicon.ico
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LukeRoantree4815162342/wordle/main/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LukeRoantree4815162342/wordle/main/public/logo512.png
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node
2 |
3 | COPY . .
4 | RUN npm install
5 |
6 | EXPOSE 3000
7 | CMD npm run start
8 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.formatOnSave": true,
3 | "editor.defaultFormatter": "esbenp.prettier-vscode"
4 | }
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/src/lib/keyboard.ts:
--------------------------------------------------------------------------------
1 | import { CharValue } from './statuses'
2 |
3 | export type KeyValue = CharValue | 'ENTER' | 'DELETE'
4 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | content: ['./src/**/*.{js,jsx,ts,tsx}'],
3 | theme: {
4 | extend: {},
5 | },
6 | plugins: [],
7 | }
8 |
--------------------------------------------------------------------------------
/src/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom'
6 |
--------------------------------------------------------------------------------
/src/App.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { render, screen } from '@testing-library/react'
3 | import App from './App'
4 |
5 | test('renders learn react link', () => {
6 | render( )
7 | const linkElement = screen.getByText(/learn react/i)
8 | expect(linkElement).toBeInTheDocument()
9 | })
10 |
--------------------------------------------------------------------------------
/src/components/grid/EmptyRow.tsx:
--------------------------------------------------------------------------------
1 | import { Cell } from './Cell'
2 |
3 | export const EmptyRow = () => {
4 | const emptyCells = Array.from(Array(5))
5 |
6 | return (
7 |
8 | {emptyCells.map((_, i) => (
9 | |
10 | ))}
11 |
12 | )
13 | }
14 |
--------------------------------------------------------------------------------
/src/components/mini-grid/MiniGrid.tsx:
--------------------------------------------------------------------------------
1 | import { MiniCompletedRow } from './MiniCompletedRow'
2 |
3 | type Props = {
4 | guesses: string[]
5 | }
6 |
7 | export const MiniGrid = ({ guesses }: Props) => {
8 | return (
9 |
10 | {guesses.map((guess, i) => (
11 |
12 | ))}
13 |
14 | )
15 | }
16 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | .cell-animation {
6 | animation: revealCharCell linear;
7 | animation-duration: 0.15s;
8 | }
9 |
10 | @keyframes revealCharCell {
11 | 0% {
12 | transform: scale(1);
13 | }
14 |
15 | 50% {
16 | transform: scale(1.1);
17 | }
18 |
19 | 100% {
20 | transform: scale(1);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/src/reportWebVitals.ts:
--------------------------------------------------------------------------------
1 | import { ReportHandler } from 'web-vitals'
2 |
3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => {
4 | if (onPerfEntry && onPerfEntry instanceof Function) {
5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
6 | getCLS(onPerfEntry)
7 | getFID(onPerfEntry)
8 | getFCP(onPerfEntry)
9 | getLCP(onPerfEntry)
10 | getTTFB(onPerfEntry)
11 | })
12 | }
13 | }
14 |
15 | export default reportWebVitals
16 |
--------------------------------------------------------------------------------
/src/components/grid/CompletedRow.tsx:
--------------------------------------------------------------------------------
1 | import { getGuessStatuses } from '../../lib/statuses'
2 | import { Cell } from './Cell'
3 |
4 | type Props = {
5 | guess: string
6 | }
7 |
8 | export const CompletedRow = ({ guess }: Props) => {
9 | const statuses = getGuessStatuses(guess)
10 |
11 | return (
12 |
13 | {guess.split('').map((letter, i) => (
14 | |
15 | ))}
16 |
17 | )
18 | }
19 |
--------------------------------------------------------------------------------
/src/components/mini-grid/MiniCompletedRow.tsx:
--------------------------------------------------------------------------------
1 | import { getGuessStatuses } from '../../lib/statuses'
2 | import { MiniCell } from './MiniCell'
3 |
4 | type Props = {
5 | guess: string
6 | }
7 |
8 | export const MiniCompletedRow = ({ guess }: Props) => {
9 | const statuses = getGuessStatuses(guess)
10 |
11 | return (
12 |
13 | {guess.split('').map((letter, i) => (
14 |
15 | ))}
16 |
17 | )
18 | }
19 |
--------------------------------------------------------------------------------
/src/components/grid/CurrentRow.tsx:
--------------------------------------------------------------------------------
1 | import { Cell } from './Cell'
2 |
3 | type Props = {
4 | guess: string
5 | }
6 |
7 | export const CurrentRow = ({ guess }: Props) => {
8 | const splitGuess = guess.split('')
9 | const emptyCells = Array.from(Array(5 - splitGuess.length))
10 |
11 | return (
12 |
13 | {splitGuess.map((letter, i) => (
14 | |
15 | ))}
16 | {emptyCells.map((_, i) => (
17 | |
18 | ))}
19 |
20 | )
21 | }
22 |
--------------------------------------------------------------------------------
/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import './index.css'
4 | import App from './App'
5 | import reportWebVitals from './reportWebVitals'
6 |
7 | ReactDOM.render(
8 |
9 |
10 | ,
11 | document.getElementById('root')
12 | )
13 |
14 | // If you want to start measuring performance in your app, pass a function
15 | // to log results (for example: reportWebVitals(console.log))
16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
17 | reportWebVitals()
18 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "esModuleInterop": true,
8 | "allowSyntheticDefaultImports": true,
9 | "strict": true,
10 | "forceConsistentCasingInFileNames": true,
11 | "noFallthroughCasesInSwitch": true,
12 | "module": "esnext",
13 | "moduleResolution": "node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true,
17 | "jsx": "react-jsx"
18 | },
19 | "include": ["src"]
20 | }
21 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/src/components/stats/Histogram.tsx:
--------------------------------------------------------------------------------
1 | import { GameStats } from '../../lib/localStorage'
2 | import { Progress } from './Progress'
3 |
4 | type Props = {
5 | gameStats: GameStats
6 | }
7 |
8 | export const Histogram = ({ gameStats }: Props) => {
9 | const { totalGames, winDistribution } = gameStats
10 |
11 | return (
12 |
13 | {winDistribution.map((value, i) => (
14 |
20 | ))}
21 |
22 | )
23 | }
24 |
--------------------------------------------------------------------------------
/src/components/stats/Progress.tsx:
--------------------------------------------------------------------------------
1 | type Props = {
2 | index: number
3 | size: number
4 | label: string
5 | }
6 |
7 | export const Progress = ({ index, size, label }: Props) => {
8 | return (
9 |
10 |
{index + 1}
11 |
12 |
16 | {label}
17 |
18 |
19 |
20 | )
21 | }
22 |
--------------------------------------------------------------------------------
/src/components/mini-grid/MiniCell.tsx:
--------------------------------------------------------------------------------
1 | import { CharStatus } from '../../lib/statuses'
2 | import classnames from 'classnames'
3 |
4 | type Props = {
5 | status: CharStatus
6 | }
7 |
8 | export const MiniCell = ({ status }: Props) => {
9 | const classes = classnames(
10 | 'w-10 h-10 border-solid border-2 border-slate-200 flex items-center justify-center mx-0.5 text-lg font-bold rounded',
11 | {
12 | 'bg-white': status === 'absent',
13 | 'bg-green-500': status === 'correct',
14 | 'bg-yellow-500': status === 'present',
15 | }
16 | )
17 |
18 | return (
19 | <>
20 |
21 | >
22 | )
23 | }
24 |
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/components/grid/Grid.tsx:
--------------------------------------------------------------------------------
1 | import { CompletedRow } from './CompletedRow'
2 | import { CurrentRow } from './CurrentRow'
3 | import { EmptyRow } from './EmptyRow'
4 |
5 | type Props = {
6 | guesses: string[]
7 | currentGuess: string
8 | }
9 |
10 | export const Grid = ({ guesses, currentGuess }: Props) => {
11 | const empties =
12 | guesses.length < 5 ? Array.from(Array(5 - guesses.length)) : []
13 |
14 | return (
15 |
16 | {guesses.map((guess, i) => (
17 |
18 | ))}
19 | {guesses.length < 6 && }
20 | {empties.map((_, i) => (
21 |
22 | ))}
23 |
24 | )
25 | }
26 |
--------------------------------------------------------------------------------
/src/components/modals/StatsModal.tsx:
--------------------------------------------------------------------------------
1 | import { StatBar } from '../stats/StatBar'
2 | import { Histogram } from '../stats/Histogram'
3 | import { GameStats } from '../../lib/localStorage'
4 | import { BaseModal } from './BaseModal'
5 |
6 | type Props = {
7 | isOpen: boolean
8 | handleClose: () => void
9 | gameStats: GameStats
10 | }
11 |
12 | export const StatsModal = ({ isOpen, handleClose, gameStats }: Props) => {
13 | return (
14 |
15 |
16 |
17 | Guess Distribution
18 |
19 |
20 |
21 | )
22 | }
23 |
--------------------------------------------------------------------------------
/src/lib/words.ts:
--------------------------------------------------------------------------------
1 | import { WORDS } from '../constants/wordlist'
2 | import { VALIDGUESSES } from '../constants/validGuesses'
3 |
4 | export const isWordInWordList = (word: string) => {
5 | return (
6 | WORDS.includes(word.toLowerCase()) ||
7 | VALIDGUESSES.includes(word.toLowerCase())
8 | )
9 | }
10 |
11 | export const isWinningWord = (word: string) => {
12 | return solution === word
13 | }
14 |
15 | export const getWordOfDay = () => {
16 | // January 1, 2022 Game Epoch
17 | const epochMs = 1641013200000
18 | const now = Date.now()
19 | const msInDay = 86400000
20 | const index = Math.floor((now - epochMs) / msInDay)
21 |
22 | return {
23 | solution: WORDS[index].toUpperCase(),
24 | solutionIndex: index,
25 | }
26 | }
27 |
28 | export const { solution, solutionIndex } = getWordOfDay()
29 |
--------------------------------------------------------------------------------
/src/components/grid/Cell.tsx:
--------------------------------------------------------------------------------
1 | import { CharStatus } from '../../lib/statuses'
2 | import classnames from 'classnames'
3 |
4 | type Props = {
5 | value?: string
6 | status?: CharStatus
7 | }
8 |
9 | export const Cell = ({ value, status }: Props) => {
10 | const classes = classnames(
11 | 'w-14 h-14 border-solid border-2 flex items-center justify-center mx-0.5 text-lg font-bold rounded',
12 | {
13 | 'bg-white border-slate-200': !status,
14 | 'border-black': value && !status,
15 | 'bg-slate-400 text-white border-slate-400': status === 'absent',
16 | 'bg-green-500 text-white border-green-500': status === 'correct',
17 | 'bg-yellow-500 text-white border-yellow-500': status === 'present',
18 | 'cell-animation': !!value,
19 | }
20 | )
21 |
22 | return {value}
23 | }
24 |
--------------------------------------------------------------------------------
/src/lib/share.ts:
--------------------------------------------------------------------------------
1 | import { getGuessStatuses } from './statuses'
2 | import { solutionIndex } from './words'
3 |
4 | export const shareStatus = (guesses: string[]) => {
5 | navigator.clipboard.writeText(
6 | `Not Wordle ${solutionIndex} ${guesses.length}/6\n\n` +
7 | generateEmojiGrid(guesses)
8 | )
9 | }
10 |
11 | export const generateEmojiGrid = (guesses: string[]) => {
12 | return guesses
13 | .map((guess) => {
14 | const status = getGuessStatuses(guess)
15 | return guess
16 | .split('')
17 | .map((letter, i) => {
18 | switch (status[i]) {
19 | case 'correct':
20 | return '🟩'
21 | case 'present':
22 | return '🟨'
23 | default:
24 | return '⬜'
25 | }
26 | })
27 | .join('')
28 | })
29 | .join('\n')
30 | }
31 |
--------------------------------------------------------------------------------
/src/components/modals/AboutModal.tsx:
--------------------------------------------------------------------------------
1 | import { BaseModal } from './BaseModal'
2 |
3 | type Props = {
4 | isOpen: boolean
5 | handleClose: () => void
6 | }
7 |
8 | export const AboutModal = ({ isOpen, handleClose }: Props) => {
9 | return (
10 |
11 |
12 | This is an open source clone of the game Wordle -{' '}
13 |
17 | check out the code here
18 | {' '}
19 | and{' '}
20 |
24 | play the original here
25 |
26 |
27 |
28 | )
29 | }
30 |
--------------------------------------------------------------------------------
/src/components/stats/StatBar.tsx:
--------------------------------------------------------------------------------
1 | import { GameStats } from '../../lib/localStorage'
2 |
3 | type Props = {
4 | gameStats: GameStats
5 | }
6 |
7 | const StatItem = ({
8 | label,
9 | value,
10 | }: {
11 | label: string
12 | value: string | number
13 | }) => {
14 | return (
15 |
16 |
{value}
17 |
{label}
18 |
19 | )
20 | }
21 |
22 | export const StatBar = ({ gameStats }: Props) => {
23 | return (
24 |
25 |
26 |
27 |
28 |
29 |
30 | )
31 | }
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Wordle Clone - In Irish / As Gaeilge
2 |
3 | ## STATUS: Work In Progress
4 |
5 | ---
6 | ### The majority of this clone was written by [hannahcode](https://github.com/hannahcode/wordle) for her Wordle Clone, my only contributions are in tweaking that code base to use an Irish corpus.
7 | ---
8 |
9 | - Try it [here](TODO)
10 | - Go play the real Wordle [here](https://www.powerlanguage.co.uk/wordle/)
11 | - Read the story behind it [here](https://www.nytimes.com/2022/01/03/technology/wordle-word-game-creator.html)
12 | - Try a demo of hannahcode's Wordle clone project [here](https://wordle.hannahmariepark.com)
13 |
14 | _To Run Locally:_
15 | Clone the repository and perform the following command line actions:
16 | ```bash
17 | $ cd wordle
18 | $ npm install
19 | $ npm run start
20 | ```
21 |
22 | _To build/run docker container:_
23 | ```bash
24 | $ docker build -t focale .
25 | $ docker run -d -p 3000:3000 focale
26 | ```
27 | open http://localhost:3000 in browser.
28 |
29 |
--------------------------------------------------------------------------------
/src/lib/localStorage.ts:
--------------------------------------------------------------------------------
1 | const gameStateKey = 'gameState'
2 |
3 | type StoredGameState = {
4 | guesses: string[]
5 | solution: string
6 | }
7 |
8 | export const saveGameStateToLocalStorage = (gameState: StoredGameState) => {
9 | localStorage.setItem(gameStateKey, JSON.stringify(gameState))
10 | }
11 |
12 | export const loadGameStateFromLocalStorage = () => {
13 | const state = localStorage.getItem(gameStateKey)
14 | return state ? (JSON.parse(state) as StoredGameState) : null
15 | }
16 |
17 | const gameStatKey = 'gameStats'
18 |
19 | export type GameStats = {
20 | winDistribution: number[]
21 | gamesFailed: number
22 | currentStreak: number
23 | bestStreak: number
24 | totalGames: number
25 | successRate: number
26 | }
27 |
28 | export const saveStatsToLocalStorage = (gameStats: GameStats) => {
29 | localStorage.setItem(gameStatKey, JSON.stringify(gameStats))
30 | }
31 |
32 | export const loadStatsFromLocalStorage = () => {
33 | const stats = localStorage.getItem(gameStatKey)
34 | return stats ? (JSON.parse(stats) as GameStats) : null
35 | }
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Hannah Park
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/components/alerts/Alert.tsx:
--------------------------------------------------------------------------------
1 | import { Fragment } from 'react'
2 | import { Transition } from '@headlessui/react'
3 | import classNames from 'classnames'
4 |
5 | type Props = {
6 | isOpen: boolean
7 | message: string
8 | variant?: 'success' | 'warning'
9 | }
10 |
11 | export const Alert = ({ isOpen, message, variant = 'warning' }: Props) => {
12 | const classes = classNames(
13 | 'fixed top-20 left-1/2 transform -translate-x-1/2 max-w-sm w-full shadow-lg rounded-lg pointer-events-auto ring-1 ring-black ring-opacity-5 overflow-hidden',
14 | {
15 | 'bg-rose-200': variant === 'warning',
16 | 'bg-green-200': variant === 'success',
17 | }
18 | )
19 |
20 | return (
21 |
31 |
32 |
33 |
34 | {message}
35 |
36 |
37 |
38 |
39 | )
40 | }
41 |
--------------------------------------------------------------------------------
/src/components/keyboard/Key.tsx:
--------------------------------------------------------------------------------
1 | import { ReactNode } from 'react'
2 | import classnames from 'classnames'
3 | import { KeyValue } from '../../lib/keyboard'
4 | import { CharStatus } from '../../lib/statuses'
5 |
6 | type Props = {
7 | children?: ReactNode
8 | value: KeyValue
9 | width?: number
10 | status?: CharStatus
11 | onClick: (value: KeyValue) => void
12 | }
13 |
14 | export const Key = ({
15 | children,
16 | status,
17 | width = 40,
18 | value,
19 | onClick,
20 | }: Props) => {
21 | const classes = classnames(
22 | 'flex items-center justify-center rounded mx-0.5 text-xs font-bold cursor-pointer select-none',
23 | {
24 | 'bg-slate-200 hover:bg-slate-300 active:bg-slate-400': !status,
25 | 'bg-slate-400 text-white': status === 'absent',
26 | 'bg-green-500 hover:bg-green-600 active:bg-green-700 text-white':
27 | status === 'correct',
28 | 'bg-yellow-500 hover:bg-yellow-600 active:bg-yellow-700 text-white':
29 | status === 'present',
30 | }
31 | )
32 |
33 | const handleClick: React.MouseEventHandler = (event) => {
34 | onClick(value)
35 | event.currentTarget.blur()
36 | }
37 |
38 | return (
39 |
44 | {children || value}
45 |
46 | )
47 | }
48 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "wordle",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@headlessui/react": "^1.4.2",
7 | "@heroicons/react": "^1.0.5",
8 | "@testing-library/jest-dom": "^5.16.1",
9 | "@testing-library/react": "^12.1.2",
10 | "@testing-library/user-event": "^13.5.0",
11 | "@types/jest": "^27.4.0",
12 | "@types/node": "^16.11.19",
13 | "@types/react": "^17.0.38",
14 | "@types/react-dom": "^17.0.11",
15 | "classnames": "^2.3.1",
16 | "react": "^17.0.2",
17 | "react-dom": "^17.0.2",
18 | "react-scripts": "5.0.0",
19 | "typescript": "^4.5.4",
20 | "web-vitals": "^2.1.3"
21 | },
22 | "scripts": {
23 | "start": "react-scripts start",
24 | "build": "react-scripts build",
25 | "test": "react-scripts test",
26 | "eject": "react-scripts eject"
27 | },
28 | "eslintConfig": {
29 | "extends": [
30 | "react-app",
31 | "react-app/jest"
32 | ]
33 | },
34 | "browserslist": {
35 | "production": [
36 | ">0.2%",
37 | "not dead",
38 | "not op_mini all"
39 | ],
40 | "development": [
41 | "last 1 chrome version",
42 | "last 1 firefox version",
43 | "last 1 safari version"
44 | ]
45 | },
46 | "devDependencies": {
47 | "autoprefixer": "^10.4.2",
48 | "postcss": "^8.4.5",
49 | "tailwindcss": "^3.0.12",
50 | "prettier": "^2.5.1"
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/lib/stats.ts:
--------------------------------------------------------------------------------
1 | import {
2 | GameStats,
3 | loadStatsFromLocalStorage,
4 | saveStatsToLocalStorage,
5 | } from './localStorage'
6 |
7 | // In stats array elements 0-5 are successes in 1-6 trys
8 |
9 | export const addStatsForCompletedGame = (
10 | gameStats: GameStats,
11 | count: number
12 | ) => {
13 | // Count is number of incorrect guesses before end.
14 | const stats = { ...gameStats }
15 |
16 | stats.totalGames += 1
17 |
18 | if (count > 5) {
19 | // A fail situation
20 | stats.currentStreak = 0
21 | stats.gamesFailed += 1
22 | } else {
23 | stats.winDistribution[count] += 1
24 | stats.currentStreak += 1
25 |
26 | if (stats.bestStreak < stats.currentStreak) {
27 | stats.bestStreak = stats.currentStreak
28 | }
29 | }
30 |
31 | stats.successRate = getSuccessRate(stats)
32 |
33 | saveStatsToLocalStorage(stats)
34 | return stats
35 | }
36 |
37 | const defaultStats: GameStats = {
38 | winDistribution: [0, 0, 0, 0, 0, 0],
39 | gamesFailed: 0,
40 | currentStreak: 0,
41 | bestStreak: 0,
42 | totalGames: 0,
43 | successRate: 0,
44 | }
45 |
46 | export const loadStats = () => {
47 | return loadStatsFromLocalStorage() || defaultStats
48 | }
49 |
50 | const getSuccessRate = (gameStats: GameStats) => {
51 | const { totalGames, gamesFailed } = gameStats
52 |
53 | return Math.round(
54 | (100 * (totalGames - gamesFailed)) / Math.max(totalGames, 1)
55 | )
56 | }
57 |
--------------------------------------------------------------------------------
/src/components/modals/InfoModal.tsx:
--------------------------------------------------------------------------------
1 | import { Cell } from '../grid/Cell'
2 | import { BaseModal } from './BaseModal'
3 |
4 | type Props = {
5 | isOpen: boolean
6 | handleClose: () => void
7 | }
8 |
9 | export const InfoModal = ({ isOpen, handleClose }: Props) => {
10 | return (
11 |
12 |
13 | Guess the WORDLE in 6 tries. After each guess, the color of the tiles
14 | will change to show how close your guess was to the word.
15 |
16 |
17 |
18 | |
19 | |
20 | |
21 | |
22 | |
23 |
24 |
25 | The letter W is in the word and in the correct spot.
26 |
27 |
28 |
29 | |
30 | |
31 | |
32 | |
33 | |
34 |
35 |
36 | The letter L is in the word but in the wrong spot.
37 |
38 |
39 |
40 | |
41 | |
42 | |
43 | |
44 | |
45 |
46 |
47 | The letter U is not in the word in any spot.
48 |
49 |
50 | )
51 | }
52 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | Wordle Clone
28 |
29 |
30 | You need to enable JavaScript to run this app.
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/components/modals/WinModal.tsx:
--------------------------------------------------------------------------------
1 | import { Dialog } from '@headlessui/react'
2 | import { CheckIcon } from '@heroicons/react/outline'
3 | import { MiniGrid } from '../mini-grid/MiniGrid'
4 | import { shareStatus } from '../../lib/share'
5 | import { BaseModal } from './BaseModal'
6 |
7 | type Props = {
8 | isOpen: boolean
9 | handleClose: () => void
10 | guesses: string[]
11 | handleShare: () => void
12 | }
13 |
14 | export const WinModal = ({
15 | isOpen,
16 | handleClose,
17 | guesses,
18 | handleShare,
19 | }: Props) => {
20 | return (
21 |
22 |
23 |
24 |
25 |
26 |
27 |
31 | You won!
32 |
33 |
34 |
35 |
Great job.
36 |
37 |
38 |
39 |
40 | {
44 | shareStatus(guesses)
45 | handleShare()
46 | }}
47 | >
48 | Share
49 |
50 |
51 |
52 | )
53 | }
54 |
--------------------------------------------------------------------------------
/src/lib/statuses.ts:
--------------------------------------------------------------------------------
1 | import { solution } from './words'
2 |
3 | export type CharStatus = 'absent' | 'present' | 'correct'
4 |
5 | export type CharValue =
6 | | 'Q'
7 | | 'W'
8 | | 'E'
9 | | 'R'
10 | | 'T'
11 | | 'Y'
12 | | 'U'
13 | | 'I'
14 | | 'O'
15 | | 'P'
16 | | 'A'
17 | | 'S'
18 | | 'D'
19 | | 'F'
20 | | 'G'
21 | | 'H'
22 | | 'J'
23 | | 'K'
24 | | 'L'
25 | | 'Z'
26 | | 'X'
27 | | 'C'
28 | | 'V'
29 | | 'B'
30 | | 'N'
31 | | 'M'
32 |
33 | export const getStatuses = (
34 | guesses: string[]
35 | ): { [key: string]: CharStatus } => {
36 | const charObj: { [key: string]: CharStatus } = {}
37 |
38 | guesses.forEach((word) => {
39 | word.split('').forEach((letter, i) => {
40 | if (!solution.includes(letter)) {
41 | // make status absent
42 | return (charObj[letter] = 'absent')
43 | }
44 |
45 | if (letter === solution[i]) {
46 | //make status correct
47 | return (charObj[letter] = 'correct')
48 | }
49 |
50 | if (charObj[letter] !== 'correct') {
51 | //make status present
52 | return (charObj[letter] = 'present')
53 | }
54 | })
55 | })
56 |
57 | return charObj
58 | }
59 |
60 | export const getGuessStatuses = (guess: string): CharStatus[] => {
61 | const splitSolution = solution.split('')
62 | const splitGuess = guess.split('')
63 |
64 | const solutionCharsTaken = splitSolution.map((_) => false)
65 |
66 | const statuses: CharStatus[] = Array.from(Array(guess.length))
67 |
68 | // handle all correct cases first
69 | splitGuess.forEach((letter, i) => {
70 | if (letter === splitSolution[i]) {
71 | statuses[i] = 'correct'
72 | solutionCharsTaken[i] = true
73 | return
74 | }
75 | })
76 |
77 | splitGuess.forEach((letter, i) => {
78 | if (statuses[i]) return
79 |
80 | if (!splitSolution.includes(letter)) {
81 | // handles the absent case
82 | statuses[i] = 'absent'
83 | return
84 | }
85 |
86 | // now we are left with "present"s
87 | const indexOfPresentChar = splitSolution.findIndex(
88 | (x, index) => x === letter && !solutionCharsTaken[index]
89 | )
90 |
91 | if (indexOfPresentChar > -1) {
92 | statuses[i] = 'present'
93 | solutionCharsTaken[indexOfPresentChar] = true
94 | return
95 | } else {
96 | statuses[i] = 'absent'
97 | return
98 | }
99 | })
100 |
101 | return statuses
102 | }
103 |
--------------------------------------------------------------------------------
/src/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/modals/BaseModal.tsx:
--------------------------------------------------------------------------------
1 | import { Fragment } from 'react'
2 | import { Dialog, Transition } from '@headlessui/react'
3 | import { XCircleIcon } from '@heroicons/react/outline'
4 |
5 | type Props = {
6 | title: string
7 | children: React.ReactNode
8 | isOpen: boolean
9 | handleClose: () => void
10 | }
11 |
12 | export const BaseModal = ({ title, children, isOpen, handleClose }: Props) => {
13 | return (
14 |
15 |
20 |
21 |
30 |
31 |
32 |
33 | {/* This element is to trick the browser into centering the modal contents. */}
34 |
38 |
39 |
40 |
49 |
50 |
51 | handleClose()}
54 | />
55 |
56 |
57 |
58 |
62 | {title}
63 |
64 |
65 | {children}
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | )
75 | }
76 |
--------------------------------------------------------------------------------
/src/components/keyboard/Keyboard.tsx:
--------------------------------------------------------------------------------
1 | import { KeyValue } from '../../lib/keyboard'
2 | import { getStatuses } from '../../lib/statuses'
3 | import { Key } from './Key'
4 | import { useEffect } from 'react'
5 |
6 | type Props = {
7 | onChar: (value: string) => void
8 | onDelete: () => void
9 | onEnter: () => void
10 | guesses: string[]
11 | }
12 |
13 | export const Keyboard = ({ onChar, onDelete, onEnter, guesses }: Props) => {
14 | const charStatuses = getStatuses(guesses)
15 |
16 | const onClick = (value: KeyValue) => {
17 | if (value === 'ENTER') {
18 | onEnter()
19 | } else if (value === 'DELETE') {
20 | onDelete()
21 | } else {
22 | onChar(value)
23 | }
24 | }
25 |
26 | useEffect(() => {
27 | const listener = (e: KeyboardEvent) => {
28 | if (e.code === 'Enter') {
29 | onEnter()
30 | } else if (e.code === 'Backspace') {
31 | onDelete()
32 | } else {
33 | const key = e.key.toUpperCase()
34 | if (key.length === 1 && key >= 'A' && key <= 'Z') {
35 | onChar(key)
36 | }
37 | }
38 | }
39 | window.addEventListener('keyup', listener)
40 | return () => {
41 | window.removeEventListener('keyup', listener)
42 | }
43 | }, [onEnter, onDelete, onChar])
44 |
45 | return (
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | Enter
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | Delete
83 |
84 |
85 |
86 | )
87 | }
88 |
--------------------------------------------------------------------------------
/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { InformationCircleIcon } from '@heroicons/react/outline'
2 | import { ChartBarIcon } from '@heroicons/react/outline'
3 | import { useState, useEffect } from 'react'
4 | import { Alert } from './components/alerts/Alert'
5 | import { Grid } from './components/grid/Grid'
6 | import { Keyboard } from './components/keyboard/Keyboard'
7 | import { AboutModal } from './components/modals/AboutModal'
8 | import { InfoModal } from './components/modals/InfoModal'
9 | import { WinModal } from './components/modals/WinModal'
10 | import { StatsModal } from './components/modals/StatsModal'
11 | import { isWordInWordList, isWinningWord, solution } from './lib/words'
12 | import { addStatsForCompletedGame, loadStats } from './lib/stats'
13 | import {
14 | loadGameStateFromLocalStorage,
15 | saveGameStateToLocalStorage,
16 | } from './lib/localStorage'
17 |
18 | function App() {
19 | const [currentGuess, setCurrentGuess] = useState('')
20 | const [isGameWon, setIsGameWon] = useState(false)
21 | const [isWinModalOpen, setIsWinModalOpen] = useState(false)
22 | const [isInfoModalOpen, setIsInfoModalOpen] = useState(false)
23 | const [isAboutModalOpen, setIsAboutModalOpen] = useState(false)
24 | const [isNotEnoughLetters, setIsNotEnoughLetters] = useState(false)
25 | const [isStatsModalOpen, setIsStatsModalOpen] = useState(false)
26 | const [isWordNotFoundAlertOpen, setIsWordNotFoundAlertOpen] = useState(false)
27 | const [isGameLost, setIsGameLost] = useState(false)
28 | const [shareComplete, setShareComplete] = useState(false)
29 | const [guesses, setGuesses] = useState(() => {
30 | const loaded = loadGameStateFromLocalStorage()
31 | if (loaded?.solution !== solution) {
32 | return []
33 | }
34 | const gameWasWon = loaded.guesses.includes(solution)
35 | if (gameWasWon) {
36 | setIsGameWon(true)
37 | }
38 | if (loaded.guesses.length === 6 && !gameWasWon) {
39 | setIsGameLost(true)
40 | }
41 | return loaded.guesses
42 | })
43 |
44 | const [stats, setStats] = useState(() => loadStats())
45 |
46 | useEffect(() => {
47 | saveGameStateToLocalStorage({ guesses, solution })
48 | }, [guesses])
49 |
50 | useEffect(() => {
51 | if (isGameWon) {
52 | setIsWinModalOpen(true)
53 | }
54 | }, [isGameWon])
55 |
56 | const onChar = (value: string) => {
57 | if (currentGuess.length < 5 && guesses.length < 6 && !isGameWon) {
58 | setCurrentGuess(`${currentGuess}${value}`)
59 | }
60 | }
61 |
62 | const onDelete = () => {
63 | setCurrentGuess(currentGuess.slice(0, -1))
64 | }
65 |
66 | const onEnter = () => {
67 | if (!(currentGuess.length === 5) && !isGameLost) {
68 | setIsNotEnoughLetters(true)
69 | return setTimeout(() => {
70 | setIsNotEnoughLetters(false)
71 | }, 2000)
72 | }
73 |
74 | if (!isWordInWordList(currentGuess)) {
75 | setIsWordNotFoundAlertOpen(true)
76 | return setTimeout(() => {
77 | setIsWordNotFoundAlertOpen(false)
78 | }, 2000)
79 | }
80 |
81 | const winningWord = isWinningWord(currentGuess)
82 |
83 | if (currentGuess.length === 5 && guesses.length < 6 && !isGameWon) {
84 | setGuesses([...guesses, currentGuess])
85 | setCurrentGuess('')
86 |
87 | if (winningWord) {
88 | setStats(addStatsForCompletedGame(stats, guesses.length))
89 | return setIsGameWon(true)
90 | }
91 |
92 | if (guesses.length === 5) {
93 | setStats(addStatsForCompletedGame(stats, guesses.length + 1))
94 | setIsGameLost(true)
95 | }
96 | }
97 | }
98 |
99 | return (
100 |
101 |
102 |
Not Wordle
103 | setIsInfoModalOpen(true)}
106 | />
107 | setIsStatsModalOpen(true)}
110 | />
111 |
112 |
113 |
119 |
setIsWinModalOpen(false)}
122 | guesses={guesses}
123 | handleShare={() => {
124 | setIsWinModalOpen(false)
125 | setShareComplete(true)
126 | return setTimeout(() => {
127 | setShareComplete(false)
128 | }, 2000)
129 | }}
130 | />
131 | setIsInfoModalOpen(false)}
134 | />
135 | setIsStatsModalOpen(false)}
138 | gameStats={stats}
139 | />
140 | setIsAboutModalOpen(false)}
143 | />
144 |
145 | setIsAboutModalOpen(true)}
149 | >
150 | About this game
151 |
152 |
153 |
154 |
155 |
159 |
164 |
165 | )
166 | }
167 |
168 | export default App
169 |
--------------------------------------------------------------------------------
/src/constants/wordlist.ts:
--------------------------------------------------------------------------------
1 | export const WORDS = [
2 | 'cigar',
3 | 'rebut',
4 | 'sissy',
5 | 'humph',
6 | 'awake',
7 | 'blush',
8 | 'focal',
9 | 'evade',
10 | 'naval',
11 | 'serve',
12 | 'heath',
13 | 'dwarf',
14 | 'model',
15 | 'karma',
16 | 'stink',
17 | 'grade',
18 | 'quiet',
19 | 'bench',
20 | 'abate',
21 | 'feign',
22 | 'major',
23 | 'death',
24 | 'fresh',
25 | 'crust',
26 | 'stool',
27 | 'colon',
28 | 'abase',
29 | 'marry',
30 | 'react',
31 | 'batty',
32 | 'pride',
33 | 'floss',
34 | 'helix',
35 | 'croak',
36 | 'staff',
37 | 'paper',
38 | 'unfed',
39 | 'whelp',
40 | 'trawl',
41 | 'outdo',
42 | 'adobe',
43 | 'crazy',
44 | 'sower',
45 | 'repay',
46 | 'digit',
47 | 'crate',
48 | 'cluck',
49 | 'spike',
50 | 'mimic',
51 | 'pound',
52 | 'maxim',
53 | 'linen',
54 | 'unmet',
55 | 'flesh',
56 | 'booby',
57 | 'forth',
58 | 'first',
59 | 'stand',
60 | 'belly',
61 | 'ivory',
62 | 'seedy',
63 | 'print',
64 | 'yearn',
65 | 'drain',
66 | 'bribe',
67 | 'stout',
68 | 'panel',
69 | 'crass',
70 | 'flume',
71 | 'offal',
72 | 'agree',
73 | 'error',
74 | 'swirl',
75 | 'argue',
76 | 'bleed',
77 | 'delta',
78 | 'flick',
79 | 'totem',
80 | 'wooer',
81 | 'front',
82 | 'shrub',
83 | 'parry',
84 | 'biome',
85 | 'lapel',
86 | 'start',
87 | 'greet',
88 | 'goner',
89 | 'golem',
90 | 'lusty',
91 | 'loopy',
92 | 'round',
93 | 'audit',
94 | 'lying',
95 | 'gamma',
96 | 'labor',
97 | 'islet',
98 | 'civic',
99 | 'forge',
100 | 'corny',
101 | 'moult',
102 | 'basic',
103 | 'salad',
104 | 'agate',
105 | 'spicy',
106 | 'spray',
107 | 'essay',
108 | 'fjord',
109 | 'spend',
110 | 'kebab',
111 | 'guild',
112 | 'aback',
113 | 'motor',
114 | 'alone',
115 | 'hatch',
116 | 'hyper',
117 | 'thumb',
118 | 'dowry',
119 | 'ought',
120 | 'belch',
121 | 'dutch',
122 | 'pilot',
123 | 'tweed',
124 | 'comet',
125 | 'jaunt',
126 | 'enema',
127 | 'steed',
128 | 'abyss',
129 | 'growl',
130 | 'fling',
131 | 'dozen',
132 | 'boozy',
133 | 'erode',
134 | 'world',
135 | 'gouge',
136 | 'click',
137 | 'briar',
138 | 'great',
139 | 'altar',
140 | 'pulpy',
141 | 'blurt',
142 | 'coast',
143 | 'duchy',
144 | 'groin',
145 | 'fixer',
146 | 'group',
147 | 'rogue',
148 | 'badly',
149 | 'smart',
150 | 'pithy',
151 | 'gaudy',
152 | 'chill',
153 | 'heron',
154 | 'vodka',
155 | 'finer',
156 | 'surer',
157 | 'radio',
158 | 'rouge',
159 | 'perch',
160 | 'retch',
161 | 'wrote',
162 | 'clock',
163 | 'tilde',
164 | 'store',
165 | 'prove',
166 | 'bring',
167 | 'solve',
168 | 'cheat',
169 | 'grime',
170 | 'exult',
171 | 'usher',
172 | 'epoch',
173 | 'triad',
174 | 'break',
175 | 'rhino',
176 | 'viral',
177 | 'conic',
178 | 'masse',
179 | 'sonic',
180 | 'vital',
181 | 'trace',
182 | 'using',
183 | 'peach',
184 | 'champ',
185 | 'baton',
186 | 'brake',
187 | 'pluck',
188 | 'craze',
189 | 'gripe',
190 | 'weary',
191 | 'picky',
192 | 'acute',
193 | 'ferry',
194 | 'aside',
195 | 'tapir',
196 | 'troll',
197 | 'unify',
198 | 'rebus',
199 | 'boost',
200 | 'truss',
201 | 'siege',
202 | 'tiger',
203 | 'banal',
204 | 'slump',
205 | 'crank',
206 | 'gorge',
207 | 'query',
208 | 'drink',
209 | 'favor',
210 | 'abbey',
211 | 'tangy',
212 | 'panic',
213 | 'solar',
214 | 'shire',
215 | 'proxy',
216 | 'point',
217 | 'robot',
218 | 'prick',
219 | 'wince',
220 | 'crimp',
221 | 'knoll',
222 | 'sugar',
223 | 'whack',
224 | 'mount',
225 | 'perky',
226 | 'could',
227 | 'wrung',
228 | 'light',
229 | 'those',
230 | 'moist',
231 | 'shard',
232 | 'pleat',
233 | 'aloft',
234 | 'skill',
235 | 'elder',
236 | 'frame',
237 | 'humor',
238 | 'pause',
239 | 'ulcer',
240 | 'ultra',
241 | 'robin',
242 | 'cynic',
243 | 'agora',
244 | 'aroma',
245 | 'caulk',
246 | 'shake',
247 | 'pupal',
248 | 'dodge',
249 | 'swill',
250 | 'tacit',
251 | 'other',
252 | 'thorn',
253 | 'trove',
254 | 'bloke',
255 | 'vivid',
256 | 'spill',
257 | 'chant',
258 | 'choke',
259 | 'rupee',
260 | 'nasty',
261 | 'mourn',
262 | 'ahead',
263 | 'brine',
264 | 'cloth',
265 | 'hoard',
266 | 'sweet',
267 | 'month',
268 | 'lapse',
269 | 'watch',
270 | 'today',
271 | 'focus',
272 | 'smelt',
273 | 'tease',
274 | 'cater',
275 | 'movie',
276 | 'lynch',
277 | 'saute',
278 | 'allow',
279 | 'renew',
280 | 'their',
281 | 'slosh',
282 | 'purge',
283 | 'chest',
284 | 'depot',
285 | 'epoxy',
286 | 'nymph',
287 | 'found',
288 | 'shall',
289 | 'harry',
290 | 'stove',
291 | 'lowly',
292 | 'snout',
293 | 'trope',
294 | 'fewer',
295 | 'shawl',
296 | 'natal',
297 | 'fibre',
298 | 'comma',
299 | 'foray',
300 | 'scare',
301 | 'stair',
302 | 'black',
303 | 'squad',
304 | 'royal',
305 | 'chunk',
306 | 'mince',
307 | 'slave',
308 | 'shame',
309 | 'cheek',
310 | 'ample',
311 | 'flair',
312 | 'foyer',
313 | 'cargo',
314 | 'oxide',
315 | 'plant',
316 | 'olive',
317 | 'inert',
318 | 'askew',
319 | 'heist',
320 | 'shown',
321 | 'zesty',
322 | 'hasty',
323 | 'trash',
324 | 'fella',
325 | 'larva',
326 | 'forgo',
327 | 'story',
328 | 'hairy',
329 | 'train',
330 | 'homer',
331 | 'badge',
332 | 'midst',
333 | 'canny',
334 | 'fetus',
335 | 'butch',
336 | 'farce',
337 | 'slung',
338 | 'tipsy',
339 | 'metal',
340 | 'yield',
341 | 'delve',
342 | 'being',
343 | 'scour',
344 | 'glass',
345 | 'gamer',
346 | 'scrap',
347 | 'money',
348 | 'hinge',
349 | 'album',
350 | 'vouch',
351 | 'asset',
352 | 'tiara',
353 | 'crept',
354 | 'bayou',
355 | 'atoll',
356 | 'manor',
357 | 'creak',
358 | 'showy',
359 | 'phase',
360 | 'froth',
361 | 'depth',
362 | 'gloom',
363 | 'flood',
364 | 'trait',
365 | 'girth',
366 | 'piety',
367 | 'payer',
368 | 'goose',
369 | 'float',
370 | 'donor',
371 | 'atone',
372 | 'primo',
373 | 'apron',
374 | 'blown',
375 | 'cacao',
376 | 'loser',
377 | 'input',
378 | 'gloat',
379 | 'awful',
380 | 'brink',
381 | 'smite',
382 | 'beady',
383 | 'rusty',
384 | 'retro',
385 | 'droll',
386 | 'gawky',
387 | 'hutch',
388 | 'pinto',
389 | 'gaily',
390 | 'egret',
391 | 'lilac',
392 | 'sever',
393 | 'field',
394 | 'fluff',
395 | 'hydro',
396 | 'flack',
397 | 'agape',
398 | 'wench',
399 | 'voice',
400 | 'stead',
401 | 'stalk',
402 | 'berth',
403 | 'madam',
404 | 'night',
405 | 'bland',
406 | 'liver',
407 | 'wedge',
408 | 'augur',
409 | 'roomy',
410 | 'wacky',
411 | 'flock',
412 | 'angry',
413 | 'bobby',
414 | 'trite',
415 | 'aphid',
416 | 'tryst',
417 | 'midge',
418 | 'power',
419 | 'elope',
420 | 'cinch',
421 | 'motto',
422 | 'stomp',
423 | 'upset',
424 | 'bluff',
425 | 'cramp',
426 | 'quart',
427 | 'coyly',
428 | 'youth',
429 | 'rhyme',
430 | 'buggy',
431 | 'alien',
432 | 'smear',
433 | 'unfit',
434 | 'patty',
435 | 'cling',
436 | 'glean',
437 | 'label',
438 | 'hunky',
439 | 'khaki',
440 | 'poker',
441 | 'gruel',
442 | 'twice',
443 | 'twang',
444 | 'shrug',
445 | 'treat',
446 | 'unlit',
447 | 'waste',
448 | 'merit',
449 | 'woven',
450 | 'octal',
451 | 'needy',
452 | 'clown',
453 | 'widow',
454 | 'irony',
455 | 'ruder',
456 | 'gauze',
457 | 'chief',
458 | 'onset',
459 | 'prize',
460 | 'fungi',
461 | 'charm',
462 | 'gully',
463 | 'inter',
464 | 'whoop',
465 | 'taunt',
466 | 'leery',
467 | 'class',
468 | 'theme',
469 | 'lofty',
470 | 'tibia',
471 | 'booze',
472 | 'alpha',
473 | 'thyme',
474 | 'eclat',
475 | 'doubt',
476 | 'parer',
477 | 'chute',
478 | 'stick',
479 | 'trice',
480 | 'alike',
481 | 'sooth',
482 | 'recap',
483 | 'saint',
484 | 'liege',
485 | 'glory',
486 | 'grate',
487 | 'admit',
488 | 'brisk',
489 | 'soggy',
490 | 'usurp',
491 | 'scald',
492 | 'scorn',
493 | 'leave',
494 | 'twine',
495 | 'sting',
496 | 'bough',
497 | 'marsh',
498 | 'sloth',
499 | 'dandy',
500 | 'vigor',
501 | 'howdy',
502 | 'enjoy',
503 | 'valid',
504 | 'ionic',
505 | 'equal',
506 | 'unset',
507 | 'floor',
508 | 'catch',
509 | 'spade',
510 | 'stein',
511 | 'exist',
512 | 'quirk',
513 | 'denim',
514 | 'grove',
515 | 'spiel',
516 | 'mummy',
517 | 'fault',
518 | 'foggy',
519 | 'flout',
520 | 'carry',
521 | 'sneak',
522 | 'libel',
523 | 'waltz',
524 | 'aptly',
525 | 'piney',
526 | 'inept',
527 | 'aloud',
528 | 'photo',
529 | 'dream',
530 | 'stale',
531 | 'vomit',
532 | 'ombre',
533 | 'fanny',
534 | 'unite',
535 | 'snarl',
536 | 'baker',
537 | 'there',
538 | 'glyph',
539 | 'pooch',
540 | 'hippy',
541 | 'spell',
542 | 'folly',
543 | 'louse',
544 | 'gulch',
545 | 'vault',
546 | 'godly',
547 | 'threw',
548 | 'fleet',
549 | 'grave',
550 | 'inane',
551 | 'shock',
552 | 'crave',
553 | 'spite',
554 | 'valve',
555 | 'skimp',
556 | 'claim',
557 | 'rainy',
558 | 'musty',
559 | 'pique',
560 | 'daddy',
561 | 'quasi',
562 | 'arise',
563 | 'aging',
564 | 'valet',
565 | 'opium',
566 | 'avert',
567 | 'stuck',
568 | 'recut',
569 | 'mulch',
570 | 'genre',
571 | 'plume',
572 | 'rifle',
573 | 'count',
574 | 'incur',
575 | 'total',
576 | 'wrest',
577 | 'mocha',
578 | 'deter',
579 | 'study',
580 | 'lover',
581 | 'safer',
582 | 'rivet',
583 | 'funny',
584 | 'smoke',
585 | 'mound',
586 | 'undue',
587 | 'sedan',
588 | 'pagan',
589 | 'swine',
590 | 'guile',
591 | 'gusty',
592 | 'equip',
593 | 'tough',
594 | 'canoe',
595 | 'chaos',
596 | 'covet',
597 | 'human',
598 | 'udder',
599 | 'lunch',
600 | 'blast',
601 | 'stray',
602 | 'manga',
603 | 'melee',
604 | 'lefty',
605 | 'quick',
606 | 'paste',
607 | 'given',
608 | 'octet',
609 | 'risen',
610 | 'groan',
611 | 'leaky',
612 | 'grind',
613 | 'carve',
614 | 'loose',
615 | 'sadly',
616 | 'spilt',
617 | 'apple',
618 | 'slack',
619 | 'honey',
620 | 'final',
621 | 'sheen',
622 | 'eerie',
623 | 'minty',
624 | 'slick',
625 | 'derby',
626 | 'wharf',
627 | 'spelt',
628 | 'coach',
629 | 'erupt',
630 | 'singe',
631 | 'price',
632 | 'spawn',
633 | 'fairy',
634 | 'jiffy',
635 | 'filmy',
636 | 'stack',
637 | 'chose',
638 | 'sleep',
639 | 'ardor',
640 | 'nanny',
641 | 'niece',
642 | 'woozy',
643 | 'handy',
644 | 'grace',
645 | 'ditto',
646 | 'stank',
647 | 'cream',
648 | 'usual',
649 | 'diode',
650 | 'valor',
651 | 'angle',
652 | 'ninja',
653 | 'muddy',
654 | 'chase',
655 | 'reply',
656 | 'prone',
657 | 'spoil',
658 | 'heart',
659 | 'shade',
660 | 'diner',
661 | 'arson',
662 | 'onion',
663 | 'sleet',
664 | 'dowel',
665 | 'couch',
666 | 'palsy',
667 | 'bowel',
668 | 'smile',
669 | 'evoke',
670 | 'creek',
671 | 'lance',
672 | 'eagle',
673 | 'idiot',
674 | 'siren',
675 | 'built',
676 | 'embed',
677 | 'award',
678 | 'dross',
679 | 'annul',
680 | 'goody',
681 | 'frown',
682 | 'patio',
683 | 'laden',
684 | 'humid',
685 | 'elite',
686 | 'lymph',
687 | 'edify',
688 | 'might',
689 | 'reset',
690 | 'visit',
691 | 'gusto',
692 | 'purse',
693 | 'vapor',
694 | 'crock',
695 | 'write',
696 | 'sunny',
697 | 'loath',
698 | 'chaff',
699 | 'slide',
700 | 'queer',
701 | 'venom',
702 | 'stamp',
703 | 'sorry',
704 | 'still',
705 | 'acorn',
706 | 'aping',
707 | 'pushy',
708 | 'tamer',
709 | 'hater',
710 | 'mania',
711 | 'awoke',
712 | 'brawn',
713 | 'swift',
714 | 'exile',
715 | 'birch',
716 | 'lucky',
717 | 'freer',
718 | 'risky',
719 | 'ghost',
720 | 'plier',
721 | 'lunar',
722 | 'winch',
723 | 'snare',
724 | 'nurse',
725 | 'house',
726 | 'borax',
727 | 'nicer',
728 | 'lurch',
729 | 'exalt',
730 | 'about',
731 | 'savvy',
732 | 'toxin',
733 | 'tunic',
734 | 'pried',
735 | 'inlay',
736 | 'chump',
737 | 'lanky',
738 | 'cress',
739 | 'eater',
740 | 'elude',
741 | 'cycle',
742 | 'kitty',
743 | 'boule',
744 | 'moron',
745 | 'tenet',
746 | 'place',
747 | 'lobby',
748 | 'plush',
749 | 'vigil',
750 | 'index',
751 | 'blink',
752 | 'clung',
753 | 'qualm',
754 | 'croup',
755 | 'clink',
756 | 'juicy',
757 | 'stage',
758 | 'decay',
759 | 'nerve',
760 | 'flier',
761 | 'shaft',
762 | 'crook',
763 | 'clean',
764 | 'china',
765 | 'ridge',
766 | 'vowel',
767 | 'gnome',
768 | 'snuck',
769 | 'icing',
770 | 'spiny',
771 | 'rigor',
772 | 'snail',
773 | 'flown',
774 | 'rabid',
775 | 'prose',
776 | 'thank',
777 | 'poppy',
778 | 'budge',
779 | 'fiber',
780 | 'moldy',
781 | 'dowdy',
782 | 'kneel',
783 | 'track',
784 | 'caddy',
785 | 'quell',
786 | 'dumpy',
787 | 'paler',
788 | 'swore',
789 | 'rebar',
790 | 'scuba',
791 | 'splat',
792 | 'flyer',
793 | 'horny',
794 | 'mason',
795 | 'doing',
796 | 'ozone',
797 | 'amply',
798 | 'molar',
799 | 'ovary',
800 | 'beset',
801 | 'queue',
802 | 'cliff',
803 | 'magic',
804 | 'truce',
805 | 'sport',
806 | 'fritz',
807 | 'edict',
808 | 'twirl',
809 | 'verse',
810 | 'llama',
811 | 'eaten',
812 | 'range',
813 | 'whisk',
814 | 'hovel',
815 | 'rehab',
816 | 'macaw',
817 | 'sigma',
818 | 'spout',
819 | 'verve',
820 | 'sushi',
821 | 'dying',
822 | 'fetid',
823 | 'brain',
824 | 'buddy',
825 | 'thump',
826 | 'scion',
827 | 'candy',
828 | 'chord',
829 | 'basin',
830 | 'march',
831 | 'crowd',
832 | 'arbor',
833 | 'gayly',
834 | 'musky',
835 | 'stain',
836 | 'dally',
837 | 'bless',
838 | 'bravo',
839 | 'stung',
840 | 'title',
841 | 'ruler',
842 | 'kiosk',
843 | 'blond',
844 | 'ennui',
845 | 'layer',
846 | 'fluid',
847 | 'tatty',
848 | 'score',
849 | 'cutie',
850 | 'zebra',
851 | 'barge',
852 | 'matey',
853 | 'bluer',
854 | 'aider',
855 | 'shook',
856 | 'river',
857 | 'privy',
858 | 'betel',
859 | 'frisk',
860 | 'bongo',
861 | 'begun',
862 | 'azure',
863 | 'weave',
864 | 'genie',
865 | 'sound',
866 | 'glove',
867 | 'braid',
868 | 'scope',
869 | 'wryly',
870 | 'rover',
871 | 'assay',
872 | 'ocean',
873 | 'bloom',
874 | 'irate',
875 | 'later',
876 | 'woken',
877 | 'silky',
878 | 'wreck',
879 | 'dwelt',
880 | 'slate',
881 | 'smack',
882 | 'solid',
883 | 'amaze',
884 | 'hazel',
885 | 'wrist',
886 | 'jolly',
887 | 'globe',
888 | 'flint',
889 | 'rouse',
890 | 'civil',
891 | 'vista',
892 | 'relax',
893 | 'cover',
894 | 'alive',
895 | 'beech',
896 | 'jetty',
897 | 'bliss',
898 | 'vocal',
899 | 'often',
900 | 'dolly',
901 | 'eight',
902 | 'joker',
903 | 'since',
904 | 'event',
905 | 'ensue',
906 | 'shunt',
907 | 'diver',
908 | 'poser',
909 | 'worst',
910 | 'sweep',
911 | 'alley',
912 | 'creed',
913 | 'anime',
914 | 'leafy',
915 | 'bosom',
916 | 'dunce',
917 | 'stare',
918 | 'pudgy',
919 | 'waive',
920 | 'choir',
921 | 'stood',
922 | 'spoke',
923 | 'outgo',
924 | 'delay',
925 | 'bilge',
926 | 'ideal',
927 | 'clasp',
928 | 'seize',
929 | 'hotly',
930 | 'laugh',
931 | 'sieve',
932 | 'block',
933 | 'meant',
934 | 'grape',
935 | 'noose',
936 | 'hardy',
937 | 'shied',
938 | 'drawl',
939 | 'daisy',
940 | 'putty',
941 | 'strut',
942 | 'burnt',
943 | 'tulip',
944 | 'crick',
945 | 'idyll',
946 | 'vixen',
947 | 'furor',
948 | 'geeky',
949 | 'cough',
950 | 'naive',
951 | 'shoal',
952 | 'stork',
953 | 'bathe',
954 | 'aunty',
955 | 'check',
956 | 'prime',
957 | 'brass',
958 | 'outer',
959 | 'furry',
960 | 'razor',
961 | 'elect',
962 | 'evict',
963 | 'imply',
964 | 'demur',
965 | 'quota',
966 | 'haven',
967 | 'cavil',
968 | 'swear',
969 | 'crump',
970 | 'dough',
971 | 'gavel',
972 | 'wagon',
973 | 'salon',
974 | 'nudge',
975 | 'harem',
976 | 'pitch',
977 | 'sworn',
978 | 'pupil',
979 | 'excel',
980 | 'stony',
981 | 'cabin',
982 | 'unzip',
983 | 'queen',
984 | 'trout',
985 | 'polyp',
986 | 'earth',
987 | 'storm',
988 | 'until',
989 | 'taper',
990 | 'enter',
991 | 'child',
992 | 'adopt',
993 | 'minor',
994 | 'fatty',
995 | 'husky',
996 | 'brave',
997 | 'filet',
998 | 'slime',
999 | 'glint',
1000 | 'tread',
1001 | 'steal',
1002 | 'regal',
1003 | 'guest',
1004 | 'every',
1005 | 'murky',
1006 | 'share',
1007 | 'spore',
1008 | 'hoist',
1009 | 'buxom',
1010 | 'inner',
1011 | 'otter',
1012 | 'dimly',
1013 | 'level',
1014 | 'sumac',
1015 | 'donut',
1016 | 'stilt',
1017 | 'arena',
1018 | 'sheet',
1019 | 'scrub',
1020 | 'fancy',
1021 | 'slimy',
1022 | 'pearl',
1023 | 'silly',
1024 | 'porch',
1025 | 'dingo',
1026 | 'sepia',
1027 | 'amble',
1028 | 'shady',
1029 | 'bread',
1030 | 'friar',
1031 | 'reign',
1032 | 'dairy',
1033 | 'quill',
1034 | 'cross',
1035 | 'brood',
1036 | 'tuber',
1037 | 'shear',
1038 | 'posit',
1039 | 'blank',
1040 | 'villa',
1041 | 'shank',
1042 | 'piggy',
1043 | 'freak',
1044 | 'which',
1045 | 'among',
1046 | 'fecal',
1047 | 'shell',
1048 | 'would',
1049 | 'algae',
1050 | 'large',
1051 | 'rabbi',
1052 | 'agony',
1053 | 'amuse',
1054 | 'bushy',
1055 | 'copse',
1056 | 'swoon',
1057 | 'knife',
1058 | 'pouch',
1059 | 'ascot',
1060 | 'plane',
1061 | 'crown',
1062 | 'urban',
1063 | 'snide',
1064 | 'relay',
1065 | 'abide',
1066 | 'viola',
1067 | 'rajah',
1068 | 'straw',
1069 | 'dilly',
1070 | 'crash',
1071 | 'amass',
1072 | 'third',
1073 | 'trick',
1074 | 'tutor',
1075 | 'woody',
1076 | 'blurb',
1077 | 'grief',
1078 | 'disco',
1079 | 'where',
1080 | 'sassy',
1081 | 'beach',
1082 | 'sauna',
1083 | 'comic',
1084 | 'clued',
1085 | 'creep',
1086 | 'caste',
1087 | 'graze',
1088 | 'snuff',
1089 | 'frock',
1090 | 'gonad',
1091 | 'drunk',
1092 | 'prong',
1093 | 'lurid',
1094 | 'steel',
1095 | 'halve',
1096 | 'buyer',
1097 | 'vinyl',
1098 | 'utile',
1099 | 'smell',
1100 | 'adage',
1101 | 'worry',
1102 | 'tasty',
1103 | 'local',
1104 | 'trade',
1105 | 'finch',
1106 | 'ashen',
1107 | 'modal',
1108 | 'gaunt',
1109 | 'clove',
1110 | 'enact',
1111 | 'adorn',
1112 | 'roast',
1113 | 'speck',
1114 | 'sheik',
1115 | 'missy',
1116 | 'grunt',
1117 | 'snoop',
1118 | 'party',
1119 | 'touch',
1120 | 'mafia',
1121 | 'emcee',
1122 | 'array',
1123 | 'south',
1124 | 'vapid',
1125 | 'jelly',
1126 | 'skulk',
1127 | 'angst',
1128 | 'tubal',
1129 | 'lower',
1130 | 'crest',
1131 | 'sweat',
1132 | 'cyber',
1133 | 'adore',
1134 | 'tardy',
1135 | 'swami',
1136 | 'notch',
1137 | 'groom',
1138 | 'roach',
1139 | 'hitch',
1140 | 'young',
1141 | 'align',
1142 | 'ready',
1143 | 'frond',
1144 | 'strap',
1145 | 'puree',
1146 | 'realm',
1147 | 'venue',
1148 | 'swarm',
1149 | 'offer',
1150 | 'seven',
1151 | 'dryer',
1152 | 'diary',
1153 | 'dryly',
1154 | 'drank',
1155 | 'acrid',
1156 | 'heady',
1157 | 'theta',
1158 | 'junto',
1159 | 'pixie',
1160 | 'quoth',
1161 | 'bonus',
1162 | 'shalt',
1163 | 'penne',
1164 | 'amend',
1165 | 'datum',
1166 | 'build',
1167 | 'piano',
1168 | 'shelf',
1169 | 'lodge',
1170 | 'suing',
1171 | 'rearm',
1172 | 'coral',
1173 | 'ramen',
1174 | 'worth',
1175 | 'psalm',
1176 | 'infer',
1177 | 'overt',
1178 | 'mayor',
1179 | 'ovoid',
1180 | 'glide',
1181 | 'usage',
1182 | 'poise',
1183 | 'randy',
1184 | 'chuck',
1185 | 'prank',
1186 | 'fishy',
1187 | 'tooth',
1188 | 'ether',
1189 | 'drove',
1190 | 'idler',
1191 | 'swath',
1192 | 'stint',
1193 | 'while',
1194 | 'begat',
1195 | 'apply',
1196 | 'slang',
1197 | 'tarot',
1198 | 'radar',
1199 | 'credo',
1200 | 'aware',
1201 | 'canon',
1202 | 'shift',
1203 | 'timer',
1204 | 'bylaw',
1205 | 'serum',
1206 | 'three',
1207 | 'steak',
1208 | 'iliac',
1209 | 'shirk',
1210 | 'blunt',
1211 | 'puppy',
1212 | 'penal',
1213 | 'joist',
1214 | 'bunny',
1215 | 'shape',
1216 | 'beget',
1217 | 'wheel',
1218 | 'adept',
1219 | 'stunt',
1220 | 'stole',
1221 | 'topaz',
1222 | 'chore',
1223 | 'fluke',
1224 | 'afoot',
1225 | 'bloat',
1226 | 'bully',
1227 | 'dense',
1228 | 'caper',
1229 | 'sneer',
1230 | 'boxer',
1231 | 'jumbo',
1232 | 'lunge',
1233 | 'space',
1234 | 'avail',
1235 | 'short',
1236 | 'slurp',
1237 | 'loyal',
1238 | 'flirt',
1239 | 'pizza',
1240 | 'conch',
1241 | 'tempo',
1242 | 'droop',
1243 | 'plate',
1244 | 'bible',
1245 | 'plunk',
1246 | 'afoul',
1247 | 'savoy',
1248 | 'steep',
1249 | 'agile',
1250 | 'stake',
1251 | 'dwell',
1252 | 'knave',
1253 | 'beard',
1254 | 'arose',
1255 | 'motif',
1256 | 'smash',
1257 | 'broil',
1258 | 'glare',
1259 | 'shove',
1260 | 'baggy',
1261 | 'mammy',
1262 | 'swamp',
1263 | 'along',
1264 | 'rugby',
1265 | 'wager',
1266 | 'quack',
1267 | 'squat',
1268 | 'snaky',
1269 | 'debit',
1270 | 'mange',
1271 | 'skate',
1272 | 'ninth',
1273 | 'joust',
1274 | 'tramp',
1275 | 'spurn',
1276 | 'medal',
1277 | 'micro',
1278 | 'rebel',
1279 | 'flank',
1280 | 'learn',
1281 | 'nadir',
1282 | 'maple',
1283 | 'comfy',
1284 | 'remit',
1285 | 'gruff',
1286 | 'ester',
1287 | 'least',
1288 | 'mogul',
1289 | 'fetch',
1290 | 'cause',
1291 | 'oaken',
1292 | 'aglow',
1293 | 'meaty',
1294 | 'gaffe',
1295 | 'shyly',
1296 | 'racer',
1297 | 'prowl',
1298 | 'thief',
1299 | 'stern',
1300 | 'poesy',
1301 | 'rocky',
1302 | 'tweet',
1303 | 'waist',
1304 | 'spire',
1305 | 'grope',
1306 | 'havoc',
1307 | 'patsy',
1308 | 'truly',
1309 | 'forty',
1310 | 'deity',
1311 | 'uncle',
1312 | 'swish',
1313 | 'giver',
1314 | 'preen',
1315 | 'bevel',
1316 | 'lemur',
1317 | 'draft',
1318 | 'slope',
1319 | 'annoy',
1320 | 'lingo',
1321 | 'bleak',
1322 | 'ditty',
1323 | 'curly',
1324 | 'cedar',
1325 | 'dirge',
1326 | 'grown',
1327 | 'horde',
1328 | 'drool',
1329 | 'shuck',
1330 | 'crypt',
1331 | 'cumin',
1332 | 'stock',
1333 | 'gravy',
1334 | 'locus',
1335 | 'wider',
1336 | 'breed',
1337 | 'quite',
1338 | 'chafe',
1339 | 'cache',
1340 | 'blimp',
1341 | 'deign',
1342 | 'fiend',
1343 | 'logic',
1344 | 'cheap',
1345 | 'elide',
1346 | 'rigid',
1347 | 'false',
1348 | 'renal',
1349 | 'pence',
1350 | 'rowdy',
1351 | 'shoot',
1352 | 'blaze',
1353 | 'envoy',
1354 | 'posse',
1355 | 'brief',
1356 | 'never',
1357 | 'abort',
1358 | 'mouse',
1359 | 'mucky',
1360 | 'sulky',
1361 | 'fiery',
1362 | 'media',
1363 | 'trunk',
1364 | 'yeast',
1365 | 'clear',
1366 | 'skunk',
1367 | 'scalp',
1368 | 'bitty',
1369 | 'cider',
1370 | 'koala',
1371 | 'duvet',
1372 | 'segue',
1373 | 'creme',
1374 | 'super',
1375 | 'grill',
1376 | 'after',
1377 | 'owner',
1378 | 'ember',
1379 | 'reach',
1380 | 'nobly',
1381 | 'empty',
1382 | 'speed',
1383 | 'gipsy',
1384 | 'recur',
1385 | 'smock',
1386 | 'dread',
1387 | 'merge',
1388 | 'burst',
1389 | 'kappa',
1390 | 'amity',
1391 | 'shaky',
1392 | 'hover',
1393 | 'carol',
1394 | 'snort',
1395 | 'synod',
1396 | 'faint',
1397 | 'haunt',
1398 | 'flour',
1399 | 'chair',
1400 | 'detox',
1401 | 'shrew',
1402 | 'tense',
1403 | 'plied',
1404 | 'quark',
1405 | 'burly',
1406 | 'novel',
1407 | 'waxen',
1408 | 'stoic',
1409 | 'jerky',
1410 | 'blitz',
1411 | 'beefy',
1412 | 'lyric',
1413 | 'hussy',
1414 | 'towel',
1415 | 'quilt',
1416 | 'below',
1417 | 'bingo',
1418 | 'wispy',
1419 | 'brash',
1420 | 'scone',
1421 | 'toast',
1422 | 'easel',
1423 | 'saucy',
1424 | 'value',
1425 | 'spice',
1426 | 'honor',
1427 | 'route',
1428 | 'sharp',
1429 | 'bawdy',
1430 | 'radii',
1431 | 'skull',
1432 | 'phony',
1433 | 'issue',
1434 | 'lager',
1435 | 'swell',
1436 | 'urine',
1437 | 'gassy',
1438 | 'trial',
1439 | 'flora',
1440 | 'upper',
1441 | 'latch',
1442 | 'wight',
1443 | 'brick',
1444 | 'retry',
1445 | 'holly',
1446 | 'decal',
1447 | 'grass',
1448 | 'shack',
1449 | 'dogma',
1450 | 'mover',
1451 | 'defer',
1452 | 'sober',
1453 | 'optic',
1454 | 'crier',
1455 | 'vying',
1456 | 'nomad',
1457 | 'flute',
1458 | 'hippo',
1459 | 'shark',
1460 | 'drier',
1461 | 'obese',
1462 | 'bugle',
1463 | 'tawny',
1464 | 'chalk',
1465 | 'feast',
1466 | 'ruddy',
1467 | 'pedal',
1468 | 'scarf',
1469 | 'cruel',
1470 | 'bleat',
1471 | 'tidal',
1472 | 'slush',
1473 | 'semen',
1474 | 'windy',
1475 | 'dusty',
1476 | 'sally',
1477 | 'igloo',
1478 | 'nerdy',
1479 | 'jewel',
1480 | 'shone',
1481 | 'whale',
1482 | 'hymen',
1483 | 'abuse',
1484 | 'fugue',
1485 | 'elbow',
1486 | 'crumb',
1487 | 'pansy',
1488 | 'welsh',
1489 | 'syrup',
1490 | 'terse',
1491 | 'suave',
1492 | 'gamut',
1493 | 'swung',
1494 | 'drake',
1495 | 'freed',
1496 | 'afire',
1497 | 'shirt',
1498 | 'grout',
1499 | 'oddly',
1500 | 'tithe',
1501 | 'plaid',
1502 | 'dummy',
1503 | 'broom',
1504 | 'blind',
1505 | 'torch',
1506 | 'enemy',
1507 | 'again',
1508 | 'tying',
1509 | 'pesky',
1510 | 'alter',
1511 | 'gazer',
1512 | 'noble',
1513 | 'ethos',
1514 | 'bride',
1515 | 'extol',
1516 | 'decor',
1517 | 'hobby',
1518 | 'beast',
1519 | 'idiom',
1520 | 'utter',
1521 | 'these',
1522 | 'sixth',
1523 | 'alarm',
1524 | 'erase',
1525 | 'elegy',
1526 | 'spunk',
1527 | 'piper',
1528 | 'scaly',
1529 | 'scold',
1530 | 'hefty',
1531 | 'chick',
1532 | 'sooty',
1533 | 'canal',
1534 | 'whiny',
1535 | 'slash',
1536 | 'quake',
1537 | 'joint',
1538 | 'swept',
1539 | 'prude',
1540 | 'heavy',
1541 | 'wield',
1542 | 'femme',
1543 | 'lasso',
1544 | 'maize',
1545 | 'shale',
1546 | 'screw',
1547 | 'spree',
1548 | 'smoky',
1549 | 'whiff',
1550 | 'scent',
1551 | 'glade',
1552 | 'spent',
1553 | 'prism',
1554 | 'stoke',
1555 | 'riper',
1556 | 'orbit',
1557 | 'cocoa',
1558 | 'guilt',
1559 | 'humus',
1560 | 'shush',
1561 | 'table',
1562 | 'smirk',
1563 | 'wrong',
1564 | 'noisy',
1565 | 'alert',
1566 | 'shiny',
1567 | 'elate',
1568 | 'resin',
1569 | 'whole',
1570 | 'hunch',
1571 | 'pixel',
1572 | 'polar',
1573 | 'hotel',
1574 | 'sword',
1575 | 'cleat',
1576 | 'mango',
1577 | 'rumba',
1578 | 'puffy',
1579 | 'filly',
1580 | 'billy',
1581 | 'leash',
1582 | 'clout',
1583 | 'dance',
1584 | 'ovate',
1585 | 'facet',
1586 | 'chili',
1587 | 'paint',
1588 | 'liner',
1589 | 'curio',
1590 | 'salty',
1591 | 'audio',
1592 | 'snake',
1593 | 'fable',
1594 | 'cloak',
1595 | 'navel',
1596 | 'spurt',
1597 | 'pesto',
1598 | 'balmy',
1599 | 'flash',
1600 | 'unwed',
1601 | 'early',
1602 | 'churn',
1603 | 'weedy',
1604 | 'stump',
1605 | 'lease',
1606 | 'witty',
1607 | 'wimpy',
1608 | 'spoof',
1609 | 'saner',
1610 | 'blend',
1611 | 'salsa',
1612 | 'thick',
1613 | 'warty',
1614 | 'manic',
1615 | 'blare',
1616 | 'squib',
1617 | 'spoon',
1618 | 'probe',
1619 | 'crepe',
1620 | 'knack',
1621 | 'force',
1622 | 'debut',
1623 | 'order',
1624 | 'haste',
1625 | 'teeth',
1626 | 'agent',
1627 | 'widen',
1628 | 'icily',
1629 | 'slice',
1630 | 'ingot',
1631 | 'clash',
1632 | 'juror',
1633 | 'blood',
1634 | 'abode',
1635 | 'throw',
1636 | 'unity',
1637 | 'pivot',
1638 | 'slept',
1639 | 'troop',
1640 | 'spare',
1641 | 'sewer',
1642 | 'parse',
1643 | 'morph',
1644 | 'cacti',
1645 | 'tacky',
1646 | 'spool',
1647 | 'demon',
1648 | 'moody',
1649 | 'annex',
1650 | 'begin',
1651 | 'fuzzy',
1652 | 'patch',
1653 | 'water',
1654 | 'lumpy',
1655 | 'admin',
1656 | 'omega',
1657 | 'limit',
1658 | 'tabby',
1659 | 'macho',
1660 | 'aisle',
1661 | 'skiff',
1662 | 'basis',
1663 | 'plank',
1664 | 'verge',
1665 | 'botch',
1666 | 'crawl',
1667 | 'lousy',
1668 | 'slain',
1669 | 'cubic',
1670 | 'raise',
1671 | 'wrack',
1672 | 'guide',
1673 | 'foist',
1674 | 'cameo',
1675 | 'under',
1676 | 'actor',
1677 | 'revue',
1678 | 'fraud',
1679 | 'harpy',
1680 | 'scoop',
1681 | 'climb',
1682 | 'refer',
1683 | 'olden',
1684 | 'clerk',
1685 | 'debar',
1686 | 'tally',
1687 | 'ethic',
1688 | 'cairn',
1689 | 'tulle',
1690 | 'ghoul',
1691 | 'hilly',
1692 | 'crude',
1693 | 'apart',
1694 | 'scale',
1695 | 'older',
1696 | 'plain',
1697 | 'sperm',
1698 | 'briny',
1699 | 'abbot',
1700 | 'rerun',
1701 | 'quest',
1702 | 'crisp',
1703 | 'bound',
1704 | 'befit',
1705 | 'drawn',
1706 | 'suite',
1707 | 'itchy',
1708 | 'cheer',
1709 | 'bagel',
1710 | 'guess',
1711 | 'broad',
1712 | 'axiom',
1713 | 'chard',
1714 | 'caput',
1715 | 'leant',
1716 | 'harsh',
1717 | 'curse',
1718 | 'proud',
1719 | 'swing',
1720 | 'opine',
1721 | 'taste',
1722 | 'lupus',
1723 | 'gumbo',
1724 | 'miner',
1725 | 'green',
1726 | 'chasm',
1727 | 'lipid',
1728 | 'topic',
1729 | 'armor',
1730 | 'brush',
1731 | 'crane',
1732 | 'mural',
1733 | 'abled',
1734 | 'habit',
1735 | 'bossy',
1736 | 'maker',
1737 | 'dusky',
1738 | 'dizzy',
1739 | 'lithe',
1740 | 'brook',
1741 | 'jazzy',
1742 | 'fifty',
1743 | 'sense',
1744 | 'giant',
1745 | 'surly',
1746 | 'legal',
1747 | 'fatal',
1748 | 'flunk',
1749 | 'began',
1750 | 'prune',
1751 | 'small',
1752 | 'slant',
1753 | 'scoff',
1754 | 'torus',
1755 | 'ninny',
1756 | 'covey',
1757 | 'viper',
1758 | 'taken',
1759 | 'moral',
1760 | 'vogue',
1761 | 'owing',
1762 | 'token',
1763 | 'entry',
1764 | 'booth',
1765 | 'voter',
1766 | 'chide',
1767 | 'elfin',
1768 | 'ebony',
1769 | 'neigh',
1770 | 'minim',
1771 | 'melon',
1772 | 'kneed',
1773 | 'decoy',
1774 | 'voila',
1775 | 'ankle',
1776 | 'arrow',
1777 | 'mushy',
1778 | 'tribe',
1779 | 'cease',
1780 | 'eager',
1781 | 'birth',
1782 | 'graph',
1783 | 'odder',
1784 | 'terra',
1785 | 'weird',
1786 | 'tried',
1787 | 'clack',
1788 | 'color',
1789 | 'rough',
1790 | 'weigh',
1791 | 'uncut',
1792 | 'ladle',
1793 | 'strip',
1794 | 'craft',
1795 | 'minus',
1796 | 'dicey',
1797 | 'titan',
1798 | 'lucid',
1799 | 'vicar',
1800 | 'dress',
1801 | 'ditch',
1802 | 'gypsy',
1803 | 'pasta',
1804 | 'taffy',
1805 | 'flame',
1806 | 'swoop',
1807 | 'aloof',
1808 | 'sight',
1809 | 'broke',
1810 | 'teary',
1811 | 'chart',
1812 | 'sixty',
1813 | 'wordy',
1814 | 'sheer',
1815 | 'leper',
1816 | 'nosey',
1817 | 'bulge',
1818 | 'savor',
1819 | 'clamp',
1820 | 'funky',
1821 | 'foamy',
1822 | 'toxic',
1823 | 'brand',
1824 | 'plumb',
1825 | 'dingy',
1826 | 'butte',
1827 | 'drill',
1828 | 'tripe',
1829 | 'bicep',
1830 | 'tenor',
1831 | 'krill',
1832 | 'worse',
1833 | 'drama',
1834 | 'hyena',
1835 | 'think',
1836 | 'ratio',
1837 | 'cobra',
1838 | 'basil',
1839 | 'scrum',
1840 | 'bused',
1841 | 'phone',
1842 | 'court',
1843 | 'camel',
1844 | 'proof',
1845 | 'heard',
1846 | 'angel',
1847 | 'petal',
1848 | 'pouty',
1849 | 'throb',
1850 | 'maybe',
1851 | 'fetal',
1852 | 'sprig',
1853 | 'spine',
1854 | 'shout',
1855 | 'cadet',
1856 | 'macro',
1857 | 'dodgy',
1858 | 'satyr',
1859 | 'rarer',
1860 | 'binge',
1861 | 'trend',
1862 | 'nutty',
1863 | 'leapt',
1864 | 'amiss',
1865 | 'split',
1866 | 'myrrh',
1867 | 'width',
1868 | 'sonar',
1869 | 'tower',
1870 | 'baron',
1871 | 'fever',
1872 | 'waver',
1873 | 'spark',
1874 | 'belie',
1875 | 'sloop',
1876 | 'expel',
1877 | 'smote',
1878 | 'baler',
1879 | 'above',
1880 | 'north',
1881 | 'wafer',
1882 | 'scant',
1883 | 'frill',
1884 | 'awash',
1885 | 'snack',
1886 | 'scowl',
1887 | 'frail',
1888 | 'drift',
1889 | 'limbo',
1890 | 'fence',
1891 | 'motel',
1892 | 'ounce',
1893 | 'wreak',
1894 | 'revel',
1895 | 'talon',
1896 | 'prior',
1897 | 'knelt',
1898 | 'cello',
1899 | 'flake',
1900 | 'debug',
1901 | 'anode',
1902 | 'crime',
1903 | 'salve',
1904 | 'scout',
1905 | 'imbue',
1906 | 'pinky',
1907 | 'stave',
1908 | 'vague',
1909 | 'chock',
1910 | 'fight',
1911 | 'video',
1912 | 'stone',
1913 | 'teach',
1914 | 'cleft',
1915 | 'frost',
1916 | 'prawn',
1917 | 'booty',
1918 | 'twist',
1919 | 'apnea',
1920 | 'stiff',
1921 | 'plaza',
1922 | 'ledge',
1923 | 'tweak',
1924 | 'board',
1925 | 'grant',
1926 | 'medic',
1927 | 'bacon',
1928 | 'cable',
1929 | 'brawl',
1930 | 'slunk',
1931 | 'raspy',
1932 | 'forum',
1933 | 'drone',
1934 | 'women',
1935 | 'mucus',
1936 | 'boast',
1937 | 'toddy',
1938 | 'coven',
1939 | 'tumor',
1940 | 'truer',
1941 | 'wrath',
1942 | 'stall',
1943 | 'steam',
1944 | 'axial',
1945 | 'purer',
1946 | 'daily',
1947 | 'trail',
1948 | 'niche',
1949 | 'mealy',
1950 | 'juice',
1951 | 'nylon',
1952 | 'plump',
1953 | 'merry',
1954 | 'flail',
1955 | 'papal',
1956 | 'wheat',
1957 | 'berry',
1958 | 'cower',
1959 | 'erect',
1960 | 'brute',
1961 | 'leggy',
1962 | 'snipe',
1963 | 'sinew',
1964 | 'skier',
1965 | 'penny',
1966 | 'jumpy',
1967 | 'rally',
1968 | 'umbra',
1969 | 'scary',
1970 | 'modem',
1971 | 'gross',
1972 | 'avian',
1973 | 'greed',
1974 | 'satin',
1975 | 'tonic',
1976 | 'parka',
1977 | 'sniff',
1978 | 'livid',
1979 | 'stark',
1980 | 'trump',
1981 | 'giddy',
1982 | 'reuse',
1983 | 'taboo',
1984 | 'avoid',
1985 | 'quote',
1986 | 'devil',
1987 | 'liken',
1988 | 'gloss',
1989 | 'gayer',
1990 | 'beret',
1991 | 'noise',
1992 | 'gland',
1993 | 'dealt',
1994 | 'sling',
1995 | 'rumor',
1996 | 'opera',
1997 | 'thigh',
1998 | 'tonga',
1999 | 'flare',
2000 | 'wound',
2001 | 'white',
2002 | 'bulky',
2003 | 'etude',
2004 | 'horse',
2005 | 'circa',
2006 | 'paddy',
2007 | 'inbox',
2008 | 'fizzy',
2009 | 'grain',
2010 | 'exert',
2011 | 'surge',
2012 | 'gleam',
2013 | 'belle',
2014 | 'salvo',
2015 | 'crush',
2016 | 'fruit',
2017 | 'sappy',
2018 | 'taker',
2019 | 'tract',
2020 | 'ovine',
2021 | 'spiky',
2022 | 'frank',
2023 | 'reedy',
2024 | 'filth',
2025 | 'spasm',
2026 | 'heave',
2027 | 'mambo',
2028 | 'right',
2029 | 'clank',
2030 | 'trust',
2031 | 'lumen',
2032 | 'borne',
2033 | 'spook',
2034 | 'sauce',
2035 | 'amber',
2036 | 'lathe',
2037 | 'carat',
2038 | 'corer',
2039 | 'dirty',
2040 | 'slyly',
2041 | 'affix',
2042 | 'alloy',
2043 | 'taint',
2044 | 'sheep',
2045 | 'kinky',
2046 | 'wooly',
2047 | 'mauve',
2048 | 'flung',
2049 | 'yacht',
2050 | 'fried',
2051 | 'quail',
2052 | 'brunt',
2053 | 'grimy',
2054 | 'curvy',
2055 | 'cagey',
2056 | 'rinse',
2057 | 'deuce',
2058 | 'state',
2059 | 'grasp',
2060 | 'milky',
2061 | 'bison',
2062 | 'graft',
2063 | 'sandy',
2064 | 'baste',
2065 | 'flask',
2066 | 'hedge',
2067 | 'girly',
2068 | 'swash',
2069 | 'boney',
2070 | 'coupe',
2071 | 'endow',
2072 | 'abhor',
2073 | 'welch',
2074 | 'blade',
2075 | 'tight',
2076 | 'geese',
2077 | 'miser',
2078 | 'mirth',
2079 | 'cloud',
2080 | 'cabal',
2081 | 'leech',
2082 | 'close',
2083 | 'tenth',
2084 | 'pecan',
2085 | 'droit',
2086 | 'grail',
2087 | 'clone',
2088 | 'guise',
2089 | 'ralph',
2090 | 'tango',
2091 | 'biddy',
2092 | 'smith',
2093 | 'mower',
2094 | 'payee',
2095 | 'serif',
2096 | 'drape',
2097 | 'fifth',
2098 | 'spank',
2099 | 'glaze',
2100 | 'allot',
2101 | 'truck',
2102 | 'kayak',
2103 | 'virus',
2104 | 'testy',
2105 | 'tepee',
2106 | 'fully',
2107 | 'zonal',
2108 | 'metro',
2109 | 'curry',
2110 | 'grand',
2111 | 'banjo',
2112 | 'axion',
2113 | 'bezel',
2114 | 'occur',
2115 | 'chain',
2116 | 'nasal',
2117 | 'gooey',
2118 | 'filer',
2119 | 'brace',
2120 | 'allay',
2121 | 'pubic',
2122 | 'raven',
2123 | 'plead',
2124 | 'gnash',
2125 | 'flaky',
2126 | 'munch',
2127 | 'dully',
2128 | 'eking',
2129 | 'thing',
2130 | 'slink',
2131 | 'hurry',
2132 | 'theft',
2133 | 'shorn',
2134 | 'pygmy',
2135 | 'ranch',
2136 | 'wring',
2137 | 'lemon',
2138 | 'shore',
2139 | 'mamma',
2140 | 'froze',
2141 | 'newer',
2142 | 'style',
2143 | 'moose',
2144 | 'antic',
2145 | 'drown',
2146 | 'vegan',
2147 | 'chess',
2148 | 'guppy',
2149 | 'union',
2150 | 'lever',
2151 | 'lorry',
2152 | 'image',
2153 | 'cabby',
2154 | 'druid',
2155 | 'exact',
2156 | 'truth',
2157 | 'dopey',
2158 | 'spear',
2159 | 'cried',
2160 | 'chime',
2161 | 'crony',
2162 | 'stunk',
2163 | 'timid',
2164 | 'batch',
2165 | 'gauge',
2166 | 'rotor',
2167 | 'crack',
2168 | 'curve',
2169 | 'latte',
2170 | 'witch',
2171 | 'bunch',
2172 | 'repel',
2173 | 'anvil',
2174 | 'soapy',
2175 | 'meter',
2176 | 'broth',
2177 | 'madly',
2178 | 'dried',
2179 | 'scene',
2180 | 'known',
2181 | 'magma',
2182 | 'roost',
2183 | 'woman',
2184 | 'thong',
2185 | 'punch',
2186 | 'pasty',
2187 | 'downy',
2188 | 'knead',
2189 | 'whirl',
2190 | 'rapid',
2191 | 'clang',
2192 | 'anger',
2193 | 'drive',
2194 | 'goofy',
2195 | 'email',
2196 | 'music',
2197 | 'stuff',
2198 | 'bleep',
2199 | 'rider',
2200 | 'mecca',
2201 | 'folio',
2202 | 'setup',
2203 | 'verso',
2204 | 'quash',
2205 | 'fauna',
2206 | 'gummy',
2207 | 'happy',
2208 | 'newly',
2209 | 'fussy',
2210 | 'relic',
2211 | 'guava',
2212 | 'ratty',
2213 | 'fudge',
2214 | 'femur',
2215 | 'chirp',
2216 | 'forte',
2217 | 'alibi',
2218 | 'whine',
2219 | 'petty',
2220 | 'golly',
2221 | 'plait',
2222 | 'fleck',
2223 | 'felon',
2224 | 'gourd',
2225 | 'brown',
2226 | 'thrum',
2227 | 'ficus',
2228 | 'stash',
2229 | 'decry',
2230 | 'wiser',
2231 | 'junta',
2232 | 'visor',
2233 | 'daunt',
2234 | 'scree',
2235 | 'impel',
2236 | 'await',
2237 | 'press',
2238 | 'whose',
2239 | 'turbo',
2240 | 'stoop',
2241 | 'speak',
2242 | 'mangy',
2243 | 'eying',
2244 | 'inlet',
2245 | 'crone',
2246 | 'pulse',
2247 | 'mossy',
2248 | 'staid',
2249 | 'hence',
2250 | 'pinch',
2251 | 'teddy',
2252 | 'sully',
2253 | 'snore',
2254 | 'ripen',
2255 | 'snowy',
2256 | 'attic',
2257 | 'going',
2258 | 'leach',
2259 | 'mouth',
2260 | 'hound',
2261 | 'clump',
2262 | 'tonal',
2263 | 'bigot',
2264 | 'peril',
2265 | 'piece',
2266 | 'blame',
2267 | 'haute',
2268 | 'spied',
2269 | 'undid',
2270 | 'intro',
2271 | 'basal',
2272 | 'shine',
2273 | 'gecko',
2274 | 'rodeo',
2275 | 'guard',
2276 | 'steer',
2277 | 'loamy',
2278 | 'scamp',
2279 | 'scram',
2280 | 'manly',
2281 | 'hello',
2282 | 'vaunt',
2283 | 'organ',
2284 | 'feral',
2285 | 'knock',
2286 | 'extra',
2287 | 'condo',
2288 | 'adapt',
2289 | 'willy',
2290 | 'polka',
2291 | 'rayon',
2292 | 'skirt',
2293 | 'faith',
2294 | 'torso',
2295 | 'match',
2296 | 'mercy',
2297 | 'tepid',
2298 | 'sleek',
2299 | 'riser',
2300 | 'twixt',
2301 | 'peace',
2302 | 'flush',
2303 | 'catty',
2304 | 'login',
2305 | 'eject',
2306 | 'roger',
2307 | 'rival',
2308 | 'untie',
2309 | 'refit',
2310 | 'aorta',
2311 | 'adult',
2312 | 'judge',
2313 | 'rower',
2314 | 'artsy',
2315 | 'rural',
2316 | 'shave',
2317 | ]
2318 |
--------------------------------------------------------------------------------