"""Проверка опубликованных проектов: встроенный Python FEMM 5, шесть полей.
Эталонные таблицы и модели не перезаписываются. Полный поиск — в run.py.
"""
import os
import sys
import json
import hashlib
import binascii

script = globals().get('__file__') or (sys.argv[0] if sys.argv else '')
if not script or not os.path.isfile(script):
    raise RuntimeError('Запустите сохранённый reproduce.py командой Run Script.')
os.chdir(os.path.dirname(os.path.abspath(script)))
with open('manifest.json') as stream:
    manifest = json.load(stream)
for item in manifest['files']:
    with open(item['path'], 'rb') as stream:
        actual = binascii.hexlify(hashlib.sha256(stream.read()).digest()).decode()
    assert actual == item['sha256'], 'Изменён файл эталона: '+item['path']
exec(open('model.py').read())
with open('results.json') as stream:
    reference = json.load(stream)
index = 1
while os.path.exists('reproduced-%02d' % index):
    index += 1
folder = 'reproduced-%02d' % index
os.mkdir(folder)
ids = [reference['baseline_id'], reference['selected_id']]
for item in reference['verification']:
    if item['kind'] in ['finer_mesh', 'larger_domain']:
        ids.append(item['id'])
ids += [reference['coenergy_check']['minus_id'], reference['coenergy_check']['plus_id']]
rows = []
for count, field_id in enumerate(ids):
    old = reference['evaluations'][field_id]
    new = field(old['r_mm'], old['t_mm'], folder, 'check-%02d' % count,
                old['mesh_scale'], old['outer_radius_mm'], old['gap_mm'])
    new['reference_id'] = field_id
    new['force_relative_difference'] = new['force_N']/old['force_N']-1
    new['power_relative_difference'] = new['power_copper_W']/old['power_copper_W']-1
    assert abs(new['force_relative_difference']) < 0.005
    assert abs(new['power_relative_difference']) < 1e-9
    assert new['energy_identity_relative'] < 0.005
    if count < 4:
        assert new['feasible']
    rows.append(new)
dg = reference['coenergy_check']['dg_mm']
force_energy = -(rows[-1]['coenergy_J']-rows[-2]['coenergy_J'])/(2*dg*1e-3)
relative = force_energy/rows[2]['force_N']-1
assert abs(relative) < 0.02
receipt = {'schema': 'femm5-actuator-replay-v1', 'passed': True,
           'fields': rows, 'coenergy_force_N': force_energy,
           'coenergy_vs_WST_relative': relative,
           'source_manifest_verified': True,
           'runtime': 'Встроенный MicroPython FEMM 5; без внешнего контроллера'}
with open(os.path.join(folder, 'replay.json'), 'w') as stream:
    json.dump(receipt, stream)
print('Проверка завершена:', folder, 'полей:', len(rows))
