GameSentenceMiner 2.8.54__py3-none-any.whl → 2.9.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- GameSentenceMiner/anki.py +1 -1
- GameSentenceMiner/communication/websocket.py +7 -0
- GameSentenceMiner/config_gui.py +63 -20
- GameSentenceMiner/configuration.py +69 -3
- GameSentenceMiner/ffmpeg.py +2 -2
- GameSentenceMiner/gametext.py +71 -62
- GameSentenceMiner/gsm.py +108 -55
- GameSentenceMiner/obs.py +2 -2
- GameSentenceMiner/ocr/owocr_helper.py +17 -25
- GameSentenceMiner/owocr/owocr/ocr.py +4 -3
- GameSentenceMiner/text_log.py +1 -1
- GameSentenceMiner/vad/groq_trim.py +82 -0
- GameSentenceMiner/vad/result.py +15 -2
- GameSentenceMiner/vad/silero_trim.py +14 -10
- GameSentenceMiner/vad/vad_utils.py +13 -0
- GameSentenceMiner/vad/vosk_helper.py +2 -2
- GameSentenceMiner/vad/whisper_helper.py +8 -7
- GameSentenceMiner/web/templates/index.html +49 -0
- GameSentenceMiner/web/templates/utility.html +2 -2
- GameSentenceMiner/web/texthooking_page.py +54 -32
- {gamesentenceminer-2.8.54.dist-info → gamesentenceminer-2.9.1.dist-info}/METADATA +4 -1
- {gamesentenceminer-2.8.54.dist-info → gamesentenceminer-2.9.1.dist-info}/RECORD +26 -23
- {gamesentenceminer-2.8.54.dist-info → gamesentenceminer-2.9.1.dist-info}/WHEEL +1 -1
- {gamesentenceminer-2.8.54.dist-info → gamesentenceminer-2.9.1.dist-info}/entry_points.txt +0 -0
- {gamesentenceminer-2.8.54.dist-info → gamesentenceminer-2.9.1.dist-info}/licenses/LICENSE +0 -0
- {gamesentenceminer-2.8.54.dist-info → gamesentenceminer-2.9.1.dist-info}/top_level.txt +0 -0
@@ -301,10 +301,10 @@
|
|
301
301
|
async function toggleCheckbox(id, checked) {
|
302
302
|
try {
|
303
303
|
checkboxes_being_updated.add(id);
|
304
|
-
const res = await fetch('/
|
304
|
+
const res = await fetch('/update_checkbox', {
|
305
305
|
method: 'POST',
|
306
306
|
headers: { 'Content-Type': 'application/json' },
|
307
|
-
body: JSON.stringify({ id
|
307
|
+
body: JSON.stringify({ id })
|
308
308
|
});
|
309
309
|
checkboxes_being_updated.delete(id);
|
310
310
|
if (!res.ok) {
|
@@ -10,11 +10,11 @@ from dataclasses import dataclass
|
|
10
10
|
import flask
|
11
11
|
import websockets
|
12
12
|
|
13
|
-
from GameSentenceMiner.text_log import GameLine, get_line_by_id, initial_time
|
13
|
+
from GameSentenceMiner.text_log import GameLine, get_line_by_id, initial_time, get_all_lines
|
14
14
|
from flask import request, jsonify, send_from_directory
|
15
15
|
import webbrowser
|
16
16
|
from GameSentenceMiner import obs
|
17
|
-
from GameSentenceMiner.configuration import logger, get_config, DB_PATH
|
17
|
+
from GameSentenceMiner.configuration import logger, get_config, DB_PATH, gsm_state
|
18
18
|
from GameSentenceMiner.util import TEXT_REPLACEMENTS_FILE
|
19
19
|
|
20
20
|
port = get_config().general.texthooker_port
|
@@ -52,8 +52,6 @@ class EventItem:
|
|
52
52
|
class EventManager:
|
53
53
|
events: list[EventItem]
|
54
54
|
events_dict: dict[str, EventItem] = {}
|
55
|
-
line_for_audio: GameLine = None
|
56
|
-
line_for_screenshot: GameLine = None
|
57
55
|
|
58
56
|
def __init__(self):
|
59
57
|
self.events = []
|
@@ -100,7 +98,7 @@ class EventManager:
|
|
100
98
|
self.events_dict[line.id] = new_event
|
101
99
|
self.events.append(new_event)
|
102
100
|
# self.store_to_db(new_event)
|
103
|
-
event_queue.put(new_event)
|
101
|
+
# event_queue.put(new_event)
|
104
102
|
return new_event
|
105
103
|
|
106
104
|
def reset_checked_lines(self):
|
@@ -225,11 +223,11 @@ def serve_static(filename):
|
|
225
223
|
|
226
224
|
@app.route('/')
|
227
225
|
def index():
|
228
|
-
return flask.render_template('utility.html', websocket_port=websocket_port)
|
226
|
+
return flask.render_template('utility.html' if get_config().general.use_old_texthooker else 'index.html', websocket_port=websocket_port)
|
229
227
|
|
230
228
|
@app.route('/texthooker')
|
231
229
|
def texthooker():
|
232
|
-
return flask.render_template('utility.html', websocket_port=websocket_port)
|
230
|
+
return flask.render_template('utility.html' if get_config().general.use_old_texthooker else 'index.html', websocket_port=websocket_port)
|
233
231
|
|
234
232
|
@app.route('/textreplacements')
|
235
233
|
def textreplacements():
|
@@ -256,16 +254,15 @@ async def add_event_to_texthooker(line: GameLine):
|
|
256
254
|
})
|
257
255
|
|
258
256
|
|
259
|
-
@app.route('/
|
257
|
+
@app.route('/update_checkbox', methods=['POST'])
|
260
258
|
def update_event():
|
261
259
|
data = request.get_json()
|
262
260
|
event_id = data.get('id')
|
263
|
-
checked = data.get('checked')
|
264
261
|
|
265
|
-
if event_id is None
|
266
|
-
return jsonify({'error': 'Missing id
|
267
|
-
|
268
|
-
event_manager.get(event_id).checked = checked
|
262
|
+
if event_id is None:
|
263
|
+
return jsonify({'error': 'Missing id'}), 400
|
264
|
+
event = event_manager.get(event_id)
|
265
|
+
event_manager.get(event_id).checked = not event.checked
|
269
266
|
return jsonify({'message': 'Event updated successfully'}), 200
|
270
267
|
|
271
268
|
@app.route('/get-screenshot', methods=['Post'])
|
@@ -275,8 +272,11 @@ def get_screenshot():
|
|
275
272
|
event_id = data.get('id')
|
276
273
|
if event_id is None:
|
277
274
|
return jsonify({'error': 'Missing id'}), 400
|
278
|
-
|
279
|
-
|
275
|
+
gsm_state.line_for_screenshot = get_line_by_id(event_id)
|
276
|
+
if gsm_state.previous_line_for_screenshot and gsm_state.line_for_screenshot.id == gsm_state.previous_line_for_screenshot.id:
|
277
|
+
open(os.path.join(get_config().paths.folder_to_watch, "previous.mkv"), 'a').close()
|
278
|
+
else:
|
279
|
+
obs.save_replay_buffer()
|
280
280
|
return jsonify({}), 200
|
281
281
|
|
282
282
|
@app.route('/play-audio', methods=['POST'])
|
@@ -286,8 +286,11 @@ def play_audio():
|
|
286
286
|
event_id = data.get('id')
|
287
287
|
if event_id is None:
|
288
288
|
return jsonify({'error': 'Missing id'}), 400
|
289
|
-
|
290
|
-
|
289
|
+
gsm_state.line_for_audio = get_line_by_id(event_id)
|
290
|
+
if gsm_state.previous_line_for_audio and gsm_state.line_for_audio == gsm_state.previous_line_for_audio:
|
291
|
+
open(os.path.join(get_config().paths.folder_to_watch, "previous.mkv"), 'a').close()
|
292
|
+
else:
|
293
|
+
obs.save_replay_buffer()
|
291
294
|
return jsonify({}), 200
|
292
295
|
|
293
296
|
|
@@ -319,8 +322,8 @@ async def websocket_handler(websocket):
|
|
319
322
|
|
320
323
|
async def broadcast_message(message):
|
321
324
|
if connected_clients:
|
322
|
-
|
323
|
-
|
325
|
+
for client in connected_clients:
|
326
|
+
await client.send(json.dumps(message))
|
324
327
|
|
325
328
|
# async def main():
|
326
329
|
# async with websockets.serve(websocket_handler, "localhost", 8765): # Choose a port for WebSocket
|
@@ -356,7 +359,12 @@ def are_lines_selected():
|
|
356
359
|
return any(item.checked for item in event_manager)
|
357
360
|
|
358
361
|
def reset_checked_lines():
|
362
|
+
async def send_reset_message():
|
363
|
+
await broadcast_message({
|
364
|
+
'event': 'reset_checkboxes',
|
365
|
+
})
|
359
366
|
event_manager.reset_checked_lines()
|
367
|
+
asyncio.run(send_reset_message())
|
360
368
|
|
361
369
|
def open_texthooker():
|
362
370
|
webbrowser.open(url + '/texthooker')
|
@@ -373,19 +381,30 @@ def start_web_server():
|
|
373
381
|
|
374
382
|
app.run(port=port, debug=False) # debug=True provides helpful error messages during development
|
375
383
|
|
376
|
-
|
377
|
-
global websocket_port
|
378
|
-
while True:
|
379
|
-
websocket_port = port
|
380
|
-
try:
|
381
|
-
async with websockets.serve(websocket_handler, host, port):
|
382
|
-
logger.debug(f"WebSocket server started at ws://{host}:{port}/")
|
383
|
-
await asyncio.Future() # Keep the WebSocket server running
|
384
|
-
except OSError as e:
|
385
|
-
logger.debug(f"Port {port} is in use. Trying the next port...")
|
386
|
-
port += 1
|
384
|
+
import signal
|
387
385
|
|
386
|
+
async def run_websocket_server(host="0.0.0.0"):
|
387
|
+
global websocket_port
|
388
|
+
websocket = None
|
389
|
+
try:
|
390
|
+
websocket_port = get_config().advanced.texthooker_communication_websocket_port
|
391
|
+
websocket = await websockets.serve(websocket_handler, host, websocket_port)
|
392
|
+
logger.debug(f"WebSocket server started at ws://{host}:{websocket_port}/")
|
393
|
+
await asyncio.Future() # Keep the server running
|
394
|
+
except asyncio.CancelledError:
|
395
|
+
logger.info("WebSocket server shutting down...")
|
396
|
+
except OSError as e:
|
397
|
+
logger.error(f"TextHooker WebSocket server failed to start on port {websocket_port}: {e}")
|
398
|
+
logger.info("You may need to try a different port in GSM's advanced config, and then update that in the Texthooker's settings.")
|
399
|
+
finally:
|
400
|
+
if websocket:
|
401
|
+
websocket.close()
|
402
|
+
await asyncio.sleep(1) # Wait before retrying
|
388
403
|
|
404
|
+
def handle_exit_signal(loop):
|
405
|
+
logger.info("Received exit signal. Shutting down...")
|
406
|
+
for task in asyncio.all_tasks(loop):
|
407
|
+
task.cancel()
|
389
408
|
|
390
409
|
async def texthooker_page_coro():
|
391
410
|
# Run the WebSocket server in the asyncio event loop
|
@@ -397,7 +416,10 @@ async def texthooker_page_coro():
|
|
397
416
|
await run_websocket_server()
|
398
417
|
|
399
418
|
def run_text_hooker_page():
|
400
|
-
|
419
|
+
try:
|
420
|
+
asyncio.run(texthooker_page_coro())
|
421
|
+
except KeyboardInterrupt:
|
422
|
+
logger.info("Shutting down due to KeyboardInterrupt.")
|
401
423
|
|
402
424
|
if __name__ == '__main__':
|
403
|
-
asyncio.run(
|
425
|
+
asyncio.run(texthooker_page_coro())
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: GameSentenceMiner
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.9.1
|
4
4
|
Summary: A tool for mining sentences from games. Update: Multi-Line Mining! Fixed!
|
5
5
|
Author-email: Beangate <bpwhelan95@gmail.com>
|
6
6
|
License: MIT License
|
@@ -38,6 +38,7 @@ Requires-Dist: pygetwindow; sys_platform == "win32"
|
|
38
38
|
Requires-Dist: flask
|
39
39
|
Requires-Dist: groq
|
40
40
|
Requires-Dist: obsws-python
|
41
|
+
Requires-Dist: Flask-SocketIO
|
41
42
|
Dynamic: license-file
|
42
43
|
|
43
44
|
# GameSentenceMiner (GSM)
|
@@ -152,6 +153,8 @@ If you encounter issues, please ask for help in my [Discord](https://discord.gg/
|
|
152
153
|
|
153
154
|
* [OBS](https://obsproject.com/) and [FFMPEG](https://ffmpeg.org/), without which GSM would not be possible.
|
154
155
|
|
156
|
+
* [Renji's Texthooker](https://github.com/Renji-XD/texthooker-ui)
|
157
|
+
|
155
158
|
## Donations
|
156
159
|
|
157
160
|
If you've found this or any of my other projects helpful, please consider supporting my work through [GitHub Sponsors](https://github.com/sponsors/bpwhelan) or [Ko-fi](https://ko-fi.com/beangate).
|
@@ -1,24 +1,24 @@
|
|
1
1
|
GameSentenceMiner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
GameSentenceMiner/anki.py,sha256=
|
3
|
-
GameSentenceMiner/config_gui.py,sha256=
|
4
|
-
GameSentenceMiner/configuration.py,sha256=
|
2
|
+
GameSentenceMiner/anki.py,sha256=JnVfFkLpEfWaPfOLngU0PSQq4vrgWuhd_VLYZEBqNTY,14608
|
3
|
+
GameSentenceMiner/config_gui.py,sha256=h4zz85gfhxSphaJ-IZSu9D4jR70mDlKecZ9JRCO5Noc,80927
|
4
|
+
GameSentenceMiner/configuration.py,sha256=8CfdTJ0ROJrxyzNg3NaElAVS1bwchg1ih6XfhfDZy1g,25492
|
5
5
|
GameSentenceMiner/electron_config.py,sha256=dGcPYCISPehXubYSzsDuI2Gl092MYK0u3bTnkL9Jh1Y,9787
|
6
|
-
GameSentenceMiner/ffmpeg.py,sha256=
|
7
|
-
GameSentenceMiner/gametext.py,sha256=
|
8
|
-
GameSentenceMiner/gsm.py,sha256
|
6
|
+
GameSentenceMiner/ffmpeg.py,sha256=zVmLJOsXpy71zKb0cLBPrXJ6YpjPVRJmH0uRfd5O30k,18299
|
7
|
+
GameSentenceMiner/gametext.py,sha256=32e7w0qGXYNRRNpLzj9XIwtuto-E6ogEcyl6DC_MPbw,6200
|
8
|
+
GameSentenceMiner/gsm.py,sha256=_Mp_gZFomeFz9FTZqYEXIgqxbICYcAB06KUlFkClX5Q,29831
|
9
9
|
GameSentenceMiner/model.py,sha256=1lRyJFf_LND_4O16h8CWVqDfosLgr0ZS6ufBZ3qJHpY,5699
|
10
10
|
GameSentenceMiner/notification.py,sha256=pXKoLfmRQLH55IQ5G6uxdMuczqX7D6l3ubVEY1e6hXg,2859
|
11
|
-
GameSentenceMiner/obs.py,sha256=
|
11
|
+
GameSentenceMiner/obs.py,sha256=DoUJk00Gk0Idley7CEldfIobqJ9na2UBlCv7nclZO4s,14793
|
12
12
|
GameSentenceMiner/obs_back.py,sha256=_N_UV7Nh5cyy3mnH5lOUOzhgZwHMACeFEuBo1Z-bNzg,10894
|
13
13
|
GameSentenceMiner/package.py,sha256=YlS6QRMuVlm6mdXx0rlXv9_3erTGS21jaP3PNNWfAH0,1250
|
14
14
|
GameSentenceMiner/ss_selector.py,sha256=csey9H3561-guRJcT6gQN6hXxvylP0CBI0dp2-kwo2Q,4446
|
15
|
-
GameSentenceMiner/text_log.py,sha256=
|
15
|
+
GameSentenceMiner/text_log.py,sha256=U2_g8THAYeexRiE2bLk_bCt_2ShiA8SQ9VdJsi4riHs,5181
|
16
16
|
GameSentenceMiner/util.py,sha256=PrDNnxWiJZh1lGuwnp3DjWIlwbkVxweRTYWLtQk94Ao,9122
|
17
17
|
GameSentenceMiner/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
18
|
GameSentenceMiner/ai/ai_prompting.py,sha256=xw8et6XNwQiDXOXZnw8iIntVSg8lni4YYZbgWsK7qDE,10013
|
19
19
|
GameSentenceMiner/communication/__init__.py,sha256=_jGn9PJxtOAOPtJ2rI-Qu9hEHVZVpIvWlxKvqk91_zI,638
|
20
20
|
GameSentenceMiner/communication/send.py,sha256=X0MytGv5hY-uUvkfvdCqQA_ljZFmV6UkJ6in1TA1bUE,217
|
21
|
-
GameSentenceMiner/communication/websocket.py,sha256=
|
21
|
+
GameSentenceMiner/communication/websocket.py,sha256=8eFZaTtoFggEPdqw2Jl4zqHC2I7J3-Gk27CxVX7SyBo,3277
|
22
22
|
GameSentenceMiner/downloader/Untitled_json.py,sha256=RUUl2bbbCpUDUUS0fP0tdvf5FngZ7ILdA_J5TFYAXUQ,15272
|
23
23
|
GameSentenceMiner/downloader/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
24
24
|
GameSentenceMiner/downloader/download_tools.py,sha256=aRfpCqEmKUFRVsGipwY-7PhY6AeWiFJanW4ZCB9e2iE,8124
|
@@ -27,21 +27,23 @@ GameSentenceMiner/ocr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3h
|
|
27
27
|
GameSentenceMiner/ocr/gsm_ocr_config.py,sha256=fEQ2o2NXksGRHpueO8c4TfAp75GEdAtAr1ngTFOsdpg,2257
|
28
28
|
GameSentenceMiner/ocr/ocrconfig.py,sha256=_tY8mjnzHMJrLS8E5pHqYXZjMuLoGKYgJwdhYgN-ny4,6466
|
29
29
|
GameSentenceMiner/ocr/owocr_area_selector.py,sha256=Q8ETMHL7BKMA1mbtjrntDLyqCQB0lZ5T4RCZsodjH7Y,47186
|
30
|
-
GameSentenceMiner/ocr/owocr_helper.py,sha256=
|
30
|
+
GameSentenceMiner/ocr/owocr_helper.py,sha256=M4Is-Ki5O3r4ixYhILibfjrVGD6xDlOcR3YvVGmETQ4,17363
|
31
31
|
GameSentenceMiner/owocr/owocr/__init__.py,sha256=opjBOyGGyEqZCE6YdZPnyt7nVfiwyELHsXA0jAsjm14,25
|
32
32
|
GameSentenceMiner/owocr/owocr/__main__.py,sha256=XQaqZY99EKoCpU-gWQjNbTs7Kg17HvBVE7JY8LqIE0o,157
|
33
33
|
GameSentenceMiner/owocr/owocr/config.py,sha256=qM7kISHdUhuygGXOxmgU6Ef2nwBShrZtdqu4InDCViE,8103
|
34
34
|
GameSentenceMiner/owocr/owocr/lens_betterproto.py,sha256=oNoISsPilVVRBBPVDtb4-roJtAhp8ZAuFTci3TGXtMc,39141
|
35
|
-
GameSentenceMiner/owocr/owocr/ocr.py,sha256=
|
35
|
+
GameSentenceMiner/owocr/owocr/ocr.py,sha256=V0HqVRQlaE1-12IH480IupfSv1BlDdEcwNPejhQZfS0,42292
|
36
36
|
GameSentenceMiner/owocr/owocr/run.py,sha256=0UyjOKEP0MqSdCaagCUMGdqO-BMexPxCl7ZabGlic4E,54749
|
37
37
|
GameSentenceMiner/owocr/owocr/screen_coordinate_picker.py,sha256=Na6XStbQBtpQUSdbN3QhEswtKuU1JjReFk_K8t5ezQE,3395
|
38
38
|
GameSentenceMiner/vad/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
39
|
-
GameSentenceMiner/vad/
|
40
|
-
GameSentenceMiner/vad/
|
41
|
-
GameSentenceMiner/vad/
|
42
|
-
GameSentenceMiner/vad/
|
39
|
+
GameSentenceMiner/vad/groq_trim.py,sha256=MDYiApduwF7oDx3r0TXL3xQrTkbUC1RinMwNKSbF5gw,3764
|
40
|
+
GameSentenceMiner/vad/result.py,sha256=aFlr2px90fn3qXj49dwF9BDXA5m4yXD_HYH01CVvP1U,799
|
41
|
+
GameSentenceMiner/vad/silero_trim.py,sha256=ACvIdfjeCku6XWeUdi1zThBDvynJ01gjMFpSPWQALjg,2240
|
42
|
+
GameSentenceMiner/vad/vad_utils.py,sha256=_YC6rW2eXSBeLnYbVl_F3na1KCRL90VrnOzKYJ9RhUE,391
|
43
|
+
GameSentenceMiner/vad/vosk_helper.py,sha256=h7yNHrzrzT-J74UniA0T2ZX8cHqhflCzwyDjoIdKLO4,6479
|
44
|
+
GameSentenceMiner/vad/whisper_helper.py,sha256=B64-Eq_ZMCIyQX_A8uvYz-c48hSXJAyz6tSXNRaLjtA,4020
|
43
45
|
GameSentenceMiner/web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
44
|
-
GameSentenceMiner/web/texthooking_page.py,sha256=
|
46
|
+
GameSentenceMiner/web/texthooking_page.py,sha256=alXNkpm2Kl-ewYIm_aw24_8RdcYedLB59y6YTkp_mrE,14789
|
45
47
|
GameSentenceMiner/web/static/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
46
48
|
GameSentenceMiner/web/static/apple-touch-icon.png,sha256=OcMI8af_68DA_tweOsQ5LytTyMwm7-hPW07IfrOVgEs,46132
|
47
49
|
GameSentenceMiner/web/static/favicon-96x96.png,sha256=lOePzjiKl1JY2J1kT_PMdyEnrlJmi5GWbmXJunM12B4,16502
|
@@ -52,11 +54,12 @@ GameSentenceMiner/web/static/style.css,sha256=bPZK0NVMuyRl5NNDuT7ZTzVLKlvSsdmeVH
|
|
52
54
|
GameSentenceMiner/web/static/web-app-manifest-192x192.png,sha256=EfSNnBmsSaLfESbkGfYwbKzcjKOdzuWo18ABADfN974,51117
|
53
55
|
GameSentenceMiner/web/static/web-app-manifest-512x512.png,sha256=wyqgCWCrLEUxSRXmaA3iJEESd-vM-ZmlTtZFBY4V8Pk,230819
|
54
56
|
GameSentenceMiner/web/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
57
|
+
GameSentenceMiner/web/templates/index.html,sha256=HZKiIjiGJV8PGQ9T2aLDUNSfJn71qOwbYCjbRuSIjpY,213583
|
55
58
|
GameSentenceMiner/web/templates/text_replacements.html,sha256=tV5c8mCaWSt_vKuUpbdbLAzXZ3ATZeDvQ9PnnAfqY0M,8598
|
56
|
-
GameSentenceMiner/web/templates/utility.html,sha256=
|
57
|
-
gamesentenceminer-2.
|
58
|
-
gamesentenceminer-2.
|
59
|
-
gamesentenceminer-2.
|
60
|
-
gamesentenceminer-2.
|
61
|
-
gamesentenceminer-2.
|
62
|
-
gamesentenceminer-2.
|
59
|
+
GameSentenceMiner/web/templates/utility.html,sha256=3flZinKNqUJ7pvrZk6xu__v67z44rXnaK7UTZ303R-8,16946
|
60
|
+
gamesentenceminer-2.9.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
61
|
+
gamesentenceminer-2.9.1.dist-info/METADATA,sha256=3SHKdq8q35tQXbi0x_4zQAekXgVPf-le5kKpSmdfSHY,7314
|
62
|
+
gamesentenceminer-2.9.1.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
|
63
|
+
gamesentenceminer-2.9.1.dist-info/entry_points.txt,sha256=2APEP25DbfjSxGeHtwBstMH8mulVhLkqF_b9bqzU6vQ,65
|
64
|
+
gamesentenceminer-2.9.1.dist-info/top_level.txt,sha256=V1hUY6xVSyUEohb0uDoN4UIE6rUZ_JYx8yMyPGX4PgQ,18
|
65
|
+
gamesentenceminer-2.9.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|