Upload folder using huggingface_hub
Browse files- .gitignore +223 -0
- README.md +25 -8
- Try Gemma-2-9B.ipynb +218 -0
- __init__.py +0 -0
- agent.py +0 -0
- environment.yml +9 -0
- gdrive_try.ipynb +1 -0
- generate.py +51 -0
- model_outputs/results_batch_api_openai_gpt-4o-mini-2024-07-18.jsonl +0 -0
- oauth_environ_google.sh +1 -0
- play.py +89 -0
- play.sh +3 -0
- play_gradio.py +77 -0
- play_helper.py +213 -77
- play_with_auth.py +158 -0
- read_pkl.py +11 -0
- textgames/__init__.py +8 -6
- textgames/base_game.py +4 -7
- textgames/ordering_text/ordering_text.py +1 -1
- textgames_userauth_generate.py +44 -0
.gitignore
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*/*.DS_Store
|
| 2 |
+
.DS_Store
|
| 3 |
+
|
| 4 |
+
ssl/
|
| 5 |
+
problemsets_*
|
| 6 |
+
|
| 7 |
+
user_outputs/
|
| 8 |
+
|
| 9 |
+
.idea/
|
| 10 |
+
|
| 11 |
+
# Created by https://www.gitignore.io/api/macos,linux,django,python,pycharm
|
| 12 |
+
|
| 13 |
+
### Django ###
|
| 14 |
+
*.log
|
| 15 |
+
*.pot
|
| 16 |
+
*.pyc
|
| 17 |
+
__pycache__/
|
| 18 |
+
local_settings.py
|
| 19 |
+
db.sqlite3
|
| 20 |
+
media
|
| 21 |
+
|
| 22 |
+
### Linux ###
|
| 23 |
+
*~
|
| 24 |
+
|
| 25 |
+
# temporary files which can be created if a process still has a handle open of a deleted file
|
| 26 |
+
.fuse_hidden*
|
| 27 |
+
|
| 28 |
+
# KDE directory preferences
|
| 29 |
+
.directory
|
| 30 |
+
|
| 31 |
+
# Linux trash folder which might appear on any partition or disk
|
| 32 |
+
.Trash-*
|
| 33 |
+
|
| 34 |
+
# .nfs files are created when an open file is removed but is still being accessed
|
| 35 |
+
.nfs*
|
| 36 |
+
|
| 37 |
+
### macOS ###
|
| 38 |
+
*.DS_Store
|
| 39 |
+
.AppleDouble
|
| 40 |
+
.LSOverride
|
| 41 |
+
|
| 42 |
+
# Icon must end with two \r
|
| 43 |
+
Icon
|
| 44 |
+
|
| 45 |
+
# Thumbnails
|
| 46 |
+
._*
|
| 47 |
+
|
| 48 |
+
# Files that might appear in the root of a volume
|
| 49 |
+
.DocumentRevisions-V100
|
| 50 |
+
.fseventsd
|
| 51 |
+
.Spotlight-V100
|
| 52 |
+
.TemporaryItems
|
| 53 |
+
.Trashes
|
| 54 |
+
.VolumeIcon.icns
|
| 55 |
+
.com.apple.timemachine.donotpresent
|
| 56 |
+
|
| 57 |
+
# Directories potentially created on remote AFP share
|
| 58 |
+
.AppleDB
|
| 59 |
+
.AppleDesktop
|
| 60 |
+
Network Trash Folder
|
| 61 |
+
Temporary Items
|
| 62 |
+
.apdisk
|
| 63 |
+
|
| 64 |
+
### PyCharm ###
|
| 65 |
+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
|
| 66 |
+
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
| 67 |
+
|
| 68 |
+
# User-specific stuff:
|
| 69 |
+
.idea/**/workspace.xml
|
| 70 |
+
.idea/**/tasks.xml
|
| 71 |
+
.idea/dictionaries
|
| 72 |
+
|
| 73 |
+
# Sensitive or high-churn files:
|
| 74 |
+
.idea/**/dataSources/
|
| 75 |
+
.idea/**/dataSources.ids
|
| 76 |
+
.idea/**/dataSources.xml
|
| 77 |
+
.idea/**/dataSources.local.xml
|
| 78 |
+
.idea/**/sqlDataSources.xml
|
| 79 |
+
.idea/**/dynamic.xml
|
| 80 |
+
.idea/**/uiDesigner.xml
|
| 81 |
+
|
| 82 |
+
# Gradle:
|
| 83 |
+
.idea/**/gradle.xml
|
| 84 |
+
.idea/**/libraries
|
| 85 |
+
|
| 86 |
+
# CMake
|
| 87 |
+
cmake-build-debug/
|
| 88 |
+
|
| 89 |
+
# Mongo Explorer plugin:
|
| 90 |
+
.idea/**/mongoSettings.xml
|
| 91 |
+
|
| 92 |
+
## File-based project format:
|
| 93 |
+
*.iws
|
| 94 |
+
|
| 95 |
+
## Plugin-specific files:
|
| 96 |
+
|
| 97 |
+
# IntelliJ
|
| 98 |
+
/out/
|
| 99 |
+
|
| 100 |
+
# mpeltonen/sbt-idea plugin
|
| 101 |
+
.idea_modules/
|
| 102 |
+
|
| 103 |
+
# JIRA plugin
|
| 104 |
+
atlassian-ide-plugin.xml
|
| 105 |
+
|
| 106 |
+
# Cursive Clojure plugin
|
| 107 |
+
.idea/replstate.xml
|
| 108 |
+
|
| 109 |
+
# Crashlytics plugin (for Android Studio and IntelliJ)
|
| 110 |
+
com_crashlytics_export_strings.xml
|
| 111 |
+
crashlytics.properties
|
| 112 |
+
crashlytics-build.properties
|
| 113 |
+
fabric.properties
|
| 114 |
+
|
| 115 |
+
### PyCharm Patch ###
|
| 116 |
+
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
| 117 |
+
|
| 118 |
+
# *.iml
|
| 119 |
+
# modules.xml
|
| 120 |
+
# .idea/misc.xml
|
| 121 |
+
# *.ipr
|
| 122 |
+
|
| 123 |
+
# Sonarlint plugin
|
| 124 |
+
.idea/sonarlint
|
| 125 |
+
|
| 126 |
+
### Python ###
|
| 127 |
+
# Byte-compiled / optimized / DLL files
|
| 128 |
+
*.py[cod]
|
| 129 |
+
*$py.class
|
| 130 |
+
|
| 131 |
+
# C extensions
|
| 132 |
+
*.so
|
| 133 |
+
|
| 134 |
+
# Distribution / packaging
|
| 135 |
+
.Python
|
| 136 |
+
env/
|
| 137 |
+
build/
|
| 138 |
+
develop-eggs/
|
| 139 |
+
dist/
|
| 140 |
+
downloads/
|
| 141 |
+
eggs/
|
| 142 |
+
.eggs/
|
| 143 |
+
lib/
|
| 144 |
+
lib64/
|
| 145 |
+
parts/
|
| 146 |
+
sdist/
|
| 147 |
+
var/
|
| 148 |
+
wheels/
|
| 149 |
+
*.egg-info/
|
| 150 |
+
.installed.cfg
|
| 151 |
+
*.egg
|
| 152 |
+
|
| 153 |
+
# PyInstaller
|
| 154 |
+
# Usually these files are written by a python script from a template
|
| 155 |
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
| 156 |
+
*.manifest
|
| 157 |
+
*.spec
|
| 158 |
+
|
| 159 |
+
# Installer logs
|
| 160 |
+
pip-log.txt
|
| 161 |
+
pip-delete-this-directory.txt
|
| 162 |
+
|
| 163 |
+
# Unit test / coverage reports
|
| 164 |
+
htmlcov/
|
| 165 |
+
.tox/
|
| 166 |
+
.coverage
|
| 167 |
+
.coverage.*
|
| 168 |
+
.cache
|
| 169 |
+
nosetests.xml
|
| 170 |
+
coverage.xml
|
| 171 |
+
*,cover
|
| 172 |
+
.hypothesis/
|
| 173 |
+
|
| 174 |
+
# Translations
|
| 175 |
+
*.mo
|
| 176 |
+
|
| 177 |
+
# Django stuff:
|
| 178 |
+
|
| 179 |
+
# Flask stuff:
|
| 180 |
+
instance/
|
| 181 |
+
.webassets-cache
|
| 182 |
+
|
| 183 |
+
# Scrapy stuff:
|
| 184 |
+
.scrapy
|
| 185 |
+
|
| 186 |
+
# Sphinx documentation
|
| 187 |
+
docs/_build/
|
| 188 |
+
|
| 189 |
+
# PyBuilder
|
| 190 |
+
target/
|
| 191 |
+
|
| 192 |
+
# Jupyter Notebook
|
| 193 |
+
.ipynb_checkpoints
|
| 194 |
+
|
| 195 |
+
# pyenv
|
| 196 |
+
.python-version
|
| 197 |
+
|
| 198 |
+
# celery beat schedule file
|
| 199 |
+
celerybeat-schedule
|
| 200 |
+
|
| 201 |
+
# SageMath parsed files
|
| 202 |
+
*.sage.py
|
| 203 |
+
|
| 204 |
+
# dotenv
|
| 205 |
+
.env
|
| 206 |
+
*.env
|
| 207 |
+
|
| 208 |
+
# virtualenv
|
| 209 |
+
.venv
|
| 210 |
+
venv/
|
| 211 |
+
ENV/
|
| 212 |
+
|
| 213 |
+
# Spyder project settings
|
| 214 |
+
.spyderproject
|
| 215 |
+
.spyproject
|
| 216 |
+
|
| 217 |
+
# Rope project settings
|
| 218 |
+
.ropeproject
|
| 219 |
+
|
| 220 |
+
# mkdocs documentation
|
| 221 |
+
/site
|
| 222 |
+
|
| 223 |
+
# End of https://www.gitignore.io/api/macos,linux,django,python,pycharm
|
README.md
CHANGED
|
@@ -1,12 +1,29 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
|
| 4 |
-
colorFrom: blue
|
| 5 |
-
colorTo: red
|
| 6 |
sdk: gradio
|
| 7 |
-
sdk_version: 5.
|
| 8 |
-
app_file: app.py
|
| 9 |
-
pinned: false
|
| 10 |
---
|
|
|
|
| 11 |
|
| 12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: textgames
|
| 3 |
+
app_file: play_gradio.py
|
|
|
|
|
|
|
| 4 |
sdk: gradio
|
| 5 |
+
sdk_version: 5.8.0
|
|
|
|
|
|
|
| 6 |
---
|
| 7 |
+
# TextGames
|
| 8 |
|
| 9 |
+
## Setup
|
| 10 |
+
```
|
| 11 |
+
❱❱❱ pip install -r requirements.txt
|
| 12 |
+
```
|
| 13 |
+
|
| 14 |
+
## Play (Terminal)
|
| 15 |
+
```
|
| 16 |
+
❱❱❱ python play.py
|
| 17 |
+
```
|
| 18 |
+
|
| 19 |
+
## Play (Web UI)
|
| 20 |
+
```
|
| 21 |
+
❱❱❱ pip install gradio
|
| 22 |
+
❱❱❱ GRADIO_SERVER_PORT=1080 python play_gradio.py
|
| 23 |
+
```
|
| 24 |
+
Open `localhost:1080` to access.
|
| 25 |
+
|
| 26 |
+
## Optional Environment Varibles
|
| 27 |
+
```
|
| 28 |
+
TEXTGAMES_SHOW_HIDDEN_LEVEL=1
|
| 29 |
+
```
|
Try Gemma-2-9B.ipynb
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"nbformat": 4,
|
| 3 |
+
"nbformat_minor": 0,
|
| 4 |
+
"metadata": {
|
| 5 |
+
"colab": {
|
| 6 |
+
"private_outputs": true,
|
| 7 |
+
"provenance": [],
|
| 8 |
+
"authorship_tag": "ABX9TyPmvDoFpmwAf1QFBJZy7XSQ"
|
| 9 |
+
},
|
| 10 |
+
"kernelspec": {
|
| 11 |
+
"name": "python3",
|
| 12 |
+
"display_name": "Python 3"
|
| 13 |
+
},
|
| 14 |
+
"language_info": {
|
| 15 |
+
"name": "python"
|
| 16 |
+
}
|
| 17 |
+
},
|
| 18 |
+
"cells": [
|
| 19 |
+
{
|
| 20 |
+
"cell_type": "code",
|
| 21 |
+
"execution_count": null,
|
| 22 |
+
"metadata": {
|
| 23 |
+
"id": "Rli_enT6lBDT"
|
| 24 |
+
},
|
| 25 |
+
"outputs": [],
|
| 26 |
+
"source": [
|
| 27 |
+
"##%%\n",
|
| 28 |
+
"import os\n",
|
| 29 |
+
"import torch\n",
|
| 30 |
+
"import random\n",
|
| 31 |
+
"import numpy as np\n",
|
| 32 |
+
"import argparse\n",
|
| 33 |
+
"import json\n",
|
| 34 |
+
"import cohere\n",
|
| 35 |
+
"from openai import OpenAI\n"
|
| 36 |
+
]
|
| 37 |
+
},
|
| 38 |
+
{
|
| 39 |
+
"cell_type": "code",
|
| 40 |
+
"source": [
|
| 41 |
+
"##%%\n",
|
| 42 |
+
"from tqdm import tqdm\n",
|
| 43 |
+
"\n",
|
| 44 |
+
"from collections import Counter\n",
|
| 45 |
+
"\n",
|
| 46 |
+
"from transformers import LlamaForCausalLM, AutoTokenizer, AutoModelForCausalLM, AutoModelForSeq2SeqLM\n",
|
| 47 |
+
"import hashlib\n",
|
| 48 |
+
"\n",
|
| 49 |
+
"from textgames import GAME_NAMES, GAME_IDS, LEVELS, LEVELS_HIDDEN, LEVEL_IDS, new_game\n"
|
| 50 |
+
],
|
| 51 |
+
"metadata": {
|
| 52 |
+
"id": "dp1F32B8oSfD"
|
| 53 |
+
},
|
| 54 |
+
"execution_count": null,
|
| 55 |
+
"outputs": []
|
| 56 |
+
},
|
| 57 |
+
{
|
| 58 |
+
"cell_type": "code",
|
| 59 |
+
"source": [
|
| 60 |
+
"##%%\n",
|
| 61 |
+
"gen_model_checkpoint = \"google/gemma-2-9b-it\"\n",
|
| 62 |
+
"quantize = True"
|
| 63 |
+
],
|
| 64 |
+
"metadata": {
|
| 65 |
+
"id": "jZF8bkUcojTX"
|
| 66 |
+
},
|
| 67 |
+
"execution_count": null,
|
| 68 |
+
"outputs": []
|
| 69 |
+
},
|
| 70 |
+
{
|
| 71 |
+
"cell_type": "code",
|
| 72 |
+
"source": [
|
| 73 |
+
"kwargs = {\n",
|
| 74 |
+
" \"device_map\": \"auto\",\n",
|
| 75 |
+
"} if quantize else {}"
|
| 76 |
+
],
|
| 77 |
+
"metadata": {
|
| 78 |
+
"id": "VAF5sR9arYzS"
|
| 79 |
+
},
|
| 80 |
+
"execution_count": null,
|
| 81 |
+
"outputs": []
|
| 82 |
+
},
|
| 83 |
+
{
|
| 84 |
+
"cell_type": "code",
|
| 85 |
+
"source": [
|
| 86 |
+
"##%%\n",
|
| 87 |
+
"gen_model = AutoModelForCausalLM.from_pretrained(gen_model_checkpoint, **kwargs)\n",
|
| 88 |
+
"tokenizer = AutoTokenizer.from_pretrained(gen_model_checkpoint, **kwargs)"
|
| 89 |
+
],
|
| 90 |
+
"metadata": {
|
| 91 |
+
"id": "tzqldl8ooRVL"
|
| 92 |
+
},
|
| 93 |
+
"execution_count": null,
|
| 94 |
+
"outputs": []
|
| 95 |
+
},
|
| 96 |
+
{
|
| 97 |
+
"cell_type": "code",
|
| 98 |
+
"source": [
|
| 99 |
+
"gen_model.device"
|
| 100 |
+
],
|
| 101 |
+
"metadata": {
|
| 102 |
+
"id": "FeBUXdkWsWrL"
|
| 103 |
+
},
|
| 104 |
+
"execution_count": null,
|
| 105 |
+
"outputs": []
|
| 106 |
+
},
|
| 107 |
+
{
|
| 108 |
+
"cell_type": "code",
|
| 109 |
+
"source": [
|
| 110 |
+
"def get_gemma_response(text):\n",
|
| 111 |
+
" # global gen_model, tokenizer\n",
|
| 112 |
+
" messages = [\n",
|
| 113 |
+
" {\"role\": \"user\", \"content\": text},\n",
|
| 114 |
+
" ]\n",
|
| 115 |
+
"\n",
|
| 116 |
+
" input_ids = tokenizer.apply_chat_template(\n",
|
| 117 |
+
" messages,\n",
|
| 118 |
+
" add_generation_prompt=True,\n",
|
| 119 |
+
" return_tensors=\"pt\"\n",
|
| 120 |
+
" ).to(gen_model.device)\n",
|
| 121 |
+
"\n",
|
| 122 |
+
" terminators = [\n",
|
| 123 |
+
" tokenizer.eos_token_id,\n",
|
| 124 |
+
" tokenizer.convert_tokens_to_ids(\"<|eot_id|>\")\n",
|
| 125 |
+
" ]\n",
|
| 126 |
+
"\n",
|
| 127 |
+
" outputs = gen_model.generate(\n",
|
| 128 |
+
" input_ids,\n",
|
| 129 |
+
" max_new_tokens=100,\n",
|
| 130 |
+
" eos_token_id=terminators,\n",
|
| 131 |
+
" do_sample=True,\n",
|
| 132 |
+
" temperature=0.2,\n",
|
| 133 |
+
" top_p=1\n",
|
| 134 |
+
" )\n",
|
| 135 |
+
"\n",
|
| 136 |
+
" response = outputs[0][input_ids.shape[-1]:]\n",
|
| 137 |
+
" return tokenizer.decode(response, skip_special_tokens=True)"
|
| 138 |
+
],
|
| 139 |
+
"metadata": {
|
| 140 |
+
"id": "R5D4K-P2sPaj"
|
| 141 |
+
},
|
| 142 |
+
"execution_count": null,
|
| 143 |
+
"outputs": []
|
| 144 |
+
},
|
| 145 |
+
{
|
| 146 |
+
"cell_type": "code",
|
| 147 |
+
"source": [
|
| 148 |
+
"text = \\\n",
|
| 149 |
+
"\"\"\"\n",
|
| 150 |
+
"Given a set of rules to calculate point, sort the set of words in decreasing order.\n",
|
| 151 |
+
"When there 2 or more words with same point, sort lexicographically.\n",
|
| 152 |
+
"\n",
|
| 153 |
+
"Rules:\n",
|
| 154 |
+
"- every pair of consecutive consonant gets 5 points\n",
|
| 155 |
+
"- every pair of consecutive vowel gets 3 points\n",
|
| 156 |
+
"- add 1 point if there exists exactly 1 'g' in the word\n",
|
| 157 |
+
"- word less than 5 characters gets 10 points\n",
|
| 158 |
+
"- word starts with gen gets 100 points\n",
|
| 159 |
+
"- word ends with ta gets -1000 point\n",
|
| 160 |
+
"\n",
|
| 161 |
+
"Words:\n",
|
| 162 |
+
"- genta\n",
|
| 163 |
+
"- winata\n",
|
| 164 |
+
"- hudi\n",
|
| 165 |
+
"- alham\n",
|
| 166 |
+
"- aji\n",
|
| 167 |
+
"- ruochen\n",
|
| 168 |
+
"\n",
|
| 169 |
+
"Print only the answer.\n",
|
| 170 |
+
"\"\"\"\n",
|
| 171 |
+
"\n",
|
| 172 |
+
"# Answer:\n",
|
| 173 |
+
"# - aji 10\n",
|
| 174 |
+
"# - hudi 10\n",
|
| 175 |
+
"# - ruochen 5 3\n",
|
| 176 |
+
"# - alham 5\n",
|
| 177 |
+
"# - genta 5 1 100 -1000\n",
|
| 178 |
+
"# - winata -1000"
|
| 179 |
+
],
|
| 180 |
+
"metadata": {
|
| 181 |
+
"id": "T_tk4hTGsxsR"
|
| 182 |
+
},
|
| 183 |
+
"execution_count": null,
|
| 184 |
+
"outputs": []
|
| 185 |
+
},
|
| 186 |
+
{
|
| 187 |
+
"cell_type": "code",
|
| 188 |
+
"source": [
|
| 189 |
+
"print(get_gemma_response(text))"
|
| 190 |
+
],
|
| 191 |
+
"metadata": {
|
| 192 |
+
"id": "05OI36v6vGoY"
|
| 193 |
+
},
|
| 194 |
+
"execution_count": null,
|
| 195 |
+
"outputs": []
|
| 196 |
+
},
|
| 197 |
+
{
|
| 198 |
+
"cell_type": "code",
|
| 199 |
+
"source": [
|
| 200 |
+
"print(get_gemma_response(text))"
|
| 201 |
+
],
|
| 202 |
+
"metadata": {
|
| 203 |
+
"id": "riwXqTc-tmNr"
|
| 204 |
+
},
|
| 205 |
+
"execution_count": null,
|
| 206 |
+
"outputs": []
|
| 207 |
+
},
|
| 208 |
+
{
|
| 209 |
+
"cell_type": "code",
|
| 210 |
+
"source": [],
|
| 211 |
+
"metadata": {
|
| 212 |
+
"id": "T72sUG4_vYUa"
|
| 213 |
+
},
|
| 214 |
+
"execution_count": null,
|
| 215 |
+
"outputs": []
|
| 216 |
+
}
|
| 217 |
+
]
|
| 218 |
+
}
|
__init__.py
ADDED
|
File without changes
|
agent.py
ADDED
|
File without changes
|
environment.yml
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# conda env create -f <this_file>
|
| 2 |
+
name: textgame
|
| 3 |
+
channels:
|
| 4 |
+
- conda-forge
|
| 5 |
+
dependencies:
|
| 6 |
+
- python=3.11
|
| 7 |
+
- pip
|
| 8 |
+
- pip:
|
| 9 |
+
- -r requirements.txt
|
gdrive_try.ipynb
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"provenance":[]},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"code","source":["# %load_ext autoreload\n","# %autoreload 2"],"metadata":{"id":"mAaspsfqKYkA"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["# %load_ext gradio"],"metadata":{"id":"8fBrlr18CB3F"},"execution_count":null,"outputs":[]},{"cell_type":"code","execution_count":null,"metadata":{"id":"6l8QdIpAB5j_"},"outputs":[],"source":["# %%blocks\n","\n","# from play_gradio import demo"]},{"cell_type":"markdown","source":["---"],"metadata":{"id":"2KNPZna6wl7f"}},{"cell_type":"code","source":["# !pip install -U google-api-python-client google-auth-httplib2 google-auth-oauthlib"],"metadata":{"id":"ExtfLnlMprwD"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["import os.path\n","\n","from google.auth.transport.requests import Request\n","from google.oauth2.credentials import Credentials\n","from google_auth_oauthlib.flow import InstalledAppFlow\n","from googleapiclient.discovery import build\n","from googleapiclient.errors import HttpError"],"metadata":{"id":"ADy9dN7bo_TC"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["# If modifying these scopes, delete the file token.json.\n","SCOPES = [\"https://www.googleapis.com/auth/drive.metadata.readonly\"]"],"metadata":{"id":"-1BrLvGaWxZ2"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["def main():\n"," \"\"\"Shows basic usage of the Drive v3 API.\n"," Prints the names and ids of the first 10 files the user has access to.\n"," \"\"\"\n"," creds = None\n"," # The file token.json stores the user's access and refresh tokens, and is\n"," # created automatically when the authorization flow completes for the first\n"," # time.\n"," if os.path.exists(\"token.json\"):\n"," creds = Credentials.from_authorized_user_file(\"token.json\", SCOPES)\n"," # If there are no (valid) credentials available, let the user log in.\n"," if not creds or not creds.valid:\n"," if creds and creds.expired and creds.refresh_token:\n"," creds.refresh(Request())\n"," else:\n"," flow = InstalledAppFlow.from_client_secrets_file(\n"," \"credentials.json\", SCOPES\n"," )\n"," creds = flow.run_local_server(port=0)\n"," # Save the credentials for the next run\n"," with open(\"token.json\", \"w\") as token:\n"," token.write(creds.to_json())\n","\n"," try:\n"," service = build(\"drive\", \"v3\", credentials=creds)\n","\n"," # Call the Drive v3 API\n"," results = (\n"," service.files()\n"," .list(pageSize=10, fields=\"nextPageToken, files(id, name)\")\n"," .execute()\n"," )\n"," items = results.get(\"files\", [])\n","\n"," if not items:\n"," print(\"No files found.\")\n"," return\n"," print(\"Files:\")\n"," for item in items:\n"," print(f\"{item['name']} ({item['id']})\")\n"," except HttpError as error:\n"," # TODO(developer) - Handle errors from drive API.\n"," print(f\"An error occurred: {error}\")"],"metadata":{"id":"-qwFweRKqBZ0"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["main()"],"metadata":{"id":"x62A2GyFqH19"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["if __name__ == \"__main__\":\n"," main()"],"metadata":{"id":"6mwHQ-vFqF-y"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":[],"metadata":{"id":"xqVim7U8qBRn"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":[],"metadata":{"id":"KrIr5DqVwFPR"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["import google.auth\n","from googleapiclient.discovery import build\n","from googleapiclient.errors import HttpError\n","from googleapiclient.http import MediaFileUpload"],"metadata":{"id":"bKn3EWoHtIw3"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["creds, _ = google.auth.default()"],"metadata":{"id":"siH9BRzptIhS"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["creds"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"Bhz_xW99tLDS","executionInfo":{"status":"ok","timestamp":1736790633770,"user_tz":-540,"elapsed":8,"user":{"displayName":"Frederikus Hudi","userId":"06823040510862360282"}},"outputId":"3271b64c-82cd-466f-8321-b5d0ddc884d6"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["<google.oauth2.service_account.Credentials at 0x108b81d90>"]},"metadata":{},"execution_count":3}]},{"cell_type":"code","source":["service = build(\"drive\", \"v3\", credentials=creds)"],"metadata":{"id":"Z3UPsS57tIaP"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["service"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"FhPuaL29ziYw","executionInfo":{"status":"ok","timestamp":1736791252169,"user_tz":-540,"elapsed":9,"user":{"displayName":"Frederikus Hudi","userId":"06823040510862360282"}},"outputId":"66e7a320-3133-4647-9a73-94b4f65ca898"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["<googleapiclient.discovery.Resource at 0x108b8f550>"]},"metadata":{},"execution_count":11}]},{"cell_type":"code","source":["file_metadata = {\"name\": \"wow.txt\"}\n","media = MediaFileUpload(\"wow.txt\")"],"metadata":{"id":"sckvnGYtqBKw"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["media"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"xjvE-Mva03L0","executionInfo":{"status":"ok","timestamp":1736791259359,"user_tz":-540,"elapsed":9,"user":{"displayName":"Frederikus Hudi","userId":"06823040510862360282"}},"outputId":"5eac30fc-1da6-48c3-93ca-40e0174d1816"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["<googleapiclient.http.MediaFileUpload at 0x108c223d0>"]},"metadata":{},"execution_count":12}]},{"cell_type":"code","source":["dir(media)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"qK-N7udo7u1i","executionInfo":{"status":"ok","timestamp":1736793093612,"user_tz":-540,"elapsed":27,"user":{"displayName":"Frederikus Hudi","userId":"06823040510862360282"}},"outputId":"a961fd11-4fae-4473-94ab-9bc775a6335e"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["['__class__',\n"," '__del__',\n"," '__delattr__',\n"," '__dict__',\n"," '__dir__',\n"," '__doc__',\n"," '__eq__',\n"," '__format__',\n"," '__ge__',\n"," '__getattribute__',\n"," '__getstate__',\n"," '__gt__',\n"," '__hash__',\n"," '__init__',\n"," '__init_subclass__',\n"," '__le__',\n"," '__lt__',\n"," '__module__',\n"," '__ne__',\n"," '__new__',\n"," '__reduce__',\n"," '__reduce_ex__',\n"," '__repr__',\n"," '__setattr__',\n"," '__sizeof__',\n"," '__str__',\n"," '__subclasshook__',\n"," '__weakref__',\n"," '_chunksize',\n"," '_fd',\n"," '_filename',\n"," '_mimetype',\n"," '_resumable',\n"," '_size',\n"," '_to_json',\n"," 'chunksize',\n"," 'from_json',\n"," 'getbytes',\n"," 'has_stream',\n"," 'mimetype',\n"," 'new_from_json',\n"," 'resumable',\n"," 'size',\n"," 'stream',\n"," 'to_json']"]},"metadata":{},"execution_count":49}]},{"cell_type":"code","source":["f = (\n"," service.files()\n"," .create(body=file_metadata, media_body=media, fields=\"id\")\n"," .execute()\n"," )\n","print(f'File ID: {file.get(\"id\")}')"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"HipJX087zir2","executionInfo":{"status":"ok","timestamp":1736792615979,"user_tz":-540,"elapsed":2189,"user":{"displayName":"Frederikus Hudi","userId":"06823040510862360282"}},"outputId":"19a11b14-cc18-455a-a4f1-d1a69f69c72f"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["File ID: 1Rnx0_wttlDG8XiyA_44yHBJeQBHvR_xh\n"]}]},{"cell_type":"code","source":["f.get(\"id\"), type(f)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"GoMMo7qX5-OH","executionInfo":{"status":"ok","timestamp":1736792629838,"user_tz":-540,"elapsed":10,"user":{"displayName":"Frederikus Hudi","userId":"06823040510862360282"}},"outputId":"ade9f343-a514-4e61-97f9-2550ed55223c"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["('1rE4uYBWAQBFVVB6m7jGqAJncIohTJrWp', dict)"]},"metadata":{},"execution_count":22}]},{"cell_type":"code","source":["f = file.get(\"id\")"],"metadata":{"id":"usWmDGQjzijj"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["f"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"PFCzbG0v0nZ-","executionInfo":{"status":"ok","timestamp":1736791193891,"user_tz":-540,"elapsed":4,"user":{"displayName":"Frederikus Hudi","userId":"06823040510862360282"}},"outputId":"9c8456bd-9996-40a4-e3e6-1e3eb0aafbe9"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["'1Rnx0_wttlDG8XiyA_44yHBJeQBHvR_xh'"]},"metadata":{},"execution_count":9}]},{"cell_type":"code","source":["files = service.files()"],"metadata":{"id":"oh18pUBj3Hn4"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["dir(service)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"LRsVc6pQ6c_1","executionInfo":{"status":"ok","timestamp":1736792725586,"user_tz":-540,"elapsed":4,"user":{"displayName":"Frederikus Hudi","userId":"06823040510862360282"}},"outputId":"c9ba40eb-f159-4f05-f5b1-53e5e81916da"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["['__class__',\n"," '__delattr__',\n"," '__dict__',\n"," '__dir__',\n"," '__doc__',\n"," '__enter__',\n"," '__eq__',\n"," '__exit__',\n"," '__format__',\n"," '__ge__',\n"," '__getattribute__',\n"," '__getstate__',\n"," '__gt__',\n"," '__hash__',\n"," '__init__',\n"," '__init_subclass__',\n"," '__le__',\n"," '__lt__',\n"," '__module__',\n"," '__ne__',\n"," '__new__',\n"," '__reduce__',\n"," '__reduce_ex__',\n"," '__repr__',\n"," '__setattr__',\n"," '__setstate__',\n"," '__sizeof__',\n"," '__str__',\n"," '__subclasshook__',\n"," '__weakref__',\n"," '_add_basic_methods',\n"," '_add_nested_resources',\n"," '_add_next_methods',\n"," '_baseUrl',\n"," '_credentials_validated',\n"," '_developerKey',\n"," '_dynamic_attrs',\n"," '_http',\n"," '_model',\n"," '_requestBuilder',\n"," '_resourceDesc',\n"," '_rootDesc',\n"," '_schema',\n"," '_set_dynamic_attr',\n"," '_set_service_methods',\n"," '_universe_domain',\n"," '_validate_credentials',\n"," 'about',\n"," 'accessproposals',\n"," 'apps',\n"," 'changes',\n"," 'channels',\n"," 'close',\n"," 'comments',\n"," 'drives',\n"," 'files',\n"," 'new_batch_http_request',\n"," 'operation',\n"," 'operations',\n"," 'permissions',\n"," 'replies',\n"," 'revisions',\n"," 'teamdrives']"]},"metadata":{},"execution_count":31}]},{"cell_type":"code","source":["dir(service.files())"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"40nai28V7Q9B","executionInfo":{"status":"ok","timestamp":1736792941319,"user_tz":-540,"elapsed":14,"user":{"displayName":"Frederikus Hudi","userId":"06823040510862360282"}},"outputId":"4e9488bc-9370-44a3-c5cc-8d009630dc2c"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["['__class__',\n"," '__delattr__',\n"," '__dict__',\n"," '__dir__',\n"," '__doc__',\n"," '__enter__',\n"," '__eq__',\n"," '__exit__',\n"," '__format__',\n"," '__ge__',\n"," '__getattribute__',\n"," '__getstate__',\n"," '__gt__',\n"," '__hash__',\n"," '__init__',\n"," '__init_subclass__',\n"," '__le__',\n"," '__lt__',\n"," '__module__',\n"," '__ne__',\n"," '__new__',\n"," '__reduce__',\n"," '__reduce_ex__',\n"," '__repr__',\n"," '__setattr__',\n"," '__setstate__',\n"," '__sizeof__',\n"," '__str__',\n"," '__subclasshook__',\n"," '__weakref__',\n"," '_add_basic_methods',\n"," '_add_nested_resources',\n"," '_add_next_methods',\n"," '_baseUrl',\n"," '_credentials_validated',\n"," '_developerKey',\n"," '_dynamic_attrs',\n"," '_http',\n"," '_model',\n"," '_requestBuilder',\n"," '_resourceDesc',\n"," '_rootDesc',\n"," '_schema',\n"," '_set_dynamic_attr',\n"," '_set_service_methods',\n"," '_universe_domain',\n"," '_validate_credentials',\n"," 'close',\n"," 'copy',\n"," 'create',\n"," 'delete',\n"," 'download',\n"," 'emptyTrash',\n"," 'export',\n"," 'export_media',\n"," 'generateIds',\n"," 'get',\n"," 'get_media',\n"," 'list',\n"," 'listLabels',\n"," 'listLabels_next',\n"," 'list_next',\n"," 'modifyLabels',\n"," 'update',\n"," 'watch']"]},"metadata":{},"execution_count":34}]},{"cell_type":"code","source":["files.delete(fileId=\"1Rnx0_wttlDG8XiyA_44yHBJeQBHvR_xh\").execute()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"9zlanjZ96Yz9","executionInfo":{"status":"ok","timestamp":1736793000575,"user_tz":-540,"elapsed":896,"user":{"displayName":"Frederikus Hudi","userId":"06823040510862360282"}},"outputId":"d6ed9310-2efb-48d1-90e5-d5b0bd9536f6"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["''"]},"metadata":{},"execution_count":40}]},{"cell_type":"code","source":["files.list().execute()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"4guAyYqt7ehH","executionInfo":{"status":"ok","timestamp":1736793001570,"user_tz":-540,"elapsed":441,"user":{"displayName":"Frederikus Hudi","userId":"06823040510862360282"}},"outputId":"d96fe0c6-71b7-4bc3-8add-afbff7bbb054"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":["{'kind': 'drive#fileList',\n"," 'incompleteSearch': False,\n"," 'files': [{'kind': 'drive#file',\n"," 'mimeType': 'application/vnd.google-apps.folder',\n"," 'id': '1qStKuVerAQPsXagngfzlNg8PdAR5hupA',\n"," 'name': 'afureteshimau'}]}"]},"metadata":{},"execution_count":41}]},{"cell_type":"code","source":["ret = (\n"," files\n"," .create(body=, media_body=media)\n"," .execute()\n",")"],"metadata":{"id":"qS4ithoH7lBq"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["results = (\n"," service.files()\n"," .list(pageSize=10, fields=\"nextPageToken, files(id, name)\")\n"," .execute()\n"," )"],"metadata":{"id":"DJQwlCAq1IDz"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["results.get(\"files\", [])"],"metadata":{"id":"kKSZI82R1J2s"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":[],"metadata":{"id":"qED1Eo_zKI4o"},"execution_count":null,"outputs":[]}]}
|
generate.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import random
|
| 3 |
+
import numpy as np
|
| 4 |
+
import torch
|
| 5 |
+
import json
|
| 6 |
+
|
| 7 |
+
from tqdm import tqdm
|
| 8 |
+
from pathlib import Path
|
| 9 |
+
from textgames import GAME_NAMES, LEVEL_IDS, new_game, game_filename
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def set_seed(seed):
|
| 13 |
+
random.seed(seed)
|
| 14 |
+
np.random.seed(seed)
|
| 15 |
+
torch.manual_seed(seed)
|
| 16 |
+
torch.cuda.manual_seed(seed)
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
#generate()
|
| 20 |
+
if __name__ == '__main__':
|
| 21 |
+
outdir = Path(os.getenv("TEXTGAMES_LOADGAME_DIR", "problemsets"))
|
| 22 |
+
# os.system(f"rm -rfd {outdir}")
|
| 23 |
+
os.makedirs(outdir, exist_ok=False) # exists_ok is set to False, making sure regeneration.
|
| 24 |
+
set_seed(42)
|
| 25 |
+
|
| 26 |
+
# level_ids = LEVEL_IDS
|
| 27 |
+
level_ids = ["1", "2", "3"]
|
| 28 |
+
session_ids = [
|
| 29 |
+
f"session_{sid:04}" for sid in range(os.getenv("TEXTGAMES_GENERATE_N", 1000))
|
| 30 |
+
]
|
| 31 |
+
|
| 32 |
+
count_duplicate = 0
|
| 33 |
+
for game_name in GAME_NAMES:
|
| 34 |
+
prompts_map = dict()
|
| 35 |
+
for level_id in level_ids:
|
| 36 |
+
os.environ["TEXTGAMES_NEWGAME_ERRFILE"] = f"{outdir}/{game_filename(game_name)}_{level_id}.err"
|
| 37 |
+
for sid in tqdm(session_ids, desc=f"{game_name}_{level_id}"):
|
| 38 |
+
while True:
|
| 39 |
+
cur_game = new_game(game_name, level_id)
|
| 40 |
+
prompt = cur_game._get_prompt()
|
| 41 |
+
if prompt not in prompts_map:
|
| 42 |
+
break
|
| 43 |
+
count_duplicate += 1
|
| 44 |
+
prompts_map[prompt] = sid
|
| 45 |
+
print(f"[{game_name}_{level_id}] Duplicate #: {count_duplicate:-4}")
|
| 46 |
+
|
| 47 |
+
json_object = json.dumps({sid: prompt for prompt, sid in prompts_map.items()}, indent=4)
|
| 48 |
+
with open(outdir / f"{game_filename(game_name)}_{level_id}.json", "w") as outfile:
|
| 49 |
+
outfile.write(json_object)
|
| 50 |
+
|
| 51 |
+
print(f"duplicates:{count_duplicate}")
|
model_outputs/results_batch_api_openai_gpt-4o-mini-2024-07-18.jsonl
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
oauth_environ_google.sh
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
export $(cat oauth_environ_google.env | xargs)
|
play.py
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from termcolor import colored
|
| 2 |
+
from textgames import GAME_IDS, GAME_NAMES, LEVEL_IDS, LEVELS, new_game, LEVELS_HIDDEN, SINGLE_LINE_GAME_IDS
|
| 3 |
+
|
| 4 |
+
import os
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
def print_text_green(string):
|
| 8 |
+
print(colored(string, "light_green"))
|
| 9 |
+
|
| 10 |
+
def print_text_cyan(string):
|
| 11 |
+
print(colored(string, "cyan"))
|
| 12 |
+
|
| 13 |
+
def print_text_white(string):
|
| 14 |
+
print(colored(string, "white"))
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
if __name__ == "__main__":
|
| 18 |
+
print_text_green("#" * 20)
|
| 19 |
+
print_text_cyan(" Welcome to")
|
| 20 |
+
print(" 🎮 " + colored("Text", "white")+ colored("Games", "yellow"))
|
| 21 |
+
print_text_green("#" * 20)
|
| 22 |
+
print_text_green("Games:")
|
| 23 |
+
for i, game_name in zip(range(len(GAME_NAMES)), GAME_NAMES):
|
| 24 |
+
print_text_green(f"{i+1}. {game_name}")
|
| 25 |
+
print_text_green("#" * 20)
|
| 26 |
+
|
| 27 |
+
cur_game_id = os.getenv("GAME_ID", None)
|
| 28 |
+
difficulty_level = os.getenv("GAME_LEVEL", None)
|
| 29 |
+
while cur_game_id is None:
|
| 30 |
+
user_input = str(input(f"Choose the game> "))
|
| 31 |
+
|
| 32 |
+
if user_input in GAME_IDS:
|
| 33 |
+
cur_game_id = user_input
|
| 34 |
+
|
| 35 |
+
print_text_green("#" * 20)
|
| 36 |
+
print_text_green("Difficulty Levels:")
|
| 37 |
+
for i, l in zip(LEVEL_IDS, LEVELS):
|
| 38 |
+
print_text_green(f"{i}. {l}")
|
| 39 |
+
print_text_green("#" * 20)
|
| 40 |
+
|
| 41 |
+
while difficulty_level is None:
|
| 42 |
+
user_input = str(input(f"Choose the difficulty level> "))
|
| 43 |
+
if user_input in LEVEL_IDS:
|
| 44 |
+
difficulty_level = user_input
|
| 45 |
+
else:
|
| 46 |
+
print("The difficulty level option is not available.")
|
| 47 |
+
else:
|
| 48 |
+
arr = user_input.split("-")
|
| 49 |
+
if len(arr) == 2 and isinstance(arr[0], str) and isinstance(arr[1], str):
|
| 50 |
+
if arr[0] in GAME_IDS and arr[1] in LEVEL_IDS:
|
| 51 |
+
cur_game_id = arr[0]
|
| 52 |
+
difficulty_level = arr[1]
|
| 53 |
+
else:
|
| 54 |
+
print("The game option is not available.")
|
| 55 |
+
cur_game = None
|
| 56 |
+
|
| 57 |
+
this_game_name = GAME_NAMES[GAME_IDS.index(cur_game_id)]
|
| 58 |
+
this_difficulty_level = (LEVELS + LEVELS_HIDDEN)[LEVEL_IDS.index(difficulty_level)].replace("\t", " ")
|
| 59 |
+
print_text_green(f"Game chosen: {this_game_name} and Difficulty Level: {this_difficulty_level}")
|
| 60 |
+
|
| 61 |
+
solved = False
|
| 62 |
+
cur_game = new_game(this_game_name, difficulty_level)
|
| 63 |
+
print(colored("######## Game Start !! ########", "light_green"))
|
| 64 |
+
print(cur_game.get_prompt())
|
| 65 |
+
while not solved:
|
| 66 |
+
contents = []
|
| 67 |
+
while True:
|
| 68 |
+
try:
|
| 69 |
+
line = str(input("\t" if contents else f"Guess>\t"))
|
| 70 |
+
# automatic break for some games:
|
| 71 |
+
if cur_game_id in SINGLE_LINE_GAME_IDS:
|
| 72 |
+
contents.append(line)
|
| 73 |
+
break
|
| 74 |
+
if len(line) == 0:
|
| 75 |
+
break
|
| 76 |
+
except EOFError:
|
| 77 |
+
break
|
| 78 |
+
contents.append(line)
|
| 79 |
+
|
| 80 |
+
user_input = '\n'.join(contents)
|
| 81 |
+
solved, val_msg = cur_game.validate(user_input)
|
| 82 |
+
if val_msg:
|
| 83 |
+
print(val_msg)
|
| 84 |
+
print(f"Attempt #{len(cur_game.attempt_timestamps)}:", "Correct guess" if solved else "Bad guess", end="\n\n")
|
| 85 |
+
|
| 86 |
+
print(f"Time to solve: {round(cur_game.attempt_timestamps[-1] - cur_game.start_timestamp, 1)}s")
|
| 87 |
+
print("Thank you for playing!")
|
| 88 |
+
|
| 89 |
+
|
play.sh
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cur_datetime="$(date '+%Y%m%d_%H%M%S')";
|
| 2 |
+
echo "Current Time: ${cur_datetime}";
|
| 3 |
+
python -u play_gradio.py | tee "log/run_${cur_datetime}.log"
|
play_gradio.py
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#%%
|
| 2 |
+
import os
|
| 3 |
+
# os.environ.setdefault("GRADIO_SERVER_PORT", "1080")
|
| 4 |
+
# os.environ.setdefault("TEXTGAMES_SHOW_HIDDEN_LEVEL", "1")
|
| 5 |
+
os.environ.setdefault("TEXTGAMES_LOADGAME_DIR", "problemsets")
|
| 6 |
+
os.environ.setdefault("TEXTGAMES_LOADGAME_ID", "42")
|
| 7 |
+
os.environ.setdefault("TEXTGAMES_MOCKUSER", "")
|
| 8 |
+
os.environ.setdefault("TEXTGAMES_OUTPUT_DIR", "user_outputs")
|
| 9 |
+
favicon_path = "textgames-scrabble-black2-ss.png"
|
| 10 |
+
|
| 11 |
+
#%%
|
| 12 |
+
from play_helper import css, declare_components, start_new_game, download_from_drive
|
| 13 |
+
import pandas as pd
|
| 14 |
+
import gradio as gr
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
#%%
|
| 18 |
+
fp_user_auth = f"{os.getenv('TEXTGAMES_OUTPUT_DIR')}/textgames_userauth.tsv"
|
| 19 |
+
# fp_user_auth_id = "13RLyxV3ys5DGgRIJt5_tO-ILllJ1LDPGasobagZyVLU"
|
| 20 |
+
fp_user_auth_mime_type = "text/tab-separated-values"
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
#%%
|
| 24 |
+
def file_based_auth(username, password):
|
| 25 |
+
if os.getenv('TEXTGAMES_MOCKUSER', ''):
|
| 26 |
+
return True
|
| 27 |
+
download_from_drive(fp_user_auth, mime_type=fp_user_auth_mime_type)
|
| 28 |
+
df_auth = pd.read_csv(fp_user_auth, sep="\t").dropna(how="any")
|
| 29 |
+
return len(df_auth.loc[(df_auth.EMAIL == username) & (df_auth.PASSWORD == password)]) > 0
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
#%%
|
| 33 |
+
def greet(request: gr.Request):
|
| 34 |
+
email = os.getenv('TEXTGAMES_MOCKUSER', '')
|
| 35 |
+
if email:
|
| 36 |
+
user = {'email': email, 'name': "mockuser"}
|
| 37 |
+
else:
|
| 38 |
+
df_auth = pd.read_csv(fp_user_auth, sep="\t").dropna(how="any").drop_duplicates(subset=['EMAIL'])
|
| 39 |
+
r = df_auth.loc[df_auth.EMAIL == request.username].iloc[0]
|
| 40 |
+
user = {'email': r.EMAIL, 'name': r.NAME}
|
| 41 |
+
return f"""
|
| 42 |
+
Welcome to TextGames, {user['name']}!<br/><{user['email'].replace('@', '{at}')}>
|
| 43 |
+
""", user, user['email']
|
| 44 |
+
|
| 45 |
+
# return f"""
|
| 46 |
+
# Welcome to TextGames, {user['name']}!<br />
|
| 47 |
+
# <{user['email'].replace('@', '{at}')}> ({'' if user['email_verified'] else 'NON-'}verified email)
|
| 48 |
+
# """, None, None
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
#%%
|
| 52 |
+
with gr.Blocks(title="TextGames", css=css, delete_cache=(3600, 3600)) as demo:
|
| 53 |
+
((m, logout_btn, solved_games_df, game_radio, level_radio, new_game_btn, render_toggle),
|
| 54 |
+
(session_state, is_solved, solved_games, user_state, uid_state),
|
| 55 |
+
) = declare_components(demo, greet)
|
| 56 |
+
|
| 57 |
+
@gr.render(inputs=[game_radio, level_radio, user_state, session_state, uid_state], triggers=[render_toggle.change])
|
| 58 |
+
def _start_new_game(game_name, level, user, _session_state, _uid_state):
|
| 59 |
+
if _session_state in [1, 2]:
|
| 60 |
+
start_new_game(game_name, level, session_state, is_solved, solved_games, user=user, uid=_uid_state)
|
| 61 |
+
|
| 62 |
+
demo.launch(
|
| 63 |
+
auth=file_based_auth,
|
| 64 |
+
favicon_path=favicon_path if os.path.exists(favicon_path) else None,
|
| 65 |
+
share=True,
|
| 66 |
+
)
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
#%%
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
#%%
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
#%%
|
| 76 |
+
|
| 77 |
+
|
play_helper.py
CHANGED
|
@@ -3,11 +3,8 @@ import os
|
|
| 3 |
import time
|
| 4 |
import pandas as pd
|
| 5 |
import gradio as gr
|
| 6 |
-
|
| 7 |
-
import
|
| 8 |
-
from googleapiclient.discovery import build
|
| 9 |
-
from googleapiclient.errors import HttpError
|
| 10 |
-
from googleapiclient.http import MediaFileUpload
|
| 11 |
|
| 12 |
from textgames import GAME_NAMES, LEVEL_IDS, LEVELS, new_game, preload_game, game_filename
|
| 13 |
from textgames.islands.islands import Islands
|
|
@@ -17,7 +14,14 @@ from textgames.ordering_text.ordering_text import OrderingTextGame
|
|
| 17 |
|
| 18 |
|
| 19 |
# %%
|
| 20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
with gr.Row():
|
| 22 |
with gr.Column(scale=1):
|
| 23 |
m = gr.Markdown("Welcome to TextGames!", elem_id="md-greeting")
|
|
@@ -29,10 +33,44 @@ def declare_components():
|
|
| 29 |
level_radio = gr.Radio(LEVELS, label="Level", elem_id="radio-level-name")
|
| 30 |
new_game_btn = gr.Button("Start Game", elem_id="btn-start-game")
|
| 31 |
render_toggle = gr.Checkbox(False, visible=False, interactive=False)
|
| 32 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
|
| 34 |
|
| 35 |
# %%
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
_creds_dict = {
|
| 37 |
"type": "service_account",
|
| 38 |
"project_id": os.getenv("GOOGLE_AUTH_CREDS_PROJECT_ID", ""),
|
|
@@ -51,6 +89,14 @@ _service = build("drive", "v3", credentials=_creds)
|
|
| 51 |
_files = _service.files()
|
| 52 |
|
| 53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
# %%
|
| 55 |
js_remove_input_helper = """(s) => {
|
| 56 |
var el = document.getElementById('lintao-container');
|
|
@@ -84,9 +130,10 @@ function island() {{
|
|
| 84 |
container.style.display = 'grid';
|
| 85 |
container.style.gridTemplateColumns = container.style.gridTemplateRows = `repeat(${{grid_N}}, ${{grid_px}}px)`;
|
| 86 |
container.style.gap = '1px';
|
| 87 |
-
container.style.border = '2px solid
|
| 88 |
container.style.width = 'max-content';
|
| 89 |
container.style.margin = '5px 0px 5px 40px';
|
|
|
|
| 90 |
container.id = 'lintao-container';
|
| 91 |
|
| 92 |
for (let i = 0; i < grid_N; ++i) {{
|
|
@@ -98,7 +145,7 @@ function island() {{
|
|
| 98 |
cell.style.alignItems = 'center';
|
| 99 |
cell.style.justifyContent = 'center';
|
| 100 |
cell.style.fontSize = `${{grid_px/2}}px`;
|
| 101 |
-
cell.style.border = '1px solid
|
| 102 |
cell.style.cursor = 'pointer';
|
| 103 |
cell.id = `lintao-cell-${{i}}-${{j}}`;
|
| 104 |
|
|
@@ -130,6 +177,8 @@ function island() {{
|
|
| 130 |
|
| 131 |
js_island_submit = """
|
| 132 |
function island_submit(textarea, io_history) {{
|
|
|
|
|
|
|
| 133 |
const grid_N = {N};
|
| 134 |
var ret = "";
|
| 135 |
for (let i = 0; i < grid_N; ++i) {{
|
|
@@ -149,7 +198,7 @@ function sudoku() {{
|
|
| 149 |
const N = {N};
|
| 150 |
const grid_N = N*N,
|
| 151 |
grid_px = 50,
|
| 152 |
-
border_px =
|
| 153 |
const mat = {mat};
|
| 154 |
|
| 155 |
let is_numeric_sudoku = false;
|
|
@@ -165,16 +214,17 @@ function sudoku() {{
|
|
| 165 |
const container = document.createElement('div');
|
| 166 |
container.style.display = 'grid';
|
| 167 |
container.style.gridTemplateColumns = container.style.gridTemplateRows = `repeat(${{grid_N}}, ${{grid_px}}px)`;
|
| 168 |
-
container.style.
|
| 169 |
-
container.style.border = '${{border_px}}px solid white';
|
| 170 |
container.style.width = 'max-content';
|
| 171 |
container.style.margin = '5px 0px 5px 40px';
|
|
|
|
| 172 |
container.id = 'lintao-container';
|
| 173 |
|
| 174 |
// Generate the grid
|
|
|
|
| 175 |
for (let i = 0; i < grid_N; ++i) {{
|
| 176 |
for (let j = 0; j < grid_N; ++j) {{
|
| 177 |
-
const cell = document.createElement('
|
| 178 |
cell.type = 'text';
|
| 179 |
cell.maxLength = 1;
|
| 180 |
cell.style.width = cell.style.height = `${{grid_px}}px`;
|
|
@@ -183,32 +233,35 @@ function sudoku() {{
|
|
| 183 |
cell.style.justifyContent = 'center';
|
| 184 |
cell.style.textAlign = 'center';
|
| 185 |
cell.style.fontSize = `${{grid_px/2}}px`;
|
| 186 |
-
cell.style.border = '1px solid
|
| 187 |
-
cell.style.
|
| 188 |
-
cell.style.
|
|
|
|
|
|
|
| 189 |
cell.id = `lintao-cell-${{i}}-${{j}}`;
|
| 190 |
|
| 191 |
if (mat[i][j] != '_') {{
|
| 192 |
-
cell.
|
| 193 |
-
cell.style.color = '
|
| 194 |
cell.disabled = true;
|
|
|
|
|
|
|
|
|
|
| 195 |
}}
|
| 196 |
|
| 197 |
-
//cell.style.color = 'black';
|
| 198 |
-
//cell.style.outline = 'none';
|
| 199 |
|
| 200 |
-
if (j % N === 0) cell.style.borderLeft = `${{border_px}}px solid
|
| 201 |
-
if (j % N === (N-1)) cell.style.borderRight = `${{border_px}}px solid
|
| 202 |
-
if (i % N === 0) cell.style.borderTop = `${{border_px}}px solid
|
| 203 |
-
if (i % N === (N-1)) cell.style.borderBottom = `${{border_px}}px solid
|
| 204 |
|
| 205 |
// Allow only numbers 1-9 or A-I
|
| 206 |
cell.addEventListener('input', (e) => {{
|
| 207 |
-
if ((N === 2 && (!(is_numeric_sudoku?/^[1-4]$/:/^[A-Da-d]$/).test(e.target.
|
| 208 |
-
(N === 3 && (!(is_numeric_sudoku?/^[1-9]$/:/^[A-Ia-i]$/).test(e.target.
|
| 209 |
-
e.target.
|
| 210 |
}}
|
| 211 |
-
e.target.
|
| 212 |
}});
|
| 213 |
|
| 214 |
container.appendChild(cell);
|
|
@@ -228,16 +281,16 @@ function sudoku() {{
|
|
| 228 |
const currentCol = i % grid_N;
|
| 229 |
|
| 230 |
if (currentRow === row || currentCol === col || (Math.floor(currentRow / N) === Math.floor(row / N) && Math.floor(currentCol / N) === Math.floor(col / N))) {{
|
| 231 |
-
cell.
|
| 232 |
}} else {{
|
| 233 |
-
cell.
|
| 234 |
}}
|
| 235 |
}}
|
| 236 |
}});
|
| 237 |
|
| 238 |
container.addEventListener('focusout', () => {{
|
| 239 |
for (let i = 0; i < grid_N * grid_N; i++) {{
|
| 240 |
-
container.children[i].
|
| 241 |
}}
|
| 242 |
}});
|
| 243 |
|
|
@@ -248,13 +301,15 @@ function sudoku() {{
|
|
| 248 |
|
| 249 |
js_sudoku_submit = """
|
| 250 |
function sudoku_submit(textarea, io_history) {{
|
|
|
|
|
|
|
| 251 |
const N = {N};
|
| 252 |
const grid_N = N*N;
|
| 253 |
var ret = "";
|
| 254 |
for (let i = 0; i < grid_N; ++i) {{
|
| 255 |
if (i > 0) ret += '\\n';
|
| 256 |
for (let j = 0; j < grid_N; ++j) {{
|
| 257 |
-
ret += document.getElementById(`lintao-cell-${{i}}-${{j}}`).
|
| 258 |
}}
|
| 259 |
}}
|
| 260 |
return [ret, io_history];
|
|
@@ -272,9 +327,10 @@ function crossword() {{
|
|
| 272 |
container.style.display = 'grid';
|
| 273 |
container.style.gridTemplateColumns = container.style.gridTemplateRows = `repeat(${{grid_N}}, ${{grid_px}}px)`;
|
| 274 |
container.style.gap = '1px';
|
| 275 |
-
container.style.border = '2px solid
|
| 276 |
container.style.width = 'max-content';
|
| 277 |
container.style.margin = '5px 0px 5px 40px';
|
|
|
|
| 278 |
container.id = 'lintao-container';
|
| 279 |
|
| 280 |
// Generate the grid
|
|
@@ -290,8 +346,8 @@ function crossword() {{
|
|
| 290 |
cell.style.justifyContent = 'center';
|
| 291 |
cell.style.textAlign = 'center';
|
| 292 |
cell.style.fontSize = `${{grid_px/2}}px`;
|
| 293 |
-
cell.style.border = '1px solid
|
| 294 |
-
cell.style.backgroundColor = '
|
| 295 |
cell.style.cursor = 'pointer';
|
| 296 |
cell.id = `lintao-cell-${{i}}-${{j}}`;
|
| 297 |
|
|
@@ -313,6 +369,8 @@ function crossword() {{
|
|
| 313 |
|
| 314 |
js_crossword_submit = """
|
| 315 |
function crossword_submit(textarea, io_history) {{
|
|
|
|
|
|
|
| 316 |
const grid_N = {N};
|
| 317 |
var ret = "";
|
| 318 |
for (let i = 0; i < grid_N; ++i) {{
|
|
@@ -333,7 +391,7 @@ function ordering() {{
|
|
| 333 |
listContainer.style.listStyle = 'none';
|
| 334 |
listContainer.style.padding = '0';
|
| 335 |
listContainer.style.width = '20em';
|
| 336 |
-
listContainer.style.border = '2px solid
|
| 337 |
listContainer.style.margin = '5px 0px 5px 40px';
|
| 338 |
listContainer.id = 'lintao-container';
|
| 339 |
|
|
@@ -346,9 +404,9 @@ function ordering() {{
|
|
| 346 |
listItem.textContent = itemText;
|
| 347 |
listItem.draggable = true;
|
| 348 |
listItem.style.padding = '10px';
|
| 349 |
-
listItem.style.border = '1px solid
|
| 350 |
listItem.style.margin = '3px';
|
| 351 |
-
listItem.style.backgroundColor = '
|
| 352 |
listItem.style.cursor = 'grab';
|
| 353 |
listItem.id = `lintao-item-${{index}}`;
|
| 354 |
|
|
@@ -356,16 +414,16 @@ function ordering() {{
|
|
| 356 |
listItem.addEventListener('dragstart', (e) => {{
|
| 357 |
const draggedIndex = Array.from(listContainer.children).indexOf(listItem);
|
| 358 |
e.dataTransfer.setData('text/plain', draggedIndex);
|
| 359 |
-
listItem.style.backgroundColor = '
|
| 360 |
}});
|
| 361 |
|
| 362 |
listItem.addEventListener('dragover', (e) => {{
|
| 363 |
e.preventDefault();
|
| 364 |
-
listItem.style.backgroundColor = '
|
| 365 |
}});
|
| 366 |
|
| 367 |
listItem.addEventListener('dragleave', () => {{
|
| 368 |
-
listItem.style.backgroundColor = '
|
| 369 |
}});
|
| 370 |
|
| 371 |
listItem.addEventListener('drop', (e) => {{
|
|
@@ -379,11 +437,11 @@ function ordering() {{
|
|
| 379 |
listContainer.insertBefore(draggedItem, targetIndex > draggedIndex ? listItem.nextSibling : listItem);
|
| 380 |
}}
|
| 381 |
|
| 382 |
-
listItem.style.backgroundColor = '
|
| 383 |
}});
|
| 384 |
|
| 385 |
listItem.addEventListener('dragend', () => {{
|
| 386 |
-
listItem.style.backgroundColor = '
|
| 387 |
}});
|
| 388 |
|
| 389 |
listContainer.appendChild(listItem);
|
|
@@ -396,9 +454,10 @@ function ordering() {{
|
|
| 396 |
|
| 397 |
js_ordering_submit = """
|
| 398 |
function ordering_submit(textarea, io_history) {{
|
|
|
|
|
|
|
| 399 |
var ret = "";
|
| 400 |
-
|
| 401 |
-
document.getElementById("lintao-container").childNodes.forEach(
|
| 402 |
(c, i) => {{
|
| 403 |
if (i>0) ret += '\\n';
|
| 404 |
ret += c.textContent;
|
|
@@ -424,6 +483,68 @@ def _get_file_output(game_name, level_id, fn_prefix):
|
|
| 424 |
return f"{fd}/{fn_prefix}_-_{game_filename(game_name)}_{level_id}.pkl"
|
| 425 |
|
| 426 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 427 |
# %%
|
| 428 |
def start_new_game(game_name, level, session_state_component, is_solved_component, solved_games_component,
|
| 429 |
user=None, show_timer=False, uid=None):
|
|
@@ -441,9 +562,12 @@ def start_new_game(game_name, level, session_state_component, is_solved_componen
|
|
| 441 |
preload_game(game_name, difficulty_level, user)
|
| 442 |
)
|
| 443 |
cur_game.attach_stats_output_(fp_out)
|
| 444 |
-
cur_game.flush_stats_(
|
| 445 |
|
| 446 |
def add_msg(new_msg, prev_msg):
|
|
|
|
|
|
|
|
|
|
| 447 |
user_input = '\n'.join(new_msg.split())
|
| 448 |
solved, val_msg = cur_game.validate(user_input)
|
| 449 |
response = ("Correct guess" if solved else "Bad guess (Wrong Answer)") + "\n" + val_msg
|
|
@@ -455,10 +579,8 @@ def start_new_game(game_name, level, session_state_component, is_solved_componen
|
|
| 455 |
|
| 456 |
gr.Markdown(
|
| 457 |
"""
|
| 458 |
-
> ### ‼️ Do
|
| 459 |
> #### ⚠️ Refreshing the page equals "Give-up 😭" ⚠️
|
| 460 |
-
|
| 461 |
-
|
| 462 |
"""
|
| 463 |
)
|
| 464 |
showhide_helper_btn = gr.Button("Show Input Helper (disabling manual input)", elem_id="lintao-helper-btn")
|
|
@@ -500,48 +622,52 @@ def start_new_game(game_name, level, session_state_component, is_solved_componen
|
|
| 500 |
|
| 501 |
def _forfeiting(confirmed, _solved_games):
|
| 502 |
if confirmed:
|
|
|
|
| 503 |
cur_game.finish_stats_(forfeit=True)
|
| 504 |
-
if level in LEVELS
|
| 505 |
_solved_games[game_name].append(level)
|
|
|
|
| 506 |
return 0, _solved_games
|
| 507 |
return 1, _solved_games
|
| 508 |
-
give_up_checkbox.change(
|
| 509 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 510 |
|
| 511 |
-
def game_is_solved(_is_solved, _session_state, _solved_games):
|
| 512 |
if _is_solved:
|
| 513 |
-
if level in LEVELS
|
| 514 |
_solved_games[game_name].append(level)
|
| 515 |
return (
|
| 516 |
2,
|
| 517 |
gr.update(visible=False, interactive=False),
|
| 518 |
gr.update(visible=False, interactive=False),
|
| 519 |
-
gr.update(visible=True, interactive=True),
|
| 520 |
_solved_games,
|
|
|
|
| 521 |
)
|
| 522 |
else:
|
| 523 |
return (
|
| 524 |
-
_session_state, gr.update(), gr.update(), gr.update()
|
| 525 |
)
|
| 526 |
|
| 527 |
-
def
|
| 528 |
-
|
| 529 |
-
|
| 530 |
-
|
| 531 |
-
|
| 532 |
-
|
| 533 |
-
_files.create(body=file_metadata, media_body=media).execute()
|
| 534 |
-
except HttpError as error:
|
| 535 |
-
print(f"An error occurred: {error}")
|
| 536 |
|
| 537 |
is_solved_component.change(
|
| 538 |
game_is_solved,
|
| 539 |
[is_solved_component, session_state_component, solved_games_component],
|
| 540 |
-
[session_state_component, submit_btn, give_up_btn,
|
|
|
|
|
|
|
| 541 |
)
|
| 542 |
finish_btn.click(
|
| 543 |
-
upload_to_drive, None, None,
|
| 544 |
-
).then(
|
| 545 |
lambda: (0, 0), None, [session_state_component, is_solved_component]
|
| 546 |
)
|
| 547 |
|
|
@@ -556,24 +682,34 @@ def check_to_start_new_game(game_name, level, user=None, uid=None):
|
|
| 556 |
raise gr.Error(f"You have done this game already.<br/>{game_name} - {level}")
|
| 557 |
if user is None:
|
| 558 |
gr.Warning("no user, game will be generated randomly")
|
| 559 |
-
else:
|
| 560 |
-
|
| 561 |
-
|
| 562 |
-
|
| 563 |
-
|
| 564 |
return 1
|
| 565 |
|
| 566 |
|
| 567 |
# %%
|
| 568 |
-
def check_played_game(solved_games, uid):
|
|
|
|
|
|
|
|
|
|
|
|
|
| 569 |
ret = dict()
|
| 570 |
for game_name in solved_games.keys():
|
| 571 |
cur = []
|
| 572 |
-
for level, level_id in zip(LEVELS
|
| 573 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 574 |
cur.append(level)
|
| 575 |
ret[game_name] = cur
|
| 576 |
-
return ret
|
| 577 |
|
| 578 |
|
| 579 |
# %%
|
|
|
|
| 3 |
import time
|
| 4 |
import pandas as pd
|
| 5 |
import gradio as gr
|
| 6 |
+
import hashlib
|
| 7 |
+
from io import BytesIO
|
|
|
|
|
|
|
|
|
|
| 8 |
|
| 9 |
from textgames import GAME_NAMES, LEVEL_IDS, LEVELS, new_game, preload_game, game_filename
|
| 10 |
from textgames.islands.islands import Islands
|
|
|
|
| 14 |
|
| 15 |
|
| 16 |
# %%
|
| 17 |
+
import google.auth
|
| 18 |
+
from googleapiclient.discovery import build
|
| 19 |
+
from googleapiclient.errors import HttpError
|
| 20 |
+
from googleapiclient.http import MediaFileUpload, MediaIoBaseDownload
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
# %%
|
| 24 |
+
def declare_components(demo, greet):
|
| 25 |
with gr.Row():
|
| 26 |
with gr.Column(scale=1):
|
| 27 |
m = gr.Markdown("Welcome to TextGames!", elem_id="md-greeting")
|
|
|
|
| 33 |
level_radio = gr.Radio(LEVELS, label="Level", elem_id="radio-level-name")
|
| 34 |
new_game_btn = gr.Button("Start Game", elem_id="btn-start-game")
|
| 35 |
render_toggle = gr.Checkbox(False, visible=False, interactive=False)
|
| 36 |
+
|
| 37 |
+
# cur_game_start = gr.BrowserState()
|
| 38 |
+
session_state = gr.State(0) # 0: menu selection, 1: game is ongoing, 2: game is solved.
|
| 39 |
+
is_solved = gr.State(0)
|
| 40 |
+
solved_games = gr.State({g: [] for _, g in game_radio.choices})
|
| 41 |
+
user_state = gr.State()
|
| 42 |
+
uid_state = gr.State()
|
| 43 |
+
|
| 44 |
+
session_state.change(
|
| 45 |
+
lambda s: session_state_change_fn(s, 2, 0, 2, 0),
|
| 46 |
+
[session_state], [game_radio, level_radio, new_game_btn, logout_btn], js=js_remove_input_helper,
|
| 47 |
+
)
|
| 48 |
+
new_game_btn.click(check_to_start_new_game, [game_radio, level_radio, user_state, uid_state], [session_state])
|
| 49 |
+
solved_games.change(solved_games_change_fn, solved_games, solved_games_df)
|
| 50 |
+
session_state.change(lambda s, r: (not r if s in [0, 1] else r), [session_state, render_toggle], [render_toggle])
|
| 51 |
+
|
| 52 |
+
demo.load(
|
| 53 |
+
greet, None, [m, user_state, uid_state], js=js_solved_games_df_and_remove_footers
|
| 54 |
+
).then(
|
| 55 |
+
lambda: gr.update(interactive=False), None, [new_game_btn],
|
| 56 |
+
).then(
|
| 57 |
+
check_played_game, [solved_games, uid_state], [solved_games, solved_games_df]
|
| 58 |
+
).then(
|
| 59 |
+
lambda: gr.update(interactive=True), None, [new_game_btn],
|
| 60 |
+
)
|
| 61 |
+
|
| 62 |
+
return (
|
| 63 |
+
(m, logout_btn, solved_games_df, game_radio, level_radio, new_game_btn, render_toggle),
|
| 64 |
+
(session_state, is_solved, solved_games, user_state, uid_state),
|
| 65 |
+
)
|
| 66 |
|
| 67 |
|
| 68 |
# %%
|
| 69 |
+
_cksm_methods, _cksm_methods_str = (
|
| 70 |
+
[hashlib.md5, hashlib.sha1], "md5Checksum, sha1Checksum",
|
| 71 |
+
# [hashlib.md5, hashlib.sha1, hashlib.sha256], "md5Checksum, sha1Checksum, sha256Checksum",
|
| 72 |
+
)
|
| 73 |
+
_folder_id = "1qStKuVerAQPsXagngfzlNg8PdAR5hupA"
|
| 74 |
_creds_dict = {
|
| 75 |
"type": "service_account",
|
| 76 |
"project_id": os.getenv("GOOGLE_AUTH_CREDS_PROJECT_ID", ""),
|
|
|
|
| 89 |
_files = _service.files()
|
| 90 |
|
| 91 |
|
| 92 |
+
#%%
|
| 93 |
+
css = """
|
| 94 |
+
#lintao-helper-btn {background: darkgreen; color: white;}
|
| 95 |
+
.lintao-cell-highlight {background: var(--border-color-primary);}
|
| 96 |
+
//.lintao-border {border-style: solid; border-color: var(--body-text-color-subdued);}
|
| 97 |
+
"""
|
| 98 |
+
|
| 99 |
+
|
| 100 |
# %%
|
| 101 |
js_remove_input_helper = """(s) => {
|
| 102 |
var el = document.getElementById('lintao-container');
|
|
|
|
| 130 |
container.style.display = 'grid';
|
| 131 |
container.style.gridTemplateColumns = container.style.gridTemplateRows = `repeat(${{grid_N}}, ${{grid_px}}px)`;
|
| 132 |
container.style.gap = '1px';
|
| 133 |
+
container.style.border = '2px solid';
|
| 134 |
container.style.width = 'max-content';
|
| 135 |
container.style.margin = '5px 0px 5px 40px';
|
| 136 |
+
container.style.padding = '1px';
|
| 137 |
container.id = 'lintao-container';
|
| 138 |
|
| 139 |
for (let i = 0; i < grid_N; ++i) {{
|
|
|
|
| 145 |
cell.style.alignItems = 'center';
|
| 146 |
cell.style.justifyContent = 'center';
|
| 147 |
cell.style.fontSize = `${{grid_px/2}}px`;
|
| 148 |
+
cell.style.border = '1px solid var(--body-text-color-subdued)';
|
| 149 |
cell.style.cursor = 'pointer';
|
| 150 |
cell.id = `lintao-cell-${{i}}-${{j}}`;
|
| 151 |
|
|
|
|
| 177 |
|
| 178 |
js_island_submit = """
|
| 179 |
function island_submit(textarea, io_history) {{
|
| 180 |
+
const container = document.getElementById("lintao-container")
|
| 181 |
+
if (container === null) return [textarea, io_history];
|
| 182 |
const grid_N = {N};
|
| 183 |
var ret = "";
|
| 184 |
for (let i = 0; i < grid_N; ++i) {{
|
|
|
|
| 198 |
const N = {N};
|
| 199 |
const grid_N = N*N,
|
| 200 |
grid_px = 50,
|
| 201 |
+
border_px = 2;
|
| 202 |
const mat = {mat};
|
| 203 |
|
| 204 |
let is_numeric_sudoku = false;
|
|
|
|
| 214 |
const container = document.createElement('div');
|
| 215 |
container.style.display = 'grid';
|
| 216 |
container.style.gridTemplateColumns = container.style.gridTemplateRows = `repeat(${{grid_N}}, ${{grid_px}}px)`;
|
| 217 |
+
container.style.border = `${{border_px}}px solid`;
|
|
|
|
| 218 |
container.style.width = 'max-content';
|
| 219 |
container.style.margin = '5px 0px 5px 40px';
|
| 220 |
+
container.style.padding = '0px';
|
| 221 |
container.id = 'lintao-container';
|
| 222 |
|
| 223 |
// Generate the grid
|
| 224 |
+
const highlightClass = 'lintao-cell-highlight';
|
| 225 |
for (let i = 0; i < grid_N; ++i) {{
|
| 226 |
for (let j = 0; j < grid_N; ++j) {{
|
| 227 |
+
const cell = document.createElement('div');
|
| 228 |
cell.type = 'text';
|
| 229 |
cell.maxLength = 1;
|
| 230 |
cell.style.width = cell.style.height = `${{grid_px}}px`;
|
|
|
|
| 233 |
cell.style.justifyContent = 'center';
|
| 234 |
cell.style.textAlign = 'center';
|
| 235 |
cell.style.fontSize = `${{grid_px/2}}px`;
|
| 236 |
+
cell.style.border = '1px solid var(--body-text-color-subdued)';
|
| 237 |
+
cell.style.margin = '0px';
|
| 238 |
+
//cell.style.outline = 'none';
|
| 239 |
+
//cell.style.color = 'var(--body-text-color)';
|
| 240 |
+
//cell.style.backgroundColor = 'black';
|
| 241 |
cell.id = `lintao-cell-${{i}}-${{j}}`;
|
| 242 |
|
| 243 |
if (mat[i][j] != '_') {{
|
| 244 |
+
cell.textContent = mat[i][j];
|
| 245 |
+
cell.style.color = 'var(--block-title-text-color)';
|
| 246 |
cell.disabled = true;
|
| 247 |
+
}} else {{
|
| 248 |
+
cell.style.cursor = 'pointer';
|
| 249 |
+
cell.contentEditable = "true";
|
| 250 |
}}
|
| 251 |
|
|
|
|
|
|
|
| 252 |
|
| 253 |
+
if (j % N === 0) cell.style.borderLeft = `${{border_px}}px solid var(--body-text-color)`;
|
| 254 |
+
if (j % N === (N-1)) cell.style.borderRight = `${{border_px}}px solid var(--body-text-color)`;
|
| 255 |
+
if (i % N === 0) cell.style.borderTop = `${{border_px}}px solid var(--body-text-color)`;
|
| 256 |
+
if (i % N === (N-1)) cell.style.borderBottom = `${{border_px}}px solid var(--body-text-color)`;
|
| 257 |
|
| 258 |
// Allow only numbers 1-9 or A-I
|
| 259 |
cell.addEventListener('input', (e) => {{
|
| 260 |
+
if ((N === 2 && (!(is_numeric_sudoku?/^[1-4]$/:/^[A-Da-d]$/).test(e.target.textContent))) ||
|
| 261 |
+
(N === 3 && (!(is_numeric_sudoku?/^[1-9]$/:/^[A-Ia-i]$/).test(e.target.textContent)))) {{
|
| 262 |
+
e.target.textContent = '';
|
| 263 |
}}
|
| 264 |
+
e.target.textContent = e.target.textContent.toUpperCase();
|
| 265 |
}});
|
| 266 |
|
| 267 |
container.appendChild(cell);
|
|
|
|
| 281 |
const currentCol = i % grid_N;
|
| 282 |
|
| 283 |
if (currentRow === row || currentCol === col || (Math.floor(currentRow / N) === Math.floor(row / N) && Math.floor(currentCol / N) === Math.floor(col / N))) {{
|
| 284 |
+
cell.classList.add(highlightClass);
|
| 285 |
}} else {{
|
| 286 |
+
cell.classList.remove(highlightClass);
|
| 287 |
}}
|
| 288 |
}}
|
| 289 |
}});
|
| 290 |
|
| 291 |
container.addEventListener('focusout', () => {{
|
| 292 |
for (let i = 0; i < grid_N * grid_N; i++) {{
|
| 293 |
+
container.children[i].classList.remove(highlightClass);
|
| 294 |
}}
|
| 295 |
}});
|
| 296 |
|
|
|
|
| 301 |
|
| 302 |
js_sudoku_submit = """
|
| 303 |
function sudoku_submit(textarea, io_history) {{
|
| 304 |
+
const container = document.getElementById("lintao-container")
|
| 305 |
+
if (container === null) return [textarea, io_history];
|
| 306 |
const N = {N};
|
| 307 |
const grid_N = N*N;
|
| 308 |
var ret = "";
|
| 309 |
for (let i = 0; i < grid_N; ++i) {{
|
| 310 |
if (i > 0) ret += '\\n';
|
| 311 |
for (let j = 0; j < grid_N; ++j) {{
|
| 312 |
+
ret += document.getElementById(`lintao-cell-${{i}}-${{j}}`).textContent;
|
| 313 |
}}
|
| 314 |
}}
|
| 315 |
return [ret, io_history];
|
|
|
|
| 327 |
container.style.display = 'grid';
|
| 328 |
container.style.gridTemplateColumns = container.style.gridTemplateRows = `repeat(${{grid_N}}, ${{grid_px}}px)`;
|
| 329 |
container.style.gap = '1px';
|
| 330 |
+
container.style.border = '2px solid';
|
| 331 |
container.style.width = 'max-content';
|
| 332 |
container.style.margin = '5px 0px 5px 40px';
|
| 333 |
+
container.style.padding = '1px';
|
| 334 |
container.id = 'lintao-container';
|
| 335 |
|
| 336 |
// Generate the grid
|
|
|
|
| 346 |
cell.style.justifyContent = 'center';
|
| 347 |
cell.style.textAlign = 'center';
|
| 348 |
cell.style.fontSize = `${{grid_px/2}}px`;
|
| 349 |
+
cell.style.border = '1px solid var(--body-text-color-subdued)';
|
| 350 |
+
cell.style.backgroundColor = 'var(--body-background-fill)';
|
| 351 |
cell.style.cursor = 'pointer';
|
| 352 |
cell.id = `lintao-cell-${{i}}-${{j}}`;
|
| 353 |
|
|
|
|
| 369 |
|
| 370 |
js_crossword_submit = """
|
| 371 |
function crossword_submit(textarea, io_history) {{
|
| 372 |
+
const container = document.getElementById("lintao-container")
|
| 373 |
+
if (container === null) return [textarea, io_history];
|
| 374 |
const grid_N = {N};
|
| 375 |
var ret = "";
|
| 376 |
for (let i = 0; i < grid_N; ++i) {{
|
|
|
|
| 391 |
listContainer.style.listStyle = 'none';
|
| 392 |
listContainer.style.padding = '0';
|
| 393 |
listContainer.style.width = '20em';
|
| 394 |
+
listContainer.style.border = '2px solid';
|
| 395 |
listContainer.style.margin = '5px 0px 5px 40px';
|
| 396 |
listContainer.id = 'lintao-container';
|
| 397 |
|
|
|
|
| 404 |
listItem.textContent = itemText;
|
| 405 |
listItem.draggable = true;
|
| 406 |
listItem.style.padding = '10px';
|
| 407 |
+
listItem.style.border = '1px solid';
|
| 408 |
listItem.style.margin = '3px';
|
| 409 |
+
//listItem.style.backgroundColor = 'var(--body-background-fill)';
|
| 410 |
listItem.style.cursor = 'grab';
|
| 411 |
listItem.id = `lintao-item-${{index}}`;
|
| 412 |
|
|
|
|
| 414 |
listItem.addEventListener('dragstart', (e) => {{
|
| 415 |
const draggedIndex = Array.from(listContainer.children).indexOf(listItem);
|
| 416 |
e.dataTransfer.setData('text/plain', draggedIndex);
|
| 417 |
+
listItem.style.backgroundColor = 'var(--block-background-fill)';
|
| 418 |
}});
|
| 419 |
|
| 420 |
listItem.addEventListener('dragover', (e) => {{
|
| 421 |
e.preventDefault();
|
| 422 |
+
listItem.style.backgroundColor = 'var(--border-color-primary)';
|
| 423 |
}});
|
| 424 |
|
| 425 |
listItem.addEventListener('dragleave', () => {{
|
| 426 |
+
listItem.style.backgroundColor = 'var(--body-background-fill)';
|
| 427 |
}});
|
| 428 |
|
| 429 |
listItem.addEventListener('drop', (e) => {{
|
|
|
|
| 437 |
listContainer.insertBefore(draggedItem, targetIndex > draggedIndex ? listItem.nextSibling : listItem);
|
| 438 |
}}
|
| 439 |
|
| 440 |
+
listItem.style.backgroundColor = 'var(--body-background-fill)';
|
| 441 |
}});
|
| 442 |
|
| 443 |
listItem.addEventListener('dragend', () => {{
|
| 444 |
+
listItem.style.backgroundColor = 'var(--body-background-fill)';
|
| 445 |
}});
|
| 446 |
|
| 447 |
listContainer.appendChild(listItem);
|
|
|
|
| 454 |
|
| 455 |
js_ordering_submit = """
|
| 456 |
function ordering_submit(textarea, io_history) {{
|
| 457 |
+
const container = document.getElementById("lintao-container")
|
| 458 |
+
if (container === null) return [textarea, io_history];
|
| 459 |
var ret = "";
|
| 460 |
+
container.childNodes.forEach(
|
|
|
|
| 461 |
(c, i) => {{
|
| 462 |
if (i>0) ret += '\\n';
|
| 463 |
ret += c.textContent;
|
|
|
|
| 483 |
return f"{fd}/{fn_prefix}_-_{game_filename(game_name)}_{level_id}.pkl"
|
| 484 |
|
| 485 |
|
| 486 |
+
# %%
|
| 487 |
+
def _is_checksum_same(fp_out, matches=None, mime_type="application/octet-stream"):
|
| 488 |
+
if matches is None:
|
| 489 |
+
matches = _files.list(
|
| 490 |
+
q=f"'{_folder_id}' in parents and mimeType='{mime_type}' and name = '{fp_out.rsplit('/', 1)[-1]}'",
|
| 491 |
+
fields=f"files(name, id, {_cksm_methods_str})",
|
| 492 |
+
).execute()['files']
|
| 493 |
+
if not os.path.exists(fp_out):
|
| 494 |
+
return None, None, matches
|
| 495 |
+
with open(fp_out, "rb") as o:
|
| 496 |
+
_local = BytesIO(o.read()).getvalue()
|
| 497 |
+
_local_hash = [m(_local).hexdigest() for m in _cksm_methods]
|
| 498 |
+
for i, match in enumerate(matches):
|
| 499 |
+
if all(a == b for a, b in zip(_local_hash, [match[k] for k in _cksm_methods_str.split(", ")])):
|
| 500 |
+
return True, i, matches
|
| 501 |
+
return False, -1, matches
|
| 502 |
+
|
| 503 |
+
|
| 504 |
+
# %%
|
| 505 |
+
def upload_to_drive(fp_out, matches=None, mime_type="application/octet-stream", compare_checksum=True):
|
| 506 |
+
if compare_checksum:
|
| 507 |
+
same_checksum, _, _ = _is_checksum_same(fp_out, matches, mime_type)
|
| 508 |
+
# same_checksum, _, _ = _is_checksum_same(
|
| 509 |
+
# fp_out, **{k: v for k, v in [('matches', matches), ('mime_type', mime_type)] if v})
|
| 510 |
+
if same_checksum:
|
| 511 |
+
return
|
| 512 |
+
fn = fp_out.rsplit("/", 1)[-1]
|
| 513 |
+
file_metadata = {"name": fn, "parents": [_folder_id]}
|
| 514 |
+
media = MediaFileUpload(fp_out)
|
| 515 |
+
try:
|
| 516 |
+
_files.create(body=file_metadata, media_body=media).execute()
|
| 517 |
+
except HttpError as error:
|
| 518 |
+
msg = f"Failed to upload the file, error: {error}"
|
| 519 |
+
print(msg)
|
| 520 |
+
gr.Error(msg)
|
| 521 |
+
|
| 522 |
+
|
| 523 |
+
# %%
|
| 524 |
+
def download_from_drive(fp_out, matches=None, mime_type="application/octet-stream", compare_checksum=True):
|
| 525 |
+
if compare_checksum and os.path.exists(fp_out):
|
| 526 |
+
same_checksum, i, matches = _is_checksum_same(fp_out, matches, mime_type)
|
| 527 |
+
if same_checksum:
|
| 528 |
+
return
|
| 529 |
+
if matches is None:
|
| 530 |
+
_, _, matches = _is_checksum_same(fp_out, matches, mime_type)
|
| 531 |
+
if len(matches) == 0:
|
| 532 |
+
return
|
| 533 |
+
else:
|
| 534 |
+
if len(matches) > 1:
|
| 535 |
+
gr.Warning(f"Multiple matches found! {fp_out.rsplit('/', 1)[-1].split('_-_', 1)[-1]}")
|
| 536 |
+
b_io, request = BytesIO(), _files.get_media(fileId=matches[0]['id'])
|
| 537 |
+
downloader = MediaIoBaseDownload(b_io, request)
|
| 538 |
+
if os.path.exists(fp_out):
|
| 539 |
+
print(f"Deleting and re-download... ({fp_out})")
|
| 540 |
+
os.remove(fp_out)
|
| 541 |
+
done = False
|
| 542 |
+
while not done:
|
| 543 |
+
status, done = downloader.next_chunk()
|
| 544 |
+
with open(fp_out, "ab") as o:
|
| 545 |
+
o.write(b_io.getvalue())
|
| 546 |
+
|
| 547 |
+
|
| 548 |
# %%
|
| 549 |
def start_new_game(game_name, level, session_state_component, is_solved_component, solved_games_component,
|
| 550 |
user=None, show_timer=False, uid=None):
|
|
|
|
| 562 |
preload_game(game_name, difficulty_level, user)
|
| 563 |
)
|
| 564 |
cur_game.attach_stats_output_(fp_out)
|
| 565 |
+
cur_game.flush_stats_(user_info_to_flush=user)
|
| 566 |
|
| 567 |
def add_msg(new_msg, prev_msg):
|
| 568 |
+
if len(new_msg) > 200:
|
| 569 |
+
new_msg = new_msg[:200]
|
| 570 |
+
gr.Warning("your input is too long! It has been truncated.")
|
| 571 |
user_input = '\n'.join(new_msg.split())
|
| 572 |
solved, val_msg = cur_game.validate(user_input)
|
| 573 |
response = ("Correct guess" if solved else "Bad guess (Wrong Answer)") + "\n" + val_msg
|
|
|
|
| 579 |
|
| 580 |
gr.Markdown(
|
| 581 |
"""
|
| 582 |
+
> ### ‼️ Do ***<span style="color:red">NOT</span>*** refresh this page. ‼️<br>
|
| 583 |
> #### ⚠️ Refreshing the page equals "Give-up 😭" ⚠️
|
|
|
|
|
|
|
| 584 |
"""
|
| 585 |
)
|
| 586 |
showhide_helper_btn = gr.Button("Show Input Helper (disabling manual input)", elem_id="lintao-helper-btn")
|
|
|
|
| 622 |
|
| 623 |
def _forfeiting(confirmed, _solved_games):
|
| 624 |
if confirmed:
|
| 625 |
+
gr.Info("Sad to see you go... Wrapping things up...")
|
| 626 |
cur_game.finish_stats_(forfeit=True)
|
| 627 |
+
if level in LEVELS and level not in _solved_games[game_name]:
|
| 628 |
_solved_games[game_name].append(level)
|
| 629 |
+
upload_to_drive(fp_out)
|
| 630 |
return 0, _solved_games
|
| 631 |
return 1, _solved_games
|
| 632 |
+
give_up_checkbox.change(
|
| 633 |
+
lambda: (gr.update(interactive=False), gr.update(interactive=False)), None, [submit_btn, give_up_btn]
|
| 634 |
+
).then(
|
| 635 |
+
_forfeiting, [give_up_checkbox, solved_games_component], [session_state_component, solved_games_component]
|
| 636 |
+
).then(
|
| 637 |
+
lambda: (gr.update(interactive=True), gr.update(interactive=True)), None, [submit_btn, give_up_btn]
|
| 638 |
+
)
|
| 639 |
|
| 640 |
+
def game_is_solved(_is_solved, _session_state, _solved_games, progress=gr.Progress()):
|
| 641 |
if _is_solved:
|
| 642 |
+
if level in LEVELS and level not in _solved_games[game_name]:
|
| 643 |
_solved_games[game_name].append(level)
|
| 644 |
return (
|
| 645 |
2,
|
| 646 |
gr.update(visible=False, interactive=False),
|
| 647 |
gr.update(visible=False, interactive=False),
|
|
|
|
| 648 |
_solved_games,
|
| 649 |
+
gr.update(visible=True, interactive=False),
|
| 650 |
)
|
| 651 |
else:
|
| 652 |
return (
|
| 653 |
+
_session_state, gr.update(), gr.update(), _solved_games, gr.update()
|
| 654 |
)
|
| 655 |
|
| 656 |
+
def finalize_game(_is_solved):
|
| 657 |
+
if _is_solved:
|
| 658 |
+
gr.Info("Reporting... Please click the button when available...")
|
| 659 |
+
upload_to_drive(fp_out)
|
| 660 |
+
return gr.update(interactive=True)
|
| 661 |
+
return gr.update()
|
|
|
|
|
|
|
|
|
|
| 662 |
|
| 663 |
is_solved_component.change(
|
| 664 |
game_is_solved,
|
| 665 |
[is_solved_component, session_state_component, solved_games_component],
|
| 666 |
+
[session_state_component, submit_btn, give_up_btn, solved_games_component, finish_btn],
|
| 667 |
+
).then(
|
| 668 |
+
finalize_game, [is_solved_component], [finish_btn],
|
| 669 |
)
|
| 670 |
finish_btn.click(
|
|
|
|
|
|
|
| 671 |
lambda: (0, 0), None, [session_state_component, is_solved_component]
|
| 672 |
)
|
| 673 |
|
|
|
|
| 682 |
raise gr.Error(f"You have done this game already.<br/>{game_name} - {level}")
|
| 683 |
if user is None:
|
| 684 |
gr.Warning("no user, game will be generated randomly")
|
| 685 |
+
# else:
|
| 686 |
+
# if not user['email_verified']:
|
| 687 |
+
# gr.Warning("please verify your email address")
|
| 688 |
+
# elif user['email_verified'] == "mockuser":
|
| 689 |
+
# gr.Info("game will load with a mocked-up user")
|
| 690 |
return 1
|
| 691 |
|
| 692 |
|
| 693 |
# %%
|
| 694 |
+
def check_played_game(solved_games, uid, progress=gr.Progress()):
|
| 695 |
+
matches = _files.list(
|
| 696 |
+
q=f"'{_folder_id}' in parents and mimeType='application/octet-stream' and name contains '{uid}_-_'",
|
| 697 |
+
fields=f"files(name, id, {_cksm_methods_str})",
|
| 698 |
+
).execute()['files']
|
| 699 |
ret = dict()
|
| 700 |
for game_name in solved_games.keys():
|
| 701 |
cur = []
|
| 702 |
+
for level, level_id in zip(LEVELS, LEVEL_IDS):
|
| 703 |
+
fp_out = _get_file_output(game_name, level_id, uid)
|
| 704 |
+
_matches = list(filter(lambda m: fp_out.endswith(m['name']), matches))
|
| 705 |
+
if os.path.exists(fp_out):
|
| 706 |
+
upload_to_drive(fp_out, _matches)
|
| 707 |
+
else:
|
| 708 |
+
download_from_drive(fp_out, _matches)
|
| 709 |
+
if os.path.exists(fp_out):
|
| 710 |
cur.append(level)
|
| 711 |
ret[game_name] = cur
|
| 712 |
+
return ret, gr.update()
|
| 713 |
|
| 714 |
|
| 715 |
# %%
|
play_with_auth.py
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
|
| 3 |
+
# os.environ.setdefault("GRADIO_SERVER_PORT", "1080")
|
| 4 |
+
# os.environ.setdefault("TEXTGAMES_SHOW_HIDDEN_LEVEL", "1")
|
| 5 |
+
os.environ.setdefault("TEXTGAMES_LOADGAME_DIR", "problemsets")
|
| 6 |
+
os.environ.setdefault("TEXTGAMES_LOADGAME_ID", "42")
|
| 7 |
+
os.environ.setdefault("TEXTGAMES_MOCKUSER", "")
|
| 8 |
+
os.environ.setdefault("TEXTGAMES_OUTPUT_DIR", "user_outputs")
|
| 9 |
+
os.environ.setdefault("TEXTGAMES_HASH_USER", "")
|
| 10 |
+
favicon_path = "textgames-scrabble-black2-ss.png"
|
| 11 |
+
|
| 12 |
+
#%%
|
| 13 |
+
from play_helper import css, declare_components, start_new_game
|
| 14 |
+
from typing import Optional
|
| 15 |
+
import gradio as gr
|
| 16 |
+
import hashlib
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
#%%
|
| 20 |
+
import uvicorn
|
| 21 |
+
from fastapi import FastAPI, Depends, Request
|
| 22 |
+
from starlette.config import Config
|
| 23 |
+
from starlette.responses import RedirectResponse, FileResponse
|
| 24 |
+
from starlette.middleware.sessions import SessionMiddleware
|
| 25 |
+
from authlib.integrations.starlette_client import OAuth, OAuthError
|
| 26 |
+
|
| 27 |
+
app = FastAPI()
|
| 28 |
+
|
| 29 |
+
# Replace these with your own OAuth settings
|
| 30 |
+
GOOGLE_CLIENT_ID = os.environ.get("GOOGLE_CLIENT_ID")
|
| 31 |
+
GOOGLE_CLIENT_SECRET = os.environ.get("GOOGLE_CLIENT_SECRET")
|
| 32 |
+
SECRET_KEY = os.environ.get("SECRET_KEY", "a_very_secret_key")
|
| 33 |
+
|
| 34 |
+
# Set up OAuth
|
| 35 |
+
config_data = {'GOOGLE_CLIENT_ID': GOOGLE_CLIENT_ID, 'GOOGLE_CLIENT_SECRET': GOOGLE_CLIENT_SECRET}
|
| 36 |
+
starlette_config = Config(environ=config_data)
|
| 37 |
+
oauth = OAuth(starlette_config)
|
| 38 |
+
oauth.register(
|
| 39 |
+
name='google',
|
| 40 |
+
server_metadata_url='https://accounts.google.com/.well-known/openid-configuration',
|
| 41 |
+
client_kwargs={'scope': 'openid email profile'},
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
app.add_middleware(SessionMiddleware, secret_key=SECRET_KEY)
|
| 45 |
+
|
| 46 |
+
_HASHER = (hashlib.blake2b, {"digest_size": 16, "key": SECRET_KEY.encode('utf-8')})
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def _hash_msg(msg):
|
| 50 |
+
if isinstance(msg, str):
|
| 51 |
+
msg = msg.encode('utf-8')
|
| 52 |
+
m = _HASHER[0](**_HASHER[1])
|
| 53 |
+
m.update(msg)
|
| 54 |
+
return m.hexdigest()
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
# Dependency to get the current user
|
| 58 |
+
def get_user(request: Request) -> Optional[dict]:
|
| 59 |
+
if user := request.session.get('user'):
|
| 60 |
+
return user
|
| 61 |
+
elif username := os.getenv("TEXTGAMES_MOCKUSER", ""):
|
| 62 |
+
return {'name': username, 'email': username, 'email_verified': False}
|
| 63 |
+
else:
|
| 64 |
+
return
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def get_username(request: Request):
|
| 68 |
+
user = get_user(request)
|
| 69 |
+
if user:
|
| 70 |
+
return user['email']
|
| 71 |
+
return None
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
@app.get('/favicon.ico', include_in_schema=False)
|
| 75 |
+
async def favicon():
|
| 76 |
+
return FileResponse(favicon_path)
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
@app.get('/')
|
| 80 |
+
def public(user: str = Depends(get_username)):
|
| 81 |
+
if user:
|
| 82 |
+
return RedirectResponse(url='/TextGames')
|
| 83 |
+
else:
|
| 84 |
+
return RedirectResponse(url='/login')
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
@app.route('/logout')
|
| 88 |
+
async def logout(request: Request):
|
| 89 |
+
request.session.pop('user', None)
|
| 90 |
+
if os.getenv('TEXTGAMES_MOCKUSER', ''):
|
| 91 |
+
os.environ['TEXTGAMES_MOCKUSER'] = ''
|
| 92 |
+
return RedirectResponse(url='/')
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
@app.route('/do-login')
|
| 96 |
+
async def login(request: Request):
|
| 97 |
+
redirect_uri = request.url_for('auth')
|
| 98 |
+
# If your app is running on https, you should ensure that the
|
| 99 |
+
# `redirect_uri` is https, e.g. uncomment the following lines:
|
| 100 |
+
|
| 101 |
+
from urllib.parse import urlparse, urlunparse
|
| 102 |
+
redirect_uri = urlunparse(urlparse(str(redirect_uri))._replace(scheme='https'))
|
| 103 |
+
return await oauth.google.authorize_redirect(request, redirect_uri)
|
| 104 |
+
|
| 105 |
+
|
| 106 |
+
@app.route('/auth')
|
| 107 |
+
async def auth(request: Request):
|
| 108 |
+
try:
|
| 109 |
+
access_token = await oauth.google.authorize_access_token(request)
|
| 110 |
+
except OAuthError:
|
| 111 |
+
return RedirectResponse(url='/')
|
| 112 |
+
request.session['user'] = dict(access_token)["userinfo"]
|
| 113 |
+
return RedirectResponse(url='/')
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
def greet(request: gr.Request):
|
| 117 |
+
user = get_user(request.request)
|
| 118 |
+
uid = _hash_msg(user['email']) if os.getenv("TEXTGAMES_HASH_USER", "") else user['email']
|
| 119 |
+
return f"""
|
| 120 |
+
Welcome to TextGames, {user['name']}!<br />
|
| 121 |
+
<{user['email'].replace('@', '{at}')}> ({'' if user['email_verified'] else 'NON-'}verified email)
|
| 122 |
+
""", user, uid
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
with gr.Blocks(title="TextGames") as login_demo:
|
| 126 |
+
gr.Markdown("Welcome to TextGames!")
|
| 127 |
+
# gr.Button("Login", link="/do-login")
|
| 128 |
+
gr.Button("🚪\tLogin", link="/do-login", icon=None)
|
| 129 |
+
|
| 130 |
+
app = gr.mount_gradio_app(app, login_demo, path="/login")
|
| 131 |
+
|
| 132 |
+
with gr.Blocks(title="TextGames", css=css, delete_cache=(3600, 3600)) as demo:
|
| 133 |
+
((m, logout_btn, solved_games_df, game_radio, level_radio, new_game_btn, render_toggle),
|
| 134 |
+
(session_state, is_solved, solved_games, user_state, uid_state),
|
| 135 |
+
) = declare_components(demo, greet)
|
| 136 |
+
|
| 137 |
+
@gr.render(inputs=[game_radio, level_radio, user_state, session_state, uid_state], triggers=[render_toggle.change])
|
| 138 |
+
def _start_new_game(game_name, level, user, _session_state, _uid_state):
|
| 139 |
+
if _session_state in [1, 2]:
|
| 140 |
+
start_new_game(game_name, level, session_state, is_solved, solved_games, user=user, uid=_uid_state)
|
| 141 |
+
|
| 142 |
+
|
| 143 |
+
app = gr.mount_gradio_app(app, demo, path="/TextGames", auth_dependency=get_username)
|
| 144 |
+
|
| 145 |
+
if __name__ == '__main__':
|
| 146 |
+
uvicorn.run(app,
|
| 147 |
+
port=int(os.getenv("GRADIO_SERVER_PORT", "7860")),
|
| 148 |
+
host=os.getenv("UVICORN_SERVER_HOST", "127.0.0.1"),
|
| 149 |
+
ssl_keyfile=os.getenv("SSL_KEYFILE", None),
|
| 150 |
+
ssl_certfile=os.getenv("SSL_CERTFILE", None),
|
| 151 |
+
)
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
#%%
|
| 155 |
+
|
| 156 |
+
|
| 157 |
+
#%%
|
| 158 |
+
|
read_pkl.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pickle
|
| 2 |
+
|
| 3 |
+
def read_pkl(fp):
|
| 4 |
+
with open(fp, "rb") as f:
|
| 5 |
+
data = []
|
| 6 |
+
try:
|
| 7 |
+
while True:
|
| 8 |
+
data.append(pickle.load(f))
|
| 9 |
+
except EOFError as e:
|
| 10 |
+
pass
|
| 11 |
+
return data
|
textgames/__init__.py
CHANGED
|
@@ -34,9 +34,9 @@ SINGLE_LINE_GAME_IDS = list(map(lambda g: GAME_IDS[GAME_NAMES.index(g.get_game_n
|
|
| 34 |
[PasswordGame, BracketGame, StringSearch, AnagramScribble]
|
| 35 |
))
|
| 36 |
|
| 37 |
-
LEVEL_IDS = ["
|
| 38 |
-
LEVELS = ["
|
| 39 |
-
LEVELS_HIDDEN = ["🌌\tInsane", "🔰\tSample #2"]
|
| 40 |
_show_hidden_level_ = os.getenv("TEXTGAMES_SHOW_HIDDEN_LEVEL", False)
|
| 41 |
if _show_hidden_level_:
|
| 42 |
LEVELS, LEVELS_HIDDEN = LEVELS + LEVELS_HIDDEN, []
|
|
@@ -62,14 +62,16 @@ def _game_class_from_name(game_name):
|
|
| 62 |
|
| 63 |
def preload_game(game_name, level_id, user):
|
| 64 |
game_cls = _game_class_from_name(game_name)
|
| 65 |
-
email_sid_dict = read_csv(
|
|
|
|
|
|
|
| 66 |
sid = email_sid_dict.get(user["email"])
|
| 67 |
-
print(f"preload_game('{game_name}', '{level_id}', '{user['email']}')
|
| 68 |
|
| 69 |
with open(f"problemsets/{game_filename(game_name)}_{level_id}.json", "r", encoding="utf8") as f:
|
| 70 |
sid_prompt_dict = json.load(f)
|
| 71 |
prompt = sid_prompt_dict.get(sid)
|
| 72 |
-
print("Loaded prompt:", prompt, sep="\n")
|
| 73 |
|
| 74 |
return _reload(prompt, game_cls)
|
| 75 |
|
|
|
|
| 34 |
[PasswordGame, BracketGame, StringSearch, AnagramScribble]
|
| 35 |
))
|
| 36 |
|
| 37 |
+
LEVEL_IDS = ["1", "2", "3", "4", "0", "00"]
|
| 38 |
+
LEVELS = ["🚅\tEasy", "🚀\tMedium", "🛸\tHard"]
|
| 39 |
+
LEVELS_HIDDEN = ["🌌\tInsane", "🔰\tSample #1", "🔰\tSample #2"]
|
| 40 |
_show_hidden_level_ = os.getenv("TEXTGAMES_SHOW_HIDDEN_LEVEL", False)
|
| 41 |
if _show_hidden_level_:
|
| 42 |
LEVELS, LEVELS_HIDDEN = LEVELS + LEVELS_HIDDEN, []
|
|
|
|
| 62 |
|
| 63 |
def preload_game(game_name, level_id, user):
|
| 64 |
game_cls = _game_class_from_name(game_name)
|
| 65 |
+
email_sid_dict = read_csv(
|
| 66 |
+
f"{os.getenv('TEXTGAMES_OUTPUT_DIR')}/textgames_userauth.tsv", sep='\t'
|
| 67 |
+
).dropna().set_index("EMAIL").SID.to_dict()
|
| 68 |
sid = email_sid_dict.get(user["email"])
|
| 69 |
+
print(f"preload_game('{game_name}', '{level_id}', '{user['email']}') on {sid}")
|
| 70 |
|
| 71 |
with open(f"problemsets/{game_filename(game_name)}_{level_id}.json", "r", encoding="utf8") as f:
|
| 72 |
sid_prompt_dict = json.load(f)
|
| 73 |
prompt = sid_prompt_dict.get(sid)
|
| 74 |
+
# print("Loaded prompt:", prompt, sep="\n")
|
| 75 |
|
| 76 |
return _reload(prompt, game_cls)
|
| 77 |
|
textgames/base_game.py
CHANGED
|
@@ -42,11 +42,11 @@ class BaseGame:
|
|
| 42 |
assert not self.stats_filepath
|
| 43 |
self.stats_filepath = filepath
|
| 44 |
|
| 45 |
-
def flush_stats_(self,
|
| 46 |
if self.stats_filepath:
|
| 47 |
with open(self.stats_filepath, mode='ab') as o:
|
| 48 |
-
if
|
| 49 |
-
pickle.dump((time.time(),
|
| 50 |
else:
|
| 51 |
pickle.dump((
|
| 52 |
time.time(),
|
|
@@ -112,7 +112,4 @@ def _is_game_reloadable(original_game: BaseGame) -> bool:
|
|
| 112 |
original_game_states = {k: v for k, v in vars(original_game).items() if k not in exclude_states}
|
| 113 |
loaded_game_states = {k: v for k, v in vars(loaded_game).items() if k not in exclude_states}
|
| 114 |
|
| 115 |
-
|
| 116 |
-
if not ret:
|
| 117 |
-
pass
|
| 118 |
-
return ret
|
|
|
|
| 42 |
assert not self.stats_filepath
|
| 43 |
self.stats_filepath = filepath
|
| 44 |
|
| 45 |
+
def flush_stats_(self, user_info_to_flush=None):
|
| 46 |
if self.stats_filepath:
|
| 47 |
with open(self.stats_filepath, mode='ab') as o:
|
| 48 |
+
if user_info_to_flush:
|
| 49 |
+
pickle.dump((time.time(), user_info_to_flush), o)
|
| 50 |
else:
|
| 51 |
pickle.dump((
|
| 52 |
time.time(),
|
|
|
|
| 112 |
original_game_states = {k: v for k, v in vars(original_game).items() if k not in exclude_states}
|
| 113 |
loaded_game_states = {k: v for k, v in vars(loaded_game).items() if k not in exclude_states}
|
| 114 |
|
| 115 |
+
return (original_game_states == loaded_game_states) and (original_game.get_prompt() == loaded_game.get_prompt())
|
|
|
|
|
|
|
|
|
textgames/ordering_text/ordering_text.py
CHANGED
|
@@ -170,7 +170,7 @@ class ConsecutiveScoring(Scoring):
|
|
| 170 |
pattern += cur_pattern
|
| 171 |
pattern += f"{{{n}}}" if (n > 1) else ""
|
| 172 |
n = 1
|
| 173 |
-
self._pattern = re.compile(pattern)
|
| 174 |
|
| 175 |
self.prompt = None
|
| 176 |
|
|
|
|
| 170 |
pattern += cur_pattern
|
| 171 |
pattern += f"{{{n}}}" if (n > 1) else ""
|
| 172 |
n = 1
|
| 173 |
+
self._pattern = re.compile(f"(?=({pattern}))")
|
| 174 |
|
| 175 |
self.prompt = None
|
| 176 |
|
textgames_userauth_generate.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import pandas as pd
|
| 3 |
+
from dotenv import load_dotenv
|
| 4 |
+
|
| 5 |
+
# %%
|
| 6 |
+
load_dotenv("oauth_environ_google.env")
|
| 7 |
+
|
| 8 |
+
# %%
|
| 9 |
+
os.system("python ~/pwd_generator.py --spchar \"+()!#$%&@?.;/\" -n 1000 -r 3 -l 24 > textgames_passwords.txt")
|
| 10 |
+
|
| 11 |
+
# %%
|
| 12 |
+
with open("textgames_passwords.txt", "r", encoding="utf8") as i:
|
| 13 |
+
passwords = [("", "", l.strip(), f"session_{k:04}") for k, l in enumerate(i)]
|
| 14 |
+
|
| 15 |
+
# %%
|
| 16 |
+
df = pd.DataFrame(passwords, columns=["EMAIL", "NAME", "PASSWORD", "SID"])
|
| 17 |
+
|
| 18 |
+
# %%
|
| 19 |
+
df.to_csv("textgames_userauth.tsv", index=False, sep="\t")
|
| 20 |
+
|
| 21 |
+
# %%
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
# %%
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
# %%
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
# %%
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
# %%
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
# %%
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
# %%
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
# %%
|
| 43 |
+
|
| 44 |
+
|