| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- #!/usr/bin/env python3
- """Machine running segments from ``wave_file.rpm > 0`` (read-only).
- The site's 开机停机表 is known to be inaccurate, so the running state is taken
- from the data itself: every calendar day that has at least one pressure record
- with ``rpm > 0`` is a running day. Consecutive running days (allowing a small
- merge gap for missing daily records) form one *running segment*. ``event_bins``
- uses these segments to pick the pre/post running periods instead of fixed
- event-relative windows.
- """
- from __future__ import annotations
- import argparse
- import csv
- import sys
- from datetime import date
- from pathlib import Path
- import pymysql
- BACKEND = Path(__file__).resolve().parents[1]
- sys.path.insert(0, str(BACKEND))
- from app.config import settings # noqa: E402
- def connect() -> pymysql.connections.Connection:
- return pymysql.connect(
- host=settings.db_host, port=settings.db_port, user=settings.db_user,
- password=settings.db_password, database=settings.db_name, charset="utf8mb4",
- cursorclass=pymysql.cursors.DictCursor, connect_timeout=8, read_timeout=120,
- )
- def running_days(unit: str, connection=None) -> list[date]:
- """Sorted distinct days with a running pressure record for one unit."""
- own = connection is None
- connection = connection or connect()
- try:
- with connection.cursor() as cursor:
- cursor.execute(
- """
- SELECT DISTINCT DATE(sample_time) AS d
- FROM wave_file
- WHERE point_name LIKE %s AND measurement_type = '压力' AND rpm > 0
- ORDER BY d
- """,
- (f"{unit}号机组%",),
- )
- return [row["d"] for row in cursor.fetchall()]
- finally:
- if own:
- connection.close()
- def build_segments(days: list[date], merge_gap: int = 2) -> list[tuple[date, date]]:
- """Merge running days into segments; a gap of at most ``merge_gap`` off-days is bridged."""
- segments: list[list[date]] = []
- for day in days:
- if segments and (day - segments[-1][1]).days <= merge_gap + 1:
- segments[-1][1] = day
- else:
- segments.append([day, day])
- return [(start, end) for start, end in segments]
- def unit_segments(unit: str, merge_gap: int = 2, connection=None) -> list[tuple[date, date]]:
- return build_segments(running_days(unit, connection), merge_gap)
- def main() -> None:
- parser = argparse.ArgumentParser(description="wave_file.rpm>0 统计开机日与运行段(只读)")
- parser.add_argument("--unit", required=True, choices=("7", "8", "9"))
- parser.add_argument("--merge-gap", type=int, default=2, help="允许跨过的停机天数(桥接)")
- parser.add_argument("--out", default="", help="运行段 CSV 输出路径(可选)")
- args = parser.parse_args()
- days = running_days(args.unit)
- segments = build_segments(days, args.merge_gap)
- print(f"{args.unit}号机 rpm>0 开机日 {len(days)} 天,运行段 {len(segments)} 个:")
- for start, end in segments:
- print(f" {start} ~ {end} ({(end - start).days + 1}天)")
- if args.out:
- out = Path(args.out)
- out.parent.mkdir(parents=True, exist_ok=True)
- with out.open("w", encoding="utf-8-sig", newline="") as handle:
- writer = csv.writer(handle)
- writer.writerow(["unit", "start", "end", "days"])
- for start, end in segments:
- writer.writerow([args.unit, start, end, (end - start).days + 1])
- print("->", out)
- if __name__ == "__main__":
- main()
|