gea-program 0.46.0__tar.gz → 0.47.0__tar.gz
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.
- {gea_program-0.46.0 → gea_program-0.47.0}/PKG-INFO +13 -1
- {gea_program-0.46.0 → gea_program-0.47.0}/README.md +12 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/__init__.py +1 -1
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/__main__.py +38 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/acceptance_tests.py +153 -0
- gea_program-0.47.0/gea/help/rig-time.md +15 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/helplib.py +2 -1
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/invoice_check.py +12 -2
- gea_program-0.47.0/gea/rig_state.py +651 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/service.py +14 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/web/app.html +59 -2
- {gea_program-0.46.0 → gea_program-0.47.0}/gea_program.egg-info/PKG-INFO +13 -1
- {gea_program-0.46.0 → gea_program-0.47.0}/gea_program.egg-info/SOURCES.txt +2 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/pyproject.toml +1 -1
- {gea_program-0.46.0 → gea_program-0.47.0}/LICENSE +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/BENCH_TEST_PROTOCOL.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/accuracy_statement.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/alarm_engine.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/alerts.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/backup.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/bench.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/blind_harness.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/acex_lomonosov_age_depth_model.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/acex_lomonosov_age_depth_model.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/agassiz77_canada_temperature.csv +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/agassiz77_canada_temperature.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/barbados_110_consolidation.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/barbados_110_consolidation.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/bengal_u1452_grain_size.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/bengal_u1452_grain_size.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/blake_164_methane_isotopes.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/blake_164_methane_isotopes.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/collingwood_1_28_ks_complete.las +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/collingwood_1_28_ks_complete.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/costa_rica_odp_friction_envelope.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/costa_rica_odp_friction_envelope.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/dsdp_504b_physical_properties.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/dsdp_504b_physical_properties.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/dsdp_504b_sound_velocity.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/dsdp_504b_sound_velocity.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/elgygytgyn_5011_turbidites.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/elgygytgyn_5011_turbidites.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/epica_domec_co2_800kyr.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/epica_domec_co2_800kyr.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/fram_909_organic_petrography.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/fram_909_organic_petrography.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/gbr_325_coral_uth_ages.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/gbr_325_coral_uth_ages.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/gisp2_greenland_temperature.csv +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/gisp2_greenland_temperature.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/gom_308_t2p_insitu.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/gom_308_t2p_insitu.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/guaymas_385_dom_d13c.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/guaymas_385_dom_d13c.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/hikurangi_u1520_friction_insitu.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/hikurangi_u1520_friction_insitu.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/iodp_u1324_pore_pressure.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/iodp_u1324_pore_pressure.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/jfast_c0019_slow_slip_events.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/jfast_c0019_slow_slip_events.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/kennetcook_2_p129_excerpt.las +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/kennetcook_2_p129_excerpt.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/ktb_hb_bhgm_density.dat +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/ktb_hb_bhgm_density.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/ktb_hb_complog_6020_excerpt.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/ktb_hb_complog_6020_excerpt.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/ktb_hb_hlog246_temperature.dat +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/ktb_hb_hlog246_temperature.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/ktb_hb_rockmech_compress.dat +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/ktb_hb_rockmech_compress.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.dat +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/ktb_vb_rockmech_compress.dat +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/ktb_vb_rockmech_compress.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/ktb_vb_vlog251_temperature.dat +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/ktb_vb_vlog251_temperature.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/l06_06_nl_survey.csv +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/l06_06_nl_survey.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/l07_01_nl_excerpt.las +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/l07_01_nl_excerpt.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/mariana_1200_serpentinite_geochem.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/mariana_1200_serpentinite_geochem.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/med_160_sapropels.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/med_160_sapropels.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/nankai_megasplay_shear_strength.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/nankai_megasplay_shear_strength.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/odp_1027b_thermal_conductivity.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/odp_1027b_thermal_conductivity.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/odp_1027c_cork_temperature.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/odp_1027c_cork_temperature.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/odp_1165b_thermal_conductivity.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/odp_1165b_thermal_conductivity.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/odp_504b_dike_elastic_moduli.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/odp_504b_dike_elastic_moduli.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/odp_504b_leg137_borehole_fluids.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/odp_504b_leg137_borehole_fluids.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/peru_201_sulfate_reduction.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/peru_201_sulfate_reduction.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/scorpio_e1_sa_excerpt.las +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/scorpio_e1_sa_excerpt.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/sumatra_362_cohesion.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/sumatra_362_cohesion.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/university_6_17_no1_tx_excerpt.las +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/university_6_17_no1_tx_excerpt.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/ursa_308_xrd_mineralogy.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/ursa_308_xrd_mineralogy.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/volve_15_9_19_sr_excerpt.las +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/volve_15_9_19_sr_excerpt.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/volve_15_9_19a_core_excerpt.csv +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/volve_15_9_19a_core_excerpt.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/volve_f12_f14_production_excerpt.csv +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/volve_f12_f14_production_excerpt.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/walvis_208_petm_carbonate.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/walvis_208_petm_carbonate.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/woodlark_1109_rock_eval.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog/woodlark_1109_rock_eval.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog_map.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/catalog_register.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/certificates.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/cli.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/client_reports.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/config_versioning.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/conformance.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/control_room.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/correlation.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/dashboard.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/declarations.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/deviation.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/dlis.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/dnp3.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/doctor.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/dossier.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/dossier_verify.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/downhole_engine.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/drift_monitor.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/drill_string.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/earth_model.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/economics.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/ed25519.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/edr.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/elevation.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/etp.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/etp12_schemas.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/example_register_map.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/fat_sat.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/files.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/fixtures/README.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/fixtures/comcat_delaware_basin_2026-09.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/fixtures/comcat_mahoning_1990-2026.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/fixtures/comcat_youngstown_2011-2012.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/fixtures/ne_110m_coastline.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/follower.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/forward_model.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/friction_priors.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/gamma.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/gauge_aging.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/gauge_specs.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/geodesy.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/gravity_reference.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/hartip.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/TESTER_GUIDE.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/alarms.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/alerts.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/audit-update.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/backup.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/catalog.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/charts.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/conformance.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/control-room.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/data-in.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/declare.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/dlis.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/doctor.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/dossier.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/drift.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/drillstring.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/economics.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/edr.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/etp.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/field-ports.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/files.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/historian.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/instruments.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/interval.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/invoice-check.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/map.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/month-end.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/notifications.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/opseis.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/osdu.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/pad-summary.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/patches.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/penetrator.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/ppdm.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/quakeml.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/quality.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/report-history.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/seedlink.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/seismic.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/setup.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/simulation.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/site.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/sites.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/slip.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/soak.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/sra.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/start.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/structure.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/tools.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/transients.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/upkeep.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/vibration.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/well-report.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/well-tests.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/help/well3d.md +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/housekeeping.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/interval.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/inverse_engine.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/jobs.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/live_ports.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/loadtest.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/matplotlib_demo.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/modbus.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/modbus_rtu.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/model_card.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/month_end.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/mqtt_port.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/notify.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/op_seismicity.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/opcua_port.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/operator_app.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/osdu.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/pad_summary.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/patches.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/pdf_report.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/penetrator.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/permits.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/piwebapi.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/ports.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/ppdm.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/profile_catalog.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/project.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/qt6_downhole_app.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/quakeml.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reconciler.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/IU_ANMO_10_BHZ_response.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/IU_ANMO_10_BHZ_response.xml +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/eia_henry_hub_daily.csv.gz +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/eia_prices.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/eia_wti_daily.csv.gz +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/libmseed_steim.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/libmseed_steim1_4096.mseed +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/libmseed_steim2_4096.mseed +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/libmseed_steim2_512.mseed +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/mahoning_example.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/mud_motor_specs.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/penetrator_ratings.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/seismicity_protocols.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/tool_sources.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/us_outline.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/us_outline.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/volve_3d.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/volve_f4_interpretation.las.gz +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/volve_f4_logs.provenance.json +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/volve_f4_lwd.las.gz +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/volve_surfaces.json.gz +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/volve_traj_F-10.xml.gz +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/volve_traj_F-4.xml.gz +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/volve_traj_F-5_12.25in.xml.gz +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/volve_traj_F-5_17.5in.xml.gz +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/volve_traj_F-5_36in.xml.gz +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/volve_traj_F-5_8.5in.xml.gz +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/reference/volve_well_picks.csv.gz +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/report_history.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/rock_inventory.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/sample_record.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/sample_well_profile.csv +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/sbom.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/seedlink.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/segy.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/seismic.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/seismic_array.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/seismic_assoc.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/seismic_detect.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/seismic_film.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/seismic_harmonic.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/seismic_qc.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/seismic_response.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/seismic_signature.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/seismic_track.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/seismic_uncertainty.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/seismic_unlisted.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/seismic_watch.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/sensor_swap.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/series_cache.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/service_life.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/setup_checklist.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/shapefile.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/shell.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/shut_in.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/simulation.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/site_map.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/sla_report.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/slip.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/soak.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/sra.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/store_forward.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/strata_join.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/structure.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/supervisor.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/survey_cmd.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/survey_view.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/telemetry.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/tool_catalog.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/tool_library.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/tool_taxonomy.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/transient.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/vibration.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/well3d.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/well_assembler.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/well_report.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/well_test_validation.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/wits0.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/witsml.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea/workspace.py +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea_program.egg-info/dependency_links.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea_program.egg-info/entry_points.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea_program.egg-info/requires.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/gea_program.egg-info/top_level.txt +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/setup.cfg +0 -0
- {gea_program-0.46.0 → gea_program-0.47.0}/tests/test_acceptance.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gea-program
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.47.0
|
|
4
4
|
Summary: GEA-Program: downhole gauge monitoring - canonical measurement records, quality rules, drift evaluation with a re-fit change log, well-test validation, alarm management, model cards, store-and-forward, monthly SLA measurement, FAT/SAT protocols and a dashboard, generated from live objects in the client's reporting outline.
|
|
5
5
|
Author: Daniel T. Murphy
|
|
6
6
|
License: MPL-2.0
|
|
@@ -648,6 +648,18 @@ against it; `gea seedlink --config ... --hello` prints what a server says of
|
|
|
648
648
|
itself; `gea help seedlink`. A TexNet station is served by EarthScope at
|
|
649
649
|
`rtserve.iris.washington.edu:18000`, network `TX`.
|
|
650
650
|
|
|
651
|
+
### Rig time
|
|
652
|
+
|
|
653
|
+
What the rig did each second of the drilling record, read from the hook
|
|
654
|
+
load, the block, the bit, the pumps and the rotary: drilling, in the slips,
|
|
655
|
+
tripping, circulating, reaming, off the hook. Every drilling connection is
|
|
656
|
+
timed weight to weight with its three parts, every trip by its speed over
|
|
657
|
+
the pipe-handling hours with its breaks beside it, and the time each loses
|
|
658
|
+
against a target - the drilling program's, or this pad's own best quarter -
|
|
659
|
+
is summed per report day and priced at the contract's operating rate. The
|
|
660
|
+
**Rig time** tab, `gea rig-time`, `gea help rig-time`; the invoice check
|
|
661
|
+
shows each day's lost time beside the bill.
|
|
662
|
+
|
|
651
663
|
### The invoice cross-check
|
|
652
664
|
|
|
653
665
|
The drilling contractor's daywork invoice, day by day, against the daily
|
|
@@ -609,6 +609,18 @@ against it; `gea seedlink --config ... --hello` prints what a server says of
|
|
|
609
609
|
itself; `gea help seedlink`. A TexNet station is served by EarthScope at
|
|
610
610
|
`rtserve.iris.washington.edu:18000`, network `TX`.
|
|
611
611
|
|
|
612
|
+
### Rig time
|
|
613
|
+
|
|
614
|
+
What the rig did each second of the drilling record, read from the hook
|
|
615
|
+
load, the block, the bit, the pumps and the rotary: drilling, in the slips,
|
|
616
|
+
tripping, circulating, reaming, off the hook. Every drilling connection is
|
|
617
|
+
timed weight to weight with its three parts, every trip by its speed over
|
|
618
|
+
the pipe-handling hours with its breaks beside it, and the time each loses
|
|
619
|
+
against a target - the drilling program's, or this pad's own best quarter -
|
|
620
|
+
is summed per report day and priced at the contract's operating rate. The
|
|
621
|
+
**Rig time** tab, `gea rig-time`, `gea help rig-time`; the invoice check
|
|
622
|
+
shows each day's lost time beside the bill.
|
|
623
|
+
|
|
612
624
|
### The invoice cross-check
|
|
613
625
|
|
|
614
626
|
The drilling contractor's daywork invoice, day by day, against the daily
|
|
@@ -590,6 +590,18 @@ def main(argv=None) -> int:
|
|
|
590
590
|
p_dz.add_argument("--actor", type=str, default="cli")
|
|
591
591
|
p_dz.add_argument("--json", action="store_true")
|
|
592
592
|
|
|
593
|
+
p_rt = sub.add_parser("rig-time", help="what the rig did each second of the drilling record - drilling, connections, trips, the slips - and the time lost against the pad's own best")
|
|
594
|
+
p_rt.add_argument("--workspace", type=str, required=True)
|
|
595
|
+
p_rt.add_argument("--well", type=str, default=None, help="with --write: one well's report (without it, the pad's)")
|
|
596
|
+
p_rt.add_argument("--write", action="store_true", help="write the client report")
|
|
597
|
+
p_rt.add_argument("--w2w-min", type=str, default=None, help="declare the weight-to-weight connection target, minutes ('' removes it)")
|
|
598
|
+
p_rt.add_argument("--trip-in", type=str, default=None, help="declare the tripping-in target, ft/h")
|
|
599
|
+
p_rt.add_argument("--trip-out", type=str, default=None, help="declare the tripping-out target, ft/h")
|
|
600
|
+
p_rt.add_argument("--source", type=str, default="", help="where the targets came from")
|
|
601
|
+
p_rt.add_argument("--block-weight", type=str, default=None, help="with --well: the block weight in klbf where the estimate is wrong ('' removes it)")
|
|
602
|
+
p_rt.add_argument("--actor", type=str, default="cli")
|
|
603
|
+
p_rt.add_argument("--json", action="store_true")
|
|
604
|
+
|
|
593
605
|
p_iv = sub.add_parser("invoice-check", help="the drilling contractor's daywork invoice, day by day, against the daily drilling reports and the drilling record, at the contract's terms")
|
|
594
606
|
p_iv.add_argument("--workspace", type=str, default=None)
|
|
595
607
|
p_iv.add_argument("--well", type=str, default=None)
|
|
@@ -2356,6 +2368,32 @@ def main(argv=None) -> int:
|
|
|
2356
2368
|
print(f" {os.path.join(ws.reports_dir, e['path'])}")
|
|
2357
2369
|
print(f" key fingerprint {e['fingerprint']}")
|
|
2358
2370
|
return 0
|
|
2371
|
+
elif a.cmd == "rig-time":
|
|
2372
|
+
import json as _json
|
|
2373
|
+
from . import rig_state as _RS
|
|
2374
|
+
from .cli import _safe_stdout
|
|
2375
|
+
from .workspace import Workspace, WorkspaceError
|
|
2376
|
+
_safe_stdout()
|
|
2377
|
+
try:
|
|
2378
|
+
ws = Workspace(a.workspace)
|
|
2379
|
+
if a.w2w_min is not None or a.trip_in is not None or a.trip_out is not None or a.block_weight is not None:
|
|
2380
|
+
if a.block_weight is not None and not a.well:
|
|
2381
|
+
raise ValueError("--block-weight needs --well")
|
|
2382
|
+
s_ = _RS.set_settings(ws, a.actor, a.source, a.w2w_min, a.trip_in, a.trip_out, (a.well, a.block_weight) if a.block_weight is not None else None)
|
|
2383
|
+
print("targets: " + (", ".join(f"{k} {v:g}" for k, v in s_.get("targets", {}).items()) or "none declared")
|
|
2384
|
+
+ "; block weights: " + (", ".join(f"{k} {v:g} klbf" for k, v in s_.get("block_weight_klbf", {}).items()) or "estimated"))
|
|
2385
|
+
return 0
|
|
2386
|
+
if a.write:
|
|
2387
|
+
r_ = _RS.write_report(ws, __version__, a.actor, a.well)
|
|
2388
|
+
print(f"wrote {r_['report_id']}: {r_['paths']['html']}")
|
|
2389
|
+
if r_['paths'].get('pdf'):
|
|
2390
|
+
print(f" printable: {r_['paths']['pdf']}")
|
|
2391
|
+
return 0
|
|
2392
|
+
p_ = _RS.pad(ws)
|
|
2393
|
+
except (KeyError, ValueError, OSError, WorkspaceError) as e:
|
|
2394
|
+
raise SystemExit(f"rig-time: {e.args[0] if e.args else e}")
|
|
2395
|
+
print(_json.dumps(p_, default=str) if a.json else _RS.text(p_))
|
|
2396
|
+
return 0
|
|
2359
2397
|
elif a.cmd == "invoice-check":
|
|
2360
2398
|
import json as _json
|
|
2361
2399
|
from . import invoice_check as _IC
|
|
@@ -10761,6 +10761,158 @@ def section_co_invoice_check(tmp: str) -> None:
|
|
|
10761
10761
|
+ (f" [failed: {', '.join(failed3)}]" if failed3 else ""))
|
|
10762
10762
|
|
|
10763
10763
|
|
|
10764
|
+
def section_cp_rig_time(tmp: str) -> None:
|
|
10765
|
+
"""Section CP - rig time: a recorder export with known answers - three drilling connections of 6, 9 and 15 minutes
|
|
10766
|
+
weight to weight, a 3,000 ft trip out at 2,449 ft/h and in at 3,333 ft/h over their pipe-handling hours, the block's
|
|
10767
|
+
40 klbf - read back to the second; the slips not taken from a light string pushed into a lateral, a depth re-set
|
|
10768
|
+
not taken for pipe moving, the weight off the hook for half an hour not a connection, the slips found from the block
|
|
10769
|
+
when there is no hook load; the targets as the pad's best quarter or as declared, each connection's and trip's time
|
|
10770
|
+
past them, priced at the contract's operating rate and beside each day of the invoice check; the report with its
|
|
10771
|
+
PDF; the API, the CLI, the tab and the help page."""
|
|
10772
|
+
import http.cookiejar
|
|
10773
|
+
import subprocess as _sp
|
|
10774
|
+
import urllib.request
|
|
10775
|
+
import urllib.error
|
|
10776
|
+
from datetime import datetime as _dtm
|
|
10777
|
+
from . import __version__
|
|
10778
|
+
from . import helplib as H
|
|
10779
|
+
from . import invoice_check as IC
|
|
10780
|
+
from . import pdf_report as PDF
|
|
10781
|
+
from . import rig_state as RS
|
|
10782
|
+
from .workspace import Workspace
|
|
10783
|
+
from .service import Service, Users
|
|
10784
|
+
pkg = Path(__file__).parent
|
|
10785
|
+
d = Path(tmp, "cp"); d.mkdir()
|
|
10786
|
+
F = RS.selftest_edr(str(d))
|
|
10787
|
+
E_ = F["expect"]
|
|
10788
|
+
wsp = str(d / "ws"); ws = Workspace.create(wsp, "Pad CP", actor="tester")
|
|
10789
|
+
w1 = ws.add_well_file(F["path"], display="RIG-1", actor="tester")
|
|
10790
|
+
r = RS.well(ws, w1["id"])
|
|
10791
|
+
|
|
10792
|
+
# -- CP1 the states, the connections, the trips ------------------------------------------------------------------
|
|
10793
|
+
cs = r["connections"]
|
|
10794
|
+
tr = {x["direction"]: x for x in r["trips"]}
|
|
10795
|
+
near = lambda a, b, tol: a is not None and abs(a - b) <= tol
|
|
10796
|
+
t = np.arange(0.0, 7200.0)
|
|
10797
|
+
n = len(t)
|
|
10798
|
+
zeros = np.zeros(n)
|
|
10799
|
+
lateral = RS.classify(t, {"hookload": np.full(n, 45.0), "block": 100.0 - t * 0.01, "bit": 15000.0 + t * 1.0, "hole": np.full(n, 25000.0),
|
|
10800
|
+
"flow": zeros, "spp": None, "rpm": zeros}, np.zeros(n, bool), block_weight=40.0)
|
|
10801
|
+
jump_bit = np.where(t < 3600, 9000.0, 9600.0)
|
|
10802
|
+
jump = RS.classify(t, {"hookload": np.full(n, 200.0), "block": np.full(n, 50.0), "bit": jump_bit, "hole": np.full(n, 9700.0), "flow": zeros,
|
|
10803
|
+
"spp": None, "rpm": zeros}, np.zeros(n, bool), block_weight=40.0)
|
|
10804
|
+
hang = RS.classify(t, {"hookload": np.full(n, 40.0), "block": np.full(n, 50.0), "bit": np.full(n, 9000.0), "hole": np.full(n, 9700.0), "flow": zeros,
|
|
10805
|
+
"spp": None, "rpm": zeros}, np.zeros(n, bool), block_weight=40.0)
|
|
10806
|
+
blk = 10.0 + (t % 120.0)
|
|
10807
|
+
nohl = RS.classify(t, {"hookload": None, "block": blk, "bit": np.full(n, 9000.0), "hole": np.full(n, 9700.0), "flow": zeros, "spp": None, "rpm": zeros},
|
|
10808
|
+
np.zeros(n, bool))
|
|
10809
|
+
c1 = {
|
|
10810
|
+
"connections": [round(c["w2w_min"]) for c in cs] == [6, 9, 15] and all(near(c["w2w_min"], e, 0.1) for c, e in zip(cs, E_["connections_w2w_min"]))
|
|
10811
|
+
and all(near(c["slips_min"], e, 0.1) for c, e in zip(cs, E_["slips_min"])) and all(near(c["pre_min"], 1.0, 0.1) and near(c["post_min"], 1.0, 0.1) for c in cs),
|
|
10812
|
+
"trips": set(tr) == {"IN", "OUT"} and near(tr["OUT"]["speed_ft_h"], E_["trip_out_ft_h"], 0.02 * E_["trip_out_ft_h"])
|
|
10813
|
+
and near(tr["IN"]["speed_ft_h"], E_["trip_in_ft_h"], 0.02 * E_["trip_in_ft_h"]) and near(tr["OUT"]["feet"], 3000, 30) and tr["OUT"]["connections"] >= 29
|
|
10814
|
+
and near(tr["OUT"]["moving_speed_ft_h"], 6000, 600),
|
|
10815
|
+
"states": near(r["hours"]["ROTARY DRILLING"], 2.0, 0.02) and r["hours"]["SLIDE DRILLING"] == 0 and r["hours"]["OFF THE HOOK"] == 0
|
|
10816
|
+
and near(r["footage"]["rotary_ft"], 380, 2) and near(r["footage"]["rotary_rop_ft_h"], 190, 2),
|
|
10817
|
+
"block": near(r["block_weight_klbf"], E_["block_weight_klbf"], 0.01) and r["block_weight_estimated"] and near(r["slips_threshold_klbf"], 60.0, 0.01),
|
|
10818
|
+
"lateral": int((lateral["state"] == RS.SLIPS).sum()) == 0 and int((lateral["state"] == RS.TIN).sum()) > 0.9 * n,
|
|
10819
|
+
"jump": int((jump["state"] == RS.TIN).sum()) == 0,
|
|
10820
|
+
"off_hook": int((hang["state"] == RS.OFFHOOK).sum()) == n and int((hang["state"] == RS.SLIPS).sum()) == 0,
|
|
10821
|
+
"no_hookload": nohl["slips"].sum() > 0.5 * n and "no hook load" in nohl["how"][0],
|
|
10822
|
+
}
|
|
10823
|
+
failed1 = [k for k, v in c1.items() if not v]
|
|
10824
|
+
ok(not failed1,
|
|
10825
|
+
"CP1 the record read to the second: three connections of 6, 9 and 15 min weight to weight with 4, 7 and 13 min in the slips; a 3,000 ft "
|
|
10826
|
+
"trip out at 2,449 ft/h and in at 3,333 ft/h over their pipe-handling hours; 2.0 h drilling 380 ft; the block's 40 klbf estimated; a light "
|
|
10827
|
+
"string pushed into a lateral tripping, not in the slips; a depth re-set not pipe moving; the weight off the hook for two hours OFF THE "
|
|
10828
|
+
"HOOK; the slips from the block when there is no hook load" + (f" [failed: {', '.join(failed1)}]" if failed1 else ""))
|
|
10829
|
+
|
|
10830
|
+
# -- CP2 the targets and the time lost ----------------------------------------------------------------------------
|
|
10831
|
+
w2 = ws.add_well_file(F["path"], display="RIG-2", actor="tester")
|
|
10832
|
+
p0 = RS.pad(ws)
|
|
10833
|
+
tg0 = p0["targets"]
|
|
10834
|
+
w2w = sorted(c["w2w_min"] for w_ in p0["wells"] for c in w_["connection_list"])
|
|
10835
|
+
lost0 = sum(max(0.0, x - tg0["w2w_min"]["value"]) for x in w2w) / 60.0
|
|
10836
|
+
IC.set_terms(ws, "tester", "test contract", "06:00", "start", {"operating": 30000}, None, None)
|
|
10837
|
+
try:
|
|
10838
|
+
RS.set_settings(ws, "tester", "", 5)
|
|
10839
|
+
no_source = False
|
|
10840
|
+
except ValueError:
|
|
10841
|
+
no_source = True
|
|
10842
|
+
RS.set_settings(ws, "tester", "drilling program 2026", 5, 2800, None)
|
|
10843
|
+
p1 = RS.pad(ws)
|
|
10844
|
+
W1 = p1["wells"][0]
|
|
10845
|
+
ti = next(x for x in W1["trips"] if x["direction"] == "IN")
|
|
10846
|
+
IC.attach(ws, "tester", w1["id"], "invoice", "inv.csv", b"Date,Rate Type,Quantity,Unit,Unit Price,Amount\n2026-08-01,Operating day rate,1,day,30000,30000\n", "test")
|
|
10847
|
+
ic = IC.check(ws, w1["id"])
|
|
10848
|
+
c2 = {
|
|
10849
|
+
"best_quarter": tg0["w2w_min"]["value"] == round(float(np.percentile(w2w, 25)), 2) and "best quarter" in tg0["w2w_min"]["how"] and tg0["trip_in_ft_h"] is None
|
|
10850
|
+
and abs(sum(w_["lost_connections_h"] for w_ in p0["wells"]) - lost0) < 0.02,
|
|
10851
|
+
"declared": no_source and p1["targets"]["w2w_min"]["value"] == 5 and "drilling program 2026" in p1["targets"]["w2w_min"]["how"]
|
|
10852
|
+
and abs(W1["lost_connections_h"] - sum(c["w2w_min"] - 5 for c in W1["connection_list"]) / 60.0) < 0.01
|
|
10853
|
+
and abs(ti["lost_h"] - max(0.0, ti["hours"] - ti["feet"] / 2800.0)) < 0.001 and next(x for x in W1["trips"] if x["direction"] == "OUT")["lost_h"] is None,
|
|
10854
|
+
"priced": p1["operating_usd_per_day"] == 30000 and abs(W1["lost_usd"] - W1["lost_h"] / 24.0 * 30000) < 0.006 * 30000 / 24.0,
|
|
10855
|
+
"by_day": len(W1["days"]) == 1 and W1["days"][0]["date"] == "2026-08-01" and W1["days"][0]["connections"] == 3 and abs(W1["days"][0]["lost_h"] - W1["lost_h"]) < 0.02,
|
|
10856
|
+
"invoice": ic["days"][0]["lost_time"] and abs(ic["days"][0]["lost_time"]["lost_h"] - W1["lost_h"]) < 0.02 and ic["days"][0]["status"] == "QUESTION",
|
|
10857
|
+
}
|
|
10858
|
+
failed2 = [k for k, v in c2.items() if not v]
|
|
10859
|
+
ok(not failed2,
|
|
10860
|
+
"CP2 the targets: the pad's best quarter (the 25th percentile of its connections) when none is declared, a declared target needing its "
|
|
10861
|
+
"source and then used; each connection's and trip's time past its target summed per well and per report day, priced at the contract's "
|
|
10862
|
+
"operating rate, and shown beside the invoice check's day" + (f" [failed: {', '.join(failed2)}]" if failed2 else ""))
|
|
10863
|
+
|
|
10864
|
+
# -- CP3 the report, the API, the CLI, the tab, the help ------------------------------------------------------------
|
|
10865
|
+
rp = RS.write_report(ws, __version__, "tester")
|
|
10866
|
+
rw = RS.write_report(ws, __version__, "tester", w1["id"])
|
|
10867
|
+
rd = PDF.read(Path(rp["paths"]["pdf"]).read_bytes())
|
|
10868
|
+
Users(str(Path(wsp, "users.json"))).add("v", "viewer-pass-1", "viewer"); Users(str(Path(wsp, "users.json"))).add("op", "op-pass-123", "operator")
|
|
10869
|
+
svc = Service(wsp, port=0, scheduler=False).start()
|
|
10870
|
+
base_url = svc.url.rstrip("/")
|
|
10871
|
+
|
|
10872
|
+
def opener(name, pw_):
|
|
10873
|
+
o = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(http.cookiejar.CookieJar()))
|
|
10874
|
+
rq = urllib.request.Request(base_url + "/api/login", method="POST", data=json.dumps({"name": name, "password": pw_}).encode())
|
|
10875
|
+
rq.add_header("Content-Type", "application/json"); rq.add_header("X-GEA-Action", "1"); o.open(rq, timeout=30)
|
|
10876
|
+
return o
|
|
10877
|
+
|
|
10878
|
+
def call(o, method, path, body=None):
|
|
10879
|
+
rq = urllib.request.Request(base_url + path, method=method, data=(json.dumps(body).encode() if body is not None else None))
|
|
10880
|
+
if method == "POST":
|
|
10881
|
+
rq.add_header("Content-Type", "application/json"); rq.add_header("X-GEA-Action", "1")
|
|
10882
|
+
try:
|
|
10883
|
+
with o.open(rq, timeout=120) as rr_:
|
|
10884
|
+
return rr_.status, json.loads(rr_.read())
|
|
10885
|
+
except urllib.error.HTTPError as e:
|
|
10886
|
+
return e.code, json.loads(e.read())
|
|
10887
|
+
try:
|
|
10888
|
+
V, O = opener("v", "viewer-pass-1"), opener("op", "op-pass-123")
|
|
10889
|
+
s_g, gj = call(V, "GET", "/api/rig-time")
|
|
10890
|
+
s_vs, _ = call(V, "POST", "/api/rig-time/settings", {"w2w_min": 4, "source": "x"})
|
|
10891
|
+
s_os, osj = call(O, "POST", "/api/rig-time/settings", {"w2w_min": 4.5, "source": "program B"})
|
|
10892
|
+
s_bad, _ = call(O, "POST", "/api/rig-time/settings", {"w2w_min": -1, "source": "program B"})
|
|
10893
|
+
s_bw, bwj = call(O, "POST", "/api/rig-time/settings", {"well_id": w2["id"], "block_weight_klbf": 42})
|
|
10894
|
+
s_w, wj = call(O, "POST", "/api/rig-time/write", {"well_id": w2["id"]})
|
|
10895
|
+
finally:
|
|
10896
|
+
svc.stop()
|
|
10897
|
+
cli_t = _sp.run([sys.executable, "-m", "gea", "rig-time", "--workspace", wsp], capture_output=True, text=True, cwd=str(pkg.parent))
|
|
10898
|
+
cli_w = _sp.run([sys.executable, "-m", "gea", "rig-time", "--workspace", wsp, "--write"], capture_output=True, text=True, cwd=str(pkg.parent))
|
|
10899
|
+
page_src = (pkg / "web" / "app.html").read_text(encoding="utf-8")
|
|
10900
|
+
c3 = {
|
|
10901
|
+
"report": rd["ok"] and "Rig time - Pad CP" in rd["text"][0] and Path(rw["paths"]["pdf"]).is_file() and "weight to weight" in Path(rp["paths"]["html"]).read_text(encoding="utf-8").lower(),
|
|
10902
|
+
"api": s_g == 200 and len(gj["wells"]) == 2 and gj["targets"]["w2w_min"]["value"] == 5 and s_vs == 403 and s_os == 200 and osj["targets"]["w2w_min"] == 4.5
|
|
10903
|
+
and s_bad == 400 and s_bw == 200 and bwj["block_weight_klbf"][w2["id"]] == 42 and s_w == 200 and wj["report_id"].startswith("RIG-"),
|
|
10904
|
+
"cli": cli_t.returncode == 0 and "drilling connections: weight to weight median 9.0 min" in cli_t.stdout and "the block weight declared, 42 klbf" in cli_t.stdout
|
|
10905
|
+
and cli_w.returncode == 0 and "printable:" in cli_w.stdout,
|
|
10906
|
+
"page": all(x in page_src for x in ("VIEWS.rigtime", "['#/rigtime', 'Rig time']", "/api/rig-time/settings", "rtBars", "Lost vs targets")),
|
|
10907
|
+
"help": any(t_[0] == "rig-time" for t_ in H.INDEX) and not H.check("rig-time") and H.VIEW_TOPIC.get("rigtime") == "rig-time",
|
|
10908
|
+
}
|
|
10909
|
+
failed3 = [k for k, v in c3.items() if not v]
|
|
10910
|
+
ok(not failed3,
|
|
10911
|
+
"CP3 the pad's report and a well's, with their PDFs; the API (anyone signed in reads it; only an operator sets a target or a block "
|
|
10912
|
+
"weight, or writes a report; a target below zero refused); the CLI (the rig time, the report); the tab and the help page"
|
|
10913
|
+
+ (f" [failed: {', '.join(failed3)}]" if failed3 else ""))
|
|
10914
|
+
|
|
10915
|
+
|
|
10764
10916
|
def main() -> int:
|
|
10765
10917
|
print("GEA-Program - ACCEPTANCE SUITE (the product gate)")
|
|
10766
10918
|
# a handle a job subprocess still holds at the end must not turn a finished gate into a traceback on Windows:
|
|
@@ -10857,6 +11009,7 @@ def main() -> int:
|
|
|
10857
11009
|
section_cm_watch_and_alerts(tmp)
|
|
10858
11010
|
section_cn_four(tmp)
|
|
10859
11011
|
section_co_invoice_check(tmp)
|
|
11012
|
+
section_cp_rig_time(tmp)
|
|
10860
11013
|
if _FAILS:
|
|
10861
11014
|
print(f"[ACCEPTANCE] {len(_FAILS)} FAILURES ({_PASS} passed):")
|
|
10862
11015
|
for f in _FAILS:
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Rig time
|
|
2
|
+
|
|
3
|
+
> What the rig did each second of the drilling record, read from the hook load, the block, the bit, the pumps and the rotary: the drilling connections timed weight to weight, the trips by speed, and the time lost against targets - the operator's declared targets, or this pad's own best quarter.
|
|
4
|
+
|
|
5
|
+
**The command**: the **Rig time** tab: the hours of each well by rig state, the drilling connections (weight to weight, and its three parts), each well's connections over time against the target, its trips and its report days; the targets and the block weight (the operator role); **Write the pad's report** or one well's. From a terminal: `gea rig-time --workspace C:\site` prints it; `--write` (with `--well W` for one well) writes the report; `--w2w-min 5 --trip-in 2500 --trip-out 2800 --source "drilling program"` declares targets; `--well W --block-weight 45` sets a well's block weight.
|
|
6
|
+
|
|
7
|
+
**The rig states**: IN SLIPS - the hook load below the block weight and half again, with the bit still (the rule rig-state software uses; the block weight is estimated from the hook load while the block moves and the bit does not, and printed); OFF THE HOOK - the same for half an hour or more (the string hung off, or no string: rigging, casing, waiting); ROTARY and SLIDE DRILLING - the record's own drilling samples, the rotary above 10 rpm or not; REAMING and WASHING - off bottom, pumping, the bit moving, with or without the rotary; CIRCULATING - pumping, the bit still; TRIPPING IN and OUT - the pumps off, the bit moving; STATIONARY - none of these.
|
|
8
|
+
|
|
9
|
+
**The connections and trips**: a drilling connection is a break of an hour or less between two stretches of drilling, with the string set in the slips and the bit kept within a stand of bottom: weight to weight from the last second drilling to the first second drilling again, made of off bottom to slips set, in the slips, and slips pulled to drilling. A trip is a run of tripping and the slips between its stands, the pumps off, split where the bit turns back 500 ft, that moves the bit 1,000 ft or more: its speed is its footage over its pipe-handling hours (moving and in the slips); the breaks inside it are reported beside it.
|
|
10
|
+
|
|
11
|
+
**What it writes**: the targets and block weights in `drillstring\rig_time.json`, the audit lines `rig_time.settings` and `report.rig_time`, and the reports `reports\rig_time_pad.*` and `reports\wells\<well>\rig_time.*` (PDF, HTML, markdown, JSON). The invoice check shows each report day's time lost beside the bill.
|
|
12
|
+
|
|
13
|
+
**The number to check**: a connection's weight to weight against the well's charts at its time; the block weight printed for each well against the rig's; a trip's footage over its hours.
|
|
14
|
+
|
|
15
|
+
**What this page will not call a measurement**: the cause of a long connection - a survey, a washout, a crew; the record shows the time, not the reason. A target beyond what this pad has done - the best quarter is this pad's own, not a technical limit. The slips themselves - a hook load threshold sees the weight leave the hook, and a block weight that differs from the estimate moves every slips time.
|
|
@@ -54,6 +54,7 @@ INDEX: List[tuple] = [
|
|
|
54
54
|
('report-history', 'Report history', 'every version of every client report kept in a dated folder with its SHA-256, when the next one replaces it'),
|
|
55
55
|
('pad-summary', 'The daily pad summary', 'one page each morning - what changed since the last one, what is due, what is still missing - kept in report history and sent through the notification rules'),
|
|
56
56
|
('dossier', 'The signed dossier', "a well's or the pad's reports, declarations, audit log and source hashes in one zip signed with the site's Ed25519 key, with a checker anyone can run without GEA"),
|
|
57
|
+
('rig-time', 'Rig time', "what the rig did each second of the drilling record - drilling, the slips, tripping, circulating - its connections timed weight to weight, its trips by speed, and the time lost against the pad's own best quarter"),
|
|
57
58
|
('invoice-check', 'The invoice cross-check', "the drilling contractor's daywork invoice, day by day, against the daily drilling reports and the drilling record at the contract's terms: hours, rates, standby, the repair allowance, depth and footage, with the dollars each difference puts in question"),
|
|
58
59
|
('economics', 'Economics', 'each well\'s days, footage and cost by the operator\'s own declared rates, against the EIA oil and gas spot prices while it was drilled, and any series the site imports'),
|
|
59
60
|
('well3d', 'The well in 3D', 'each well\'s path from its directional survey, set among the mapped formation surfaces and contours with its picks, coloured by what was measured along it, and the drill string replayed from the record; the Volve field shipped as the worked example'),
|
|
@@ -85,7 +86,7 @@ REQUIRED_LINES = ('**The command**', '**What it writes**', '**The number to chec
|
|
|
85
86
|
VIEW_TOPIC: Dict[str, str] = {
|
|
86
87
|
'home': 'start', 'wells': 'data-in', 'well': 'drift', 'live': 'patches', 'patch': 'patches', 'files': 'files', 'alarms': 'alarms',
|
|
87
88
|
'approvals': 'well-tests', 'config': 'site', 'reports': 'drift', 'verify': 'start', 'survey': 'data-in', 'jobs': 'site',
|
|
88
|
-
'admin': 'site', 'prefs': 'site', 'search': 'start', 'welcome': 'start', 'seismic': 'seismic', 'seismic_station': 'seismic', 'track': 'seismic', 'sar': 'seismic', 'sites': 'sites', 'setup': 'setup', 'map': 'map', '3d': 'well3d', 'simulation': 'simulation', 'drillstring': 'drillstring', 'completion': 'penetrator', 'opseis': 'opseis', 'economics': 'economics', 'invoices': 'invoice-check', 'control': 'control-room', 'wall': 'control-room', 'audit': 'audit-update', 'tools': 'tools', 'catalog': 'catalog',
|
|
89
|
+
'admin': 'site', 'prefs': 'site', 'search': 'start', 'welcome': 'start', 'seismic': 'seismic', 'seismic_station': 'seismic', 'track': 'seismic', 'sar': 'seismic', 'sites': 'sites', 'setup': 'setup', 'map': 'map', '3d': 'well3d', 'simulation': 'simulation', 'drillstring': 'drillstring', 'completion': 'penetrator', 'opseis': 'opseis', 'economics': 'economics', 'invoices': 'invoice-check', 'rigtime': 'rig-time', 'control': 'control-room', 'wall': 'control-room', 'audit': 'audit-update', 'tools': 'tools', 'catalog': 'catalog',
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
|
|
@@ -618,6 +618,13 @@ def check(ws, well_id: str) -> dict:
|
|
|
618
618
|
D['status'] = 'DIFFERS' if 'DIFFERS' in sev else 'QUESTION' if 'QUESTION' in sev else 'AGREES'
|
|
619
619
|
D['usd_in_question'] = round(sum(f['usd_in_question'] for f in D['findings']), 2)
|
|
620
620
|
out['days'].append(D)
|
|
621
|
+
try: # the time lost against the pad's targets, beside each day (not a finding: daywork pays it)
|
|
622
|
+
from . import rig_state as RS
|
|
623
|
+
lost = RS.lost_by_day(ws, well_id)
|
|
624
|
+
except Exception:
|
|
625
|
+
lost = {}
|
|
626
|
+
for D in out['days']:
|
|
627
|
+
D['lost_time'] = lost.get(D['date'])
|
|
621
628
|
out['totals'] = {'days': len(out['days']), 'agrees': sum(d['status'] == 'AGREES' for d in out['days']),
|
|
622
629
|
'question': sum(d['status'] == 'QUESTION' for d in out['days']), 'differs': sum(d['status'] == 'DIFFERS' for d in out['days']),
|
|
623
630
|
'billed_usd': round(sum(ln['amount'] or 0.0 for ln in inv), 2),
|
|
@@ -655,10 +662,13 @@ def build_report(ws, well_id: str, version: str):
|
|
|
655
662
|
hw = r.get('how') or r.get('detail') or ''
|
|
656
663
|
s1.paragraphs.append(hw[:1].upper() + hw[1:] + '.')
|
|
657
664
|
s2 = CR.Section('2', 'Day by day', [], [])
|
|
658
|
-
s2.tables.append(CR.Table(['Day', 'Result', 'Billed (h)', 'Billed (USD)', 'Report (h)', 'Record: working / quiet / drilling (h)', 'USD in question'],
|
|
665
|
+
s2.tables.append(CR.Table(['Day', 'Result', 'Billed (h)', 'Billed (USD)', 'Report (h)', 'Record: working / quiet / drilling (h)', 'Time lost vs targets (h)', 'USD in question'],
|
|
659
666
|
[[d['date'], d['status'], ', '.join(f"{k.replace('_', ' ')} {v:g}" for k, v in d['billed_hours'].items()) or '-', f"{d['billed_usd']:,.2f}",
|
|
660
667
|
f"{d['ddr_hours']:g}", (f"{d['record']['active_h']:.1f} / {d['record']['quiet_h']:.1f} / {d['record']['drilling_h']:.1f}" if d['record'] else 'not in the record'),
|
|
661
|
-
f"{d['usd_in_question']:,.2f}"] for d in r['days']]))
|
|
668
|
+
(f"{d['lost_time']['lost_h']:.2f}" if d.get('lost_time') else '-'), f"{d['usd_in_question']:,.2f}"] for d in r['days']]))
|
|
669
|
+
if any(d.get('lost_time') for d in r['days']):
|
|
670
|
+
s2.paragraphs.append('Time lost vs targets: the drilling connections\' weight-to-weight time and the trips\' pipe-handling time past the pad\'s targets '
|
|
671
|
+
'(the Rig time tab). Under daywork the operator pays for it; it is shown beside the bill, not counted in question.')
|
|
662
672
|
s3 = CR.Section('3', 'What differs, and what to ask', [], [])
|
|
663
673
|
if r['findings']:
|
|
664
674
|
s3.tables.append(CR.Table(['Day', 'Check', 'Result', 'What the three accounts say', 'USD', 'Line'],
|