Files
product-vamp/tests/position_fixtures.py
khodowany 3f63b255ac
ci / checks (push) Failing after 23m26s
Fix Playability
2026-10-08 19:04:06 -05:00

38 lines
1.7 KiB
Python

"""Independent exhaustive oracle for small grip/hand placement examples."""
import itertools
def regions(shape):
return tuple(h for h in range(1, 13) if all(h <= p.fret <= h + 3 for p in shape)) if shape else tuple([0])
def movement(a, b, ha, hb, acoustic=False):
if not a or not b:
return 0, 0
if len(a) == len(b) == 1:
pairs, unmatched = [(a[0], b[0])], 0
else:
def voices(shape):
return {('bass' if acoustic and p.string_number in (5, 6) else p.string_number): p for p in shape}
x, y = voices(a), voices(b)
pairs = [(x[s], y[s]) for s in x.keys() & y.keys()]
unmatched = len(x.keys() ^ y.keys())
return abs(ha - hb), unmatched + sum(abs((p.fret - ha) - (q.fret - hb)) + abs(p.string_number - q.string_number) for p, q in pairs)
def cost(path, costs, indices, *, acoustic=False, left=(), right=(), close=False, hands=None, left_hand=None, right_hand=None):
travel, peak, effort = indices
base = [sum(costs[i][v][j] for i, v in enumerate(path)) for j in range(len(costs[0][path[0]]))]
results = []
for positions in [hands] if hands is not None else itertools.product(*(regions(v) for v in path)):
for lh in [left_hand] if left_hand is not None else regions(left):
for rh in [positions[0]] if close else [right_hand] if right_hand is not None else regions(right):
points = [(left, lh), *zip(path, positions), (path[0] if close else right, rh)]
total = base.copy()
total[peak] = max(h for _, h in points)
for (a, ha), (b, hb) in zip(points, points[1:]):
shift, ergonomics = movement(a, b, ha, hb, acoustic)
total[travel] += shift
total[effort] += ergonomics
results.append(tuple(total))
return min(results)