neal-words/words.py

108 lines
2.4 KiB
Python

import time
import httpx
import random
import sqlite3
import logging
from dataclasses import dataclass
@dataclass
class Scores:
productivity : int
rank : int
logging.basicConfig(level=logging.INFO)
log = logging.getLogger(__name__)
http = httpx.Client(headers={
'Referer': 'https://neal.fun/infinite-craft/',
})
db = sqlite3.connect('words.sqlite3')
db.execute('pragma foreign_keys = on')
r = db.execute('''
select x.word, x.rank, y.word, y.rank
from words x, words y
where not exists (
select *
from combos c
where c.x = x.word and c.y = y.word
)
''')
while True:
r = db.execute('''
select
w.word,
w.rank,
count(distinct c.z) as productivity
from combos c
join words w on w.word = c.x
where w.word != 'Nothing'
group by w.word
''')
scores = {
w: Scores(productivity=p, rank=r)
for w, r, p in r.fetchall()
}
pop = [(
(x,y),
xs.productivity*ys.productivity,
) for x, xs in scores.items()
for y, ys in scores.items()
]
while True:
(x, y), = random.sample(
k=1,
population=[xy for xy,_ in pop],
counts=[score for _,score in pop],
)
r = db.execute('''
select exists (
select *
from combos
where x = ? and y = ?
)
''', (x, y))
if r.fetchall()[0][0]:
# we already know the answer
log.info('already got %s + %s', x, y)
continue
else:
break
resp = http.get(
'https://neal.fun/api/infinite-craft/pair',
params={
'first': x,
'second': y,
},
)
resp.raise_for_status()
response = resp.json()
z = response['result']
is_new = response['isNew']
log.info(
'%s (%s) + %s (%s) -> %s%s',
x, scores[x], y, scores[y], z,
' [NEW!]' if is_new else ''
)
z_rank = 1+max(scores[x].rank, scores[y].rank)
db.execute('''
insert into words (word, rank, is_new) values (?, ?, ?)
on conflict(word) do update set rank = ? where rank > ?
''', (z, z_rank, is_new, z_rank, z_rank))
db.executemany(
'insert or ignore into combos (x, y, z) values (?, ?, ?)',
[(x, y, z), (y, x, z)],
)
db.commit()
time.sleep(5)