#!/usr/bin/env python3
"""Check: the challenger's predictions were written before it read anything.

    predictions-first <directory>

A round lives in docs/rounds/<name>/ and holds one file per participant. The
challenger's file is predictions.md.

CATCHES  A round whose predictions were written afterwards, or not at all.

         An objection composed after reading somebody's work is shaped by that
         work — you find whichever weakness the text put in front of you. A
         prediction is not. One that proves accurate shows the weakness was
         built into the approach rather than a slip on the day, which is a far
         stronger result. Written afterwards, it is a description, and it
         proves nothing while looking exactly the same.

WHAT THE EVIDENCE IS WORTH, HONESTLY
------------------------------------
Two things are checked, and they are not equally strong.

  * **The file exists.** Solid. A round with reports and no predictions did
    not do this at all.
  * **It is older than the reports.** Weak. Modification times are not carried
    by version control and are reset by copying, so this can be wrong in both
    directions.

The second is reported as a warning rather than treated as proof. Nothing here
can prove when somebody thought something; what it can do is make the absence
impossible to miss.

Exit status:
    0   every round has predictions, written first as far as can be told
    1   a round has reports and no predictions
    2   the check could not run
"""
import os
import sys

ROUNDS = os.path.join("docs", "rounds")
PREDICTIONS = "predictions.md"
# brief.md is the human's input, written before anybody works. Counting it as
# a participant report meant every correctly-run round warned about itself.
SKIP = {"README.md", "round.md", "index.md", "brief.md"}


def rounds(root):
    base = os.path.join(root, ROUNDS)
    if not os.path.isdir(base):
        return None
    out = []
    for name in sorted(os.listdir(base)):
        d = os.path.join(base, name)
        if os.path.isdir(d):
            out.append((name, d))
    return out


def main(argv):
    args = [a for a in argv[1:] if not a.startswith("--")]
    if not args:
        print("usage: predictions-first <directory>", file=sys.stderr)
        return 2
    root = args[0]
    if not os.path.isdir(root):
        print("ERROR: not a directory: %s" % root, file=sys.stderr)
        return 2

    found = rounds(root)
    if found is None:
        print("no %s directory, no rounds to check" % ROUNDS)
        return 0
    if not found:
        print("no rounds recorded yet")
        return 0

    problems = []
    warnings = []
    checked = 0

    for name, d in found:
        files = [f for f in sorted(os.listdir(d))
                 if f.endswith(".md") and f not in SKIP]
        reports = [f for f in files if f != PREDICTIONS]
        if not reports:
            continue                      # nothing was argued yet
        checked += 1

        predictions = os.path.join(d, PREDICTIONS)
        if not os.path.exists(predictions):
            problems.append("%s — has %d report(s) and no %s"
                            % (name, len(reports), PREDICTIONS))
            continue

        try:
            when = os.path.getmtime(predictions)
            earliest = min(os.path.getmtime(os.path.join(d, r)) for r in reports)
        except OSError:
            continue
        if when > earliest:
            warnings.append("%s — %s is newer than the earliest report"
                            % (name, PREDICTIONS))

    if problems:
        print("%d round(s) argued without predictions, of %d checked"
              % (len(problems), checked))
        for p in problems:
            print("  %s" % p)
        if warnings:
            for w in warnings:
                print("  warning: %s" % w)
        return 1

    if warnings:
        print("%d round(s) checked. Nothing missing, but:" % checked)
        for w in warnings:
            print("  warning: %s" % w)
        print("  Modification times are weak evidence — version control does "
              "not carry them and copying resets them.")
        return 0

    print("%d round(s) checked, each with predictions on record" % checked)
    return 0


if __name__ == "__main__":
    sys.exit(main(sys.argv))
