Compare commits

..

5 Commits
shalom ... main

9 changed files with 794886 additions and 27 deletions

794771
1_1_all_fullalpha.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,13 @@
WORD_LENGTH=5 WORD_LENGTH=5
MIN_FREQUENCY=1 VALID_ANSWER_FREQ_MIN=10
VALID_INPUT_FREQ_MIN=1
SOURCE_WORDLIST=1_1_all_fullalpha.txt SOURCE_WORDLIST=1_1_all_fullalpha.txt
ALLOWED_TYPELIST=allowed_types ALLOWED_TYPELIST=allowed_types
all: wordlist.js .SUBMODULES all: wordlist.js .SUBMODULES
wordlist.js: wordlist.js:
./scripts/gen_wordlist.py ${SOURCE_WORDLIST} ${WORD_LENGTH} ${MIN_FREQUENCY} ${ALLOWED_TYPELIST} > wordlist.js ./scripts/gen_wordlist.py ${SOURCE_WORDLIST} ${WORD_LENGTH} ${VALID_ANSWER_FREQ_MIN} ${VALID_INPUT_FREQ_MIN} ${ALLOWED_TYPELIST} > wordlist.js
clean: clean:
rm -rf wordlist.js rm -rf wordlist.js

11
allowed_types Normal file
View File

@ -0,0 +1,11 @@
adj
prep
adv
num
int
verb
pron
conj
noc
vmod
@

18
game.js
View File

