Spaces:
Runtime error
Runtime error
add scheduler and collect guesses
Browse files- .gitignore +2 -1
- app.py +61 -3
- frontend/src/lib/Result.svelte +2 -2
- frontend/src/routes/index.svelte +19 -5
- requirements.txt +2 -1
.gitignore
CHANGED
|
@@ -25,4 +25,5 @@ htmlcov/
|
|
| 25 |
*,cover
|
| 26 |
venv
|
| 27 |
*_cache.json
|
| 28 |
-
static
|
|
|
|
|
|
| 25 |
*,cover
|
| 26 |
venv
|
| 27 |
*_cache.json
|
| 28 |
+
static
|
| 29 |
+
data
|
app.py
CHANGED
|
@@ -5,19 +5,44 @@ import uuid
|
|
| 5 |
from pathlib import Path
|
| 6 |
import json
|
| 7 |
from datasets import load_dataset
|
| 8 |
-
from flask import Flask
|
| 9 |
from flask_cors import CORS
|
|
|
|
|
|
|
| 10 |
from PIL import Image
|
|
|
|
|
|
|
| 11 |
|
| 12 |
app = Flask(__name__, static_url_path='/static')
|
| 13 |
|
| 14 |
CORS(app)
|
| 15 |
|
| 16 |
TOKEN = os.environ.get('dataset_token')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
dataset = load_dataset(
|
| 18 |
-
"huggingface-projects/wordalle_prompts",
|
|
|
|
| 19 |
Path("static/images").mkdir(parents=True, exist_ok=True)
|
| 20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
# extract images and prompts from dataset and save to dis
|
| 22 |
data = {}
|
| 23 |
for row in dataset['train']:
|
|
@@ -35,6 +60,20 @@ with open('static/data.json', 'w') as f:
|
|
| 35 |
json.dump(data, f)
|
| 36 |
|
| 37 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
@app.route('/')
|
| 39 |
def index():
|
| 40 |
return app.send_static_file('index.html')
|
|
@@ -45,5 +84,24 @@ def getdata():
|
|
| 45 |
return app.send_static_file('data.json')
|
| 46 |
|
| 47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
if __name__ == '__main__':
|
| 49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
from pathlib import Path
|
| 6 |
import json
|
| 7 |
from datasets import load_dataset
|
| 8 |
+
from flask import Flask, request, jsonify
|
| 9 |
from flask_cors import CORS
|
| 10 |
+
from flask_apscheduler import APScheduler
|
| 11 |
+
|
| 12 |
from PIL import Image
|
| 13 |
+
import sqlite3
|
| 14 |
+
from huggingface_hub import Repository
|
| 15 |
|
| 16 |
app = Flask(__name__, static_url_path='/static')
|
| 17 |
|
| 18 |
CORS(app)
|
| 19 |
|
| 20 |
TOKEN = os.environ.get('dataset_token')
|
| 21 |
+
|
| 22 |
+
DB_FILE = Path("./data/prompts.db")
|
| 23 |
+
|
| 24 |
+
repo = Repository(
|
| 25 |
+
local_dir="data",
|
| 26 |
+
repo_type="dataset",
|
| 27 |
+
clone_from="huggingface-projects/wordalle_guesses",
|
| 28 |
+
use_auth_token=TOKEN
|
| 29 |
+
)
|
| 30 |
+
repo.git_pull()
|
| 31 |
+
|
| 32 |
dataset = load_dataset(
|
| 33 |
+
"huggingface-projects/wordalle_prompts",
|
| 34 |
+
use_auth_token=TOKEN)
|
| 35 |
Path("static/images").mkdir(parents=True, exist_ok=True)
|
| 36 |
|
| 37 |
+
db = sqlite3.connect(DB_FILE)
|
| 38 |
+
try:
|
| 39 |
+
data = db.execute("SELECT * FROM prompts").fetchall()
|
| 40 |
+
db.close()
|
| 41 |
+
print("DB DATA", data)
|
| 42 |
+
except sqlite3.OperationalError:
|
| 43 |
+
db.execute('CREATE TABLE prompts (guess TEXT, correct TEXT)')
|
| 44 |
+
db.commit()
|
| 45 |
+
|
| 46 |
# extract images and prompts from dataset and save to dis
|
| 47 |
data = {}
|
| 48 |
for row in dataset['train']:
|
|
|
|
| 60 |
json.dump(data, f)
|
| 61 |
|
| 62 |
|
| 63 |
+
def update_repository():
|
| 64 |
+
with sqlite3.connect(DB_FILE) as db:
|
| 65 |
+
db.row_factory = sqlite3.Row
|
| 66 |
+
result = db.execute("SELECT * FROM prompts").fetchall()
|
| 67 |
+
data = [dict(row) for row in result]
|
| 68 |
+
|
| 69 |
+
with open('./data/data.json', 'w') as f:
|
| 70 |
+
json.dump(data, f, separators=(',', ':'))
|
| 71 |
+
|
| 72 |
+
print("Updating repository")
|
| 73 |
+
repo.git_pull()
|
| 74 |
+
repo.push_to_hub(blocking=False)
|
| 75 |
+
|
| 76 |
+
|
| 77 |
@app.route('/')
|
| 78 |
def index():
|
| 79 |
return app.send_static_file('index.html')
|
|
|
|
| 84 |
return app.send_static_file('data.json')
|
| 85 |
|
| 86 |
|
| 87 |
+
@app.route('/prompt', methods=['POST', 'GET'])
|
| 88 |
+
def create():
|
| 89 |
+
if request.method == 'POST':
|
| 90 |
+
try:
|
| 91 |
+
data = request.get_json()
|
| 92 |
+
guess = data['guess']
|
| 93 |
+
correct = data['correct']
|
| 94 |
+
with sqlite3.connect(DB_FILE) as db:
|
| 95 |
+
db.execute(
|
| 96 |
+
'INSERT INTO prompts (guess, correct) VALUES (?, ?)', (guess, correct))
|
| 97 |
+
db.commit()
|
| 98 |
+
return 'OK', 200
|
| 99 |
+
except:
|
| 100 |
+
return 'Missing guess or correct', 400
|
| 101 |
+
|
| 102 |
if __name__ == '__main__':
|
| 103 |
+
scheduler = APScheduler()
|
| 104 |
+
scheduler.add_job(id = 'Update Dataset Repository', func = update_repository, trigger = 'interval', seconds = 60)
|
| 105 |
+
scheduler.start()
|
| 106 |
+
app.run(host='0.0.0.0', port=int(
|
| 107 |
+
os.environ.get('PORT', 7860)), debug=True)
|
frontend/src/lib/Result.svelte
CHANGED
|
@@ -13,7 +13,7 @@
|
|
| 13 |
export let totalStreaks: number;
|
| 14 |
const message = cheersMessages[currentRowIndex];
|
| 15 |
import domtoimage from 'dom-to-image';
|
| 16 |
-
const
|
| 17 |
|
| 18 |
let modalEl: HTMLDivElement;
|
| 19 |
let elToShare: HTMLDivElement;
|
|
@@ -89,7 +89,7 @@
|
|
| 89 |
{/if}
|
| 90 |
{#each imagePaths as image}
|
| 91 |
<div>
|
| 92 |
-
<img src={
|
| 93 |
</div>
|
| 94 |
{/each}
|
| 95 |
</div>
|
|
|
|
| 13 |
export let totalStreaks: number;
|
| 14 |
const message = cheersMessages[currentRowIndex];
|
| 15 |
import domtoimage from 'dom-to-image';
|
| 16 |
+
const apiUrl = import.meta.env.MODE === 'development' ? 'http://localhost:7860/' : '';
|
| 17 |
|
| 18 |
let modalEl: HTMLDivElement;
|
| 19 |
let elToShare: HTMLDivElement;
|
|
|
|
| 89 |
{/if}
|
| 90 |
{#each imagePaths as image}
|
| 91 |
<div>
|
| 92 |
+
<img src={apiUrl + image} alt="" class="aspect-square w-full h-full" />
|
| 93 |
</div>
|
| 94 |
{/each}
|
| 95 |
</div>
|
frontend/src/routes/index.svelte
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
<script lang="ts">
|
| 2 |
// original code inspired by Evan You https://github.com/yyx990803/vue-wordle/
|
| 3 |
import { LetterState, GameState } from '../types';
|
| 4 |
-
import type { Board, PromptsData, SuccessPrompt } from '../types';
|
| 5 |
import { clearTile, fillTile } from '$lib/utils';
|
| 6 |
|
| 7 |
import Keyboard from '$lib/Keyboard.svelte';
|
|
@@ -12,15 +12,14 @@
|
|
| 12 |
import { browser } from '$app/env';
|
| 13 |
|
| 14 |
const totalTime = 1000;
|
| 15 |
-
const apiUrl = import.meta.env.MODE === 'development' ? 'http://localhost:7860/
|
| 16 |
-
const imageBaseUrl = import.meta.env.MODE === 'development' ? 'http://localhost:7860/' : '';
|
| 17 |
|
| 18 |
let promptsData: PromptsData;
|
| 19 |
let completedPrompts: SuccessPrompt[] = [];
|
| 20 |
let currPromptIndex: number;
|
| 21 |
onMount(async () => {
|
| 22 |
onResize();
|
| 23 |
-
promptsData = await fetch(apiUrl).then((d) => d.json());
|
| 24 |
restartBoard();
|
| 25 |
window.addEventListener('keyup', onKeyup, true);
|
| 26 |
window.addEventListener('resize', onResize);
|
|
@@ -117,6 +116,7 @@
|
|
| 117 |
// showMessage(`Not in word list`)
|
| 118 |
// return
|
| 119 |
// }
|
|
|
|
| 120 |
|
| 121 |
const answerLetters: (string | null)[] = answer.split('');
|
| 122 |
// first pass: mark correct ones
|
|
@@ -190,6 +190,20 @@
|
|
| 190 |
shakeRowIndex = -1;
|
| 191 |
}, 1000);
|
| 192 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 193 |
</script>
|
| 194 |
|
| 195 |
{#if board !== undefined}
|
|
@@ -233,7 +247,7 @@
|
|
| 233 |
<div class="grid grid-cols-3 gap-2 max-w-md mx-auto p-3">
|
| 234 |
{#each imagePaths as image}
|
| 235 |
<div>
|
| 236 |
-
<img src={
|
| 237 |
</div>
|
| 238 |
{/each}
|
| 239 |
</div>
|
|
|
|
| 1 |
<script lang="ts">
|
| 2 |
// original code inspired by Evan You https://github.com/yyx990803/vue-wordle/
|
| 3 |
import { LetterState, GameState } from '../types';
|
| 4 |
+
import type { Board, PromptsData, SuccessPrompt, Tile } from '../types';
|
| 5 |
import { clearTile, fillTile } from '$lib/utils';
|
| 6 |
|
| 7 |
import Keyboard from '$lib/Keyboard.svelte';
|
|
|
|
| 12 |
import { browser } from '$app/env';
|
| 13 |
|
| 14 |
const totalTime = 1000;
|
| 15 |
+
const apiUrl = import.meta.env.MODE === 'development' ? 'http://localhost:7860/' : '';
|
|
|
|
| 16 |
|
| 17 |
let promptsData: PromptsData;
|
| 18 |
let completedPrompts: SuccessPrompt[] = [];
|
| 19 |
let currPromptIndex: number;
|
| 20 |
onMount(async () => {
|
| 21 |
onResize();
|
| 22 |
+
promptsData = await fetch(apiUrl + 'data').then((d) => d.json());
|
| 23 |
restartBoard();
|
| 24 |
window.addEventListener('keyup', onKeyup, true);
|
| 25 |
window.addEventListener('resize', onResize);
|
|
|
|
| 116 |
// showMessage(`Not in word list`)
|
| 117 |
// return
|
| 118 |
// }
|
| 119 |
+
postProcess(currentRow);
|
| 120 |
|
| 121 |
const answerLetters: (string | null)[] = answer.split('');
|
| 122 |
// first pass: mark correct ones
|
|
|
|
| 190 |
shakeRowIndex = -1;
|
| 191 |
}, 1000);
|
| 192 |
}
|
| 193 |
+
async function postProcess(currentRow: Tile[]) {
|
| 194 |
+
const guess = currentRow.map((tile) => tile.letter).join('');
|
| 195 |
+
const correct = currentRow.map((tile) => tile.correct).join('');
|
| 196 |
+
fetch(apiUrl + 'prompt', {
|
| 197 |
+
method: 'POST',
|
| 198 |
+
headers: {
|
| 199 |
+
'Content-Type': 'application/json'
|
| 200 |
+
},
|
| 201 |
+
body: JSON.stringify({
|
| 202 |
+
guess: guess,
|
| 203 |
+
correct: correct
|
| 204 |
+
})
|
| 205 |
+
});
|
| 206 |
+
}
|
| 207 |
</script>
|
| 208 |
|
| 209 |
{#if board !== undefined}
|
|
|
|
| 247 |
<div class="grid grid-cols-3 gap-2 max-w-md mx-auto p-3">
|
| 248 |
{#each imagePaths as image}
|
| 249 |
<div>
|
| 250 |
+
<img src={apiUrl + image} alt="" class="aspect-square w-full h-full" />
|
| 251 |
</div>
|
| 252 |
{/each}
|
| 253 |
</div>
|
requirements.txt
CHANGED
|
@@ -4,4 +4,5 @@ flask_cors
|
|
| 4 |
requests
|
| 5 |
Pillow
|
| 6 |
scipy
|
| 7 |
-
gradio==3.0.
|
|
|
|
|
|
| 4 |
requests
|
| 5 |
Pillow
|
| 6 |
scipy
|
| 7 |
+
gradio==3.0.19
|
| 8 |
+
Flask-APScheduler
|