# The search's best two-frame lattice, through Starlock's real glow path (pipe_t.py), beside the shipped IGN flip;
# and the "squeeze" that the simple model can't tell apart from it. Prints out/lattice-path.txt (about 20 minutes on
# 4 cores; the IGN rows are in out/pipe.txt).
#
# On a 2x screen the painterly pass reads every second device pixel, so a lattice must be scaled to the pixel ratio:
#   latstill  (54,11)/112 per device pixel: each set of pixels the pass reads holds the best still lattice (54,11)/56
#   latflip   the search's form for two frames: (54,11)/224 per device pixel plus half a step every other frame, so
#             each set the pass reads holds (54,11,56)/112 (up to a constant offset of 1/448), whose two-frame blend is (54,11)/56 on half-height
#             steps; every frame uses the whole range of thresholds
#   latsq     the squeeze, (d + t mod 2) / 2 with d = (54,11)/112: the same two-frame blend, but frame 0's
#             thresholds all lie below 1/2 and frame 1's above, so every frame on its own is biased
import sys
import numpy as np
from multiprocessing import Pool
import pipe_t as P

orig = P.field
def field(kind, x, y, t):
    xi = np.floor(x).astype(np.int64); yi = np.floor(y).astype(np.int64)
    if kind == 'latstill': return (((54 * xi + 11 * yi) % 112) + .5) / 112
    if kind == 'latflip': return ((((54 * xi + 11 * yi) % 224) + .5) / 224 + .5 * (t % 2)) % 1
    if kind == 'latsq': return ((((54 * xi + 11 * yi) % 112) + .5) / 112 + (t % 2)) / 2
    return orig(kind, x, y, t)
P.field = field

if __name__ == '__main__':
    kinds = sys.argv[1:] or ['latstill', 'latflip', 'latsq']
    jobs = [(s, k, R) for R in (5, 0) for s in P.scenes() for k in kinds]
    with Pool(4) as pool:
        out = pool.map(P.case, jobs, chunksize=1)
    print('as out/pipe.txt: band / grain in L* per eye model; JND (generous model, and its dark variant): grain, shimmer at 60 fps, at 30 fps')
    for s, k, R, res, s60, s30, d60, d30 in out:
        print(f'paint {"on " if R else "off"} {s:6s} {k:9s} ' + ' '.join(f'{b:6.3f} {g:6.3f}' for b, g in res) + f'   {s60[0]:10.2f} {s60[1]:11.2f} {s30[1]:5.2f} | {d60[0]:11.2f} {d60[1]:4.2f} {d30[1]:4.2f}')