@ -1,7 +1,7 @@
// global constants // global constants
const gridWidth = 6 const gridWidth = 5
const gridHeight = 6 const gridHeight = 6
const word = wordlist[Math.floor(Math.random()*wordlist.length)]; const word = wordlist.valid_answers[Math.floor(Math.random()*wordlist.valid_answers.length)];
// global state variables // global state variables
var gameCompleted = null var gameCompleted = null
@ -42,9 +42,11 @@ function checkGridRow() {
getGridRow(row).items.forEach(item => rowWord += item.letter) getGridRow(row).items.forEach(item => rowWord += item.letter)
console.log(rowWord) console.log(rowWord)
if (!wordlist.includes(rowWord)) { if (!wordlist.valid_inputs.includes(rowWord)) {
body.classList.add("incorrect") getGridRow(row).items.forEach(item => {
setTimeout( () => body.classList.remove("incorrect"), 500) item.HTMLItem.classList.add("incorrect")
setTimeout( () => item.HTMLItem.classList.remove("incorrect"), 500)
})
return return
} }
@ -191,21 +193,16 @@ function runClickAnimation(el) {
el.classList.add("clicked") el.classList.add("clicked")
setTimeout(() => el.classList.remove("clicked"), 500) setTimeout(() => el.classList.remove("clicked"), 500)
} }
// create event listeners // create event listeners
document.addEventListener('keyup', e => setNextLetter(e)) document.addEventListener('keyup', e => setNextLetter(e))
kbBackspace.addEventListener('click', () => { kbBackspace.addEventListener('click', () => {
runClickAnimation(kbBackspace) runClickAnimation(kbBackspace)
setNextLetter({code: "Backspace", key: "Backspace"}) setNextLetter({code: "Backspace", key: "Backspace"})
}) })
kbEnter.addEventListener('click', () => { kbEnter.addEventListener('click', () => {
runClickAnimation(kbEnter) runClickAnimation(kbEnter)
setNextLetter({code: "Enter", key: "Enter"}) setNextLetter({code: "Enter", key: "Enter"})
}) })
kbLetters.forEach(kbl => { kbLetters.forEach(kbl => {
kbl.addEventListener('click', () => { kbl.addEventListener('click', () => {
runClickAnimation(kbl) runClickAnimation(kbl)
@ -213,7 +210,6 @@ kbLetters.forEach(kbl => {
}) })
}) })
// start game // start game
init() init()
console.log(word) console.log(word)

View File

@ -4,10 +4,10 @@
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="styles.css"> <link rel="stylesheet" type="text/css" href="styles.css">
<link rel="stylesheet" type="text/css" href="./Font-Awesome/css/all.min.css"> <link rel="stylesheet" type="text/css" href="./Font-Awesome/css/all.min.css">
<title>shalomle</title> <title>words by alv</title>
</head> </head>
<body> <body>
<h1 style="text-align: center">shalomle</h1> <h1 style="text-align: center">words by alv</h1>
<div id="game_container"> <div id="game_container">
</div> </div>
@ -55,7 +55,8 @@
</div> </div>
</div> </div>
<div id="footer"> <div id="footer">
<p>built with ❤ and shalom by <a href="https://alv.cx">alv</a></p> <p>built with ❤ and adequate amounts of care by <a href="https://alv.cx">alv</a></p>
<p>thanks to Lancaster University for the wordlist, which you can find <a href="https://ucrel.lancs.ac.uk/bncfreq/flists.html">here</a> </p>
</div> </div>
<script type="application/javascript" src="wordlist.js"></script> <script type="application/javascript" src="wordlist.js"></script>

View File

@ -1,2 +1,8 @@
# shalomle # words
you know what it is
wordlist `1_1_all_fullalpha.txt` is from Lancaster University, available [here](https://ucrel.lancs.ac.uk/bncfreq/flists.html)
![screenshot](./screenshot.png)

66
scripts/gen_wordlist.py Executable file
View File

@ -0,0 +1,66 @@
#!/usr/bin/env python3
import sys
import json
class WordListItem:
def __init__(self, line):
word = line.split('\t')
self.word = word[1] if word[1].isalpha() else word[3]
self.pos = word[2]
self.freq = int(word[4])
def __repr__(self):
return f"<WordListItem {self.word=} {self.pos=} {self.freq=}>"
def get_args():
""" Get command line arguments """
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('wordlist')
parser.add_argument('word_length', type=int)
parser.add_argument('valid_answer_freq_min', type=int)
parser.add_argument('valid_input_freq_min', type=int)
parser.add_argument('allowedtypelist')
return parser.parse_args()
def main(args):
""" Entry point for script """
with open(args.allowedtypelist) as fp:
allowed_types = fp.read().split('\n')
types = set()
with open(args.wordlist) as fp:
src_words = [ WordListItem(line) for line in fp.read().strip().lower().split('\n') ]
src_words = [ word for word in src_words if word.word.isalpha() ]
src_words = [ word for word in src_words if len(word.word) == args.word_length ]
src_words = [ word for word in src_words if word.pos in allowed_types ]
[ types.add(word.pos) for word in src_words ]
words = {}
words['valid_answers'] = [ w.word for w in src_words if w.freq >= args.valid_answer_freq_min ]
words['valid_inputs'] = [ w.word for w in src_words if w.freq >= args.valid_input_freq_min ]
# remove duplicates
print(f"wordlist = {json.dumps(words)}")
print(f"{args=}", file=sys.stderr)
print(f"{len(words['valid_answers'])=}", file=sys.stderr)
print(f"{len(words['valid_inputs'])=}", file=sys.stderr)
print(f"{types=}", file=sys.stderr)
return 0
if __name__ == '__main__':
try:
sys.exit(main(get_args()))
except KeyboardInterrupt:
sys.exit(0)

View File

@ -1,4 +1,10 @@
@import url("https://alv.cx/styles.css"); @import url("https://styles.alv.cx/colors/gruvbox.css");
@import url("https://styles.alv.cx/base.css");
:root {
--light: var(--colorscheme-light);
}
:root { :root {
--default-bg: #fefefe; --default-bg: #fefefe;
@ -78,37 +84,37 @@ body {
@keyframes correct { @keyframes correct {
0% { 0% {
background: var(--default-bg); background: var(--bg);
} }
50% { 50% {
background: var(--green); background: var(--green);
} }
100% { 100% {
background: var(--default-bg); background: var(--bg);
} }
} }
@keyframes incorrect { @keyframes incorrect {
0% { 0% {
background: var(--default-bg); background: var(--bg);
} }
50% { 50% {
background: var(--red); background: var(--red);
} }
100% { 100% {
background: var(--default-bg); background: var(--bg);
} }
} }
@keyframes clicked { @keyframes clicked {
0% { 0% {
background: var(--default-bg); background: var(--bg);
} }
50% { 50% {
background: var(--dark-bg); background: var(--bg-lc);
} }
100% { 100% {
background: var(--default-bg); background: var(--bg);
} }
} }
@ -123,11 +129,13 @@ body {
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
background-color: rgba(255, 255, 255, 0.8) background-color: var(--bg);
opacity: 0.8;
} }
#end_screen * { #end_screen * {
width: fit-content; width: fit-content;
opacity: 1;
} }
#end_screen_image { #end_screen_image {

View File

@ -1 +0,0 @@
wordlist = [ "shalom" ]