Files
oxTTT/generate.py

124 lines
5.9 KiB
Python

import itertools, os, sys
try: from tqdm import tqdm
except: pass
args = sys.argv
help_mode = "help" in args
file_mode = "file" in args
server_mode = "server" in args
path = list(filter(lambda x: x.endswith("/") or x.endswith("\\"), args))
if help_mode:
print(f'Usage: python generate.py [args]')
print(f'Args:')
print(f'\thelp - Show this message')
print(f'\tfile - File mode with .html extension')
print(f'\tserver - Server mode without .html extension for use folder as static pages')
print(f'\t[path]/ - Directory for save pages')
exit(0)
else:
if file_mode and server_mode:
print("args 'file' and 'server' is incompatible")
exit(1)
elif not (file_mode or server_mode):
print("args 'file' or 'server' is required")
exit(1)
elif len(path) > 1:
print("args must contain only one path (optional)")
exit(1)
if len(path) == 0: path = "static/"
else: path = path[0]
def check_win(board) -> str:
lines = [
[0, 1, 2], [3, 4, 5], [6, 7, 8], # rows
[0, 3, 6], [1, 4, 7], [2, 5, 8], # columns
[0, 4, 8], [2, 4, 6] # diagonals
]
return next((board[line[0]] for line in lines if board[line[0]] == board[line[1]] == board[line[2]] != '-'), '-')
minify = lambda s: s.replace('\n', '').replace('\t', '').replace(' ', '')
style = minify("""
body{margin:0;padding:20px;font-family:Arial,sans-serif;text-align:center;background:#fff}h1{font-size:24px;margin-bottom:20px}
a{text-decoration:none}img{width:10vw}a,h1 a{color:#007bff}table{margin:0 auto;border-collapse:collapse;max-width:100%;overflow-x:auto}
td,td a{line-height:50px}td{border:1px solid #ccc;padding:10px;width:50px;height:50px;text-align:center;font-size:18px;vertical-align:middle}
td a{display:block;width:100%;height:100%;color:#007bff}td:hover{background:#eee}@media (max-width:600px){body{padding:10px}img{width:20vw}
h1{font-size:20px;margin-bottom:10px}td{padding:5px;width:40px;height:40px;font-size:16px}td,td a{line-height:40px}}""")
apply_css = minify(f"const style=document.createElement('style');style.textContent='{style}';document.head.appendChild(style);")
preload = minify("""
document.addEventListener('mouseover', e => {
const a = e.target.closest('a[href]');
if (!a) return;
if (!a.dataset.prefetched) {
a.dataset.prefetched = true;
fetch(a.href, {mode: 'no-cors'});
}
});
""")
pages = {
'index':
minify(f"""<meta name="viewport" content="width=device-width,initial-scale=1">
<meta property="og:url" content="http://0x174.su/tic/tac/toe/index.html">
<title>oxTicTacToe</title><img src="/favicon.ico"><h1>oxTicTacToe.html</h1>
<p>Select team for start [ <a href="o---------.html">O</a> | <a href="x---------.html">X</a> ]
{'<br/><a href="../../../multiplayer">multiplayer mode</a>' if server_mode else ''}</p>
<a href="https://git.0x174.su/wowlikon/oxTTT">source code</a>
<script src="{'s' if file_mode else 'a'}.js"></script>""")
}
scripts = {
's': apply_css,
'p': preload,
'a': (apply_css+preload)
}
try: iterable = tqdm(itertools.product('-xo', repeat=10))
except: iterable = itertools.product('-xo', repeat=10)
for field_tuple in iterable:
field = ''.join(field_tuple)
if abs(field.count('x') - field.count('o')) > 1 or field[0] == '-': continue
win = check_win(list(field[1:]))
np = "x" if field.startswith("o") else "o"
line = lambda n: (np + field[1:])[:n] + field[0] + (np + field[1:])[n+1:] + '.html'
if win != '-':
line = lambda n: "index.html"
title = f'WIN {win}'
elif '-' not in field:
line = lambda n: "index.html"
title = f'Draft'
else: title = field[0]
content = minify(f"""<meta name="viewport" content="width=device-width,initial-scale=1">
<meta property="og:url" content="http://0x174.su/tic/tac/toe/{field}.html"><title>oxTTT:{title}</title><h1><a href="{line(0)}">{title}</a></h1>
<table>
<tr>
<td>{'' if field[1] != '-' else f'<a href="{line(1)}">'}{field[1].replace('-', '')}{'' if field[1] != '-' else '</a>'}</td>
<td>{'' if field[2] != '-' else f'<a href="{line(2)}">'}{field[2].replace('-', '')}{'' if field[2] != '-' else '</a>'}</td>
<td>{'' if field[3] != '-' else f'<a href="{line(3)}">'}{field[3].replace('-', '')}{'' if field[3] != '-' else '</a>'}</td>
</tr>
<tr>
<td>{'' if field[4] != '-' else f'<a href="{line(4)}">'}{field[4].replace('-', '')}{'' if field[4] != '-' else '</a>'}</td>
<td>{'' if field[5] != '-' else f'<a href="{line(5)}">'}{field[5].replace('-', '')}{'' if field[5] != '-' else '</a>'}</td>
<td>{'' if field[6] != '-' else f'<a href="{line(6)}">'}{field[6].replace('-', '')}{'' if field[6] != '-' else '</a>'}</td>
</tr>
<tr>
<td>{'' if field[7] != '-' else f'<a href="{line(7)}">'}{field[7].replace('-', '')}{'' if field[7] != '-' else '</a>'}</td>
<td>{'' if field[8] != '-' else f'<a href="{line(8)}">'}{field[8].replace('-', '')}{'' if field[8] != '-' else '</a>'}</td>
<td>{'' if field[9] != '-' else f'<a href="{line(9)}">'}{field[9].replace('-', '')}{'' if field[9] != '-' else '</a>'}</td>
</tr>
</table><script src="{'s' if file_mode else 'a'}.js"></script>""")
pages[field] = f"{'<a href=\"../index.html\">' if win != '-' else ''}{content}{'</a>' if win != '-' else ''}"
os.makedirs(path, exist_ok=True)
for filename, content in pages.items():
with open(f'{path}{filename}{".html" if file_mode else ""}', 'w+', encoding='utf-8') as f:
f.write(('<meta property="og:type" content="website">' if server_mode else '')+(content.replace('.html', '') if server_mode else content))
for filename, content in scripts.items():
with open(f'{path}{filename}.js', 'w+', encoding='utf-8') as f:
f.write(content)
with open(f'{path}s.css', 'w+', encoding='utf-8') as f:
f.write(style)