import re, io
p = 'pages/AnalysisPage.jsx'
s = io.open(p, encoding='utf-8').read()

start = s.index('function FocusRow({ row, onPractise }) {')
end = s.index('export default function AnalysisPage() {')
old = s[start:end]

new = '''/**
 * One topic, and what it is telling you.
 *
 * Closed it is a rank: readiness, relevance, and whether it needs work. Open
 * it is the two figures that rank was built from — how much of the topic has
 * been sat, and how much of that was right — with the reading and the practice
 * that follow from the pair beside them. Two bars rather than two percentages
 * because the shapes are what separate "you have not looked at this" from "you
 * have looked at this and it is not going in".
 */
function FocusRow({ row, onPractise }) {
  const [open, setOpen] = useState(false)
  const seenShare = row.available ? Math.min(100, (row.seen_questions / row.available) * 100) : 0
  const correctShare = row.answered ? (row.correct / row.answered) * 100 : 0
  const accuracyLabel = row.answered
    ? `${row.accuracy}% (${row.correct} out of ${row.answered})`
    : 'Not attempted'

  return (
    <div className={`an-focus${row.is_focus_area ? ' is-focus' : ''}`}>
      <button type="button" className="an-focus-row" aria-expanded={open} onClick={() => setOpen(v => !v)}>
        <span className="an-focus-toggle" aria-hidden="true">{open ? '\\u25be' : '\\u25b8'}</span>
        <span className="an-focus-name">
          <strong>{row.name}</strong>
          {row.parent_name && <span className="an-focus-parent">{row.parent_name}</span>}
          {row.is_focus_area && <span className="an-focus-tag">Focus area</span>}
        </span>
        <span className="an-metric an-metric-readiness">
          {row.readiness !== null ? `${row.readiness}%` : row.accuracy !== null ? `${row.accuracy}%` : '\\u2014'}
          <small>{row.readiness !== null ? 'Readiness' : 'Accuracy'}</small>
        </span>
        {/* Where the number comes from decides what it means. From a board's
            published outline it is the share of the real paper this topic
            accounts for \\u2014 a fact about the exam. Otherwise it is the share of
            our own bank sitting under it, which is a fact about us. */}
        <span className="an-metric an-metric-relevance"
          title={row.relevance_source === 'blueprint'
            ? 'Share of the real exam this topic accounts for, from the examining board\\u2019s published content outline'
            : 'Share of the question bank filed under this topic'}>
          {row.relevance}%
          <small>{row.relevance_source === 'blueprint' ? 'Of the exam' : 'Of the bank'}</small>
        </span>
        <span className={`an-status is-${row.status}`}>{STATUS_LABEL[row.status]}</span>
      </button>

      {open && (
        <div className="an-focus-detail">
          <div className="an-detail-grid">
            <div className="an-detail-block">
              <div className="an-detail-block-label">Questions completed</div>
              <div className="an-detail-value">{row.seen_questions}/{row.available}</div>
              {/* The bar is the whole topic, not the part that has been sat, so
                  a full green line means there is nothing left of it \\u2014 which is
                  the thing a coverage percentage on its own never shows. */}
              <div className="an-bar an-bar-split">
                <span className="is-seen" style={{ width: `${seenShare}%` }} />
                <span className="is-unseen" style={{ width: `${100 - seenShare}%` }} />
              </div>
              <ul className="an-detail-legend">
                <li><i className="is-seen" />Answered</li>
                <li><i className="is-unseen" />Not answered</li>
              </ul>
            </div>
            <div className="an-detail-block">
              <div className="an-detail-block-label">Answered correctly</div>
              <div className="an-detail-value">{accuracyLabel}</div>
              {/* This bar spans what was answered rather than the whole topic:
                  it is the accuracy above drawn out, and mixing the unseen
                  material into it would make a perfect score on a tenth of the
                  questions look like a poor one.

                  The reference splits it three ways \\u2014 right, right after a tip,
                  wrong. Per-topic hint counts are not in the recommendations
                  payload, only `answered` and `correct`, so the middle slice is
                  left undrawn rather than inferred from the lifetime figure,
                  which is about a different set of answers. */}
              <div className="an-bar an-bar-split">
                {row.answered ? (
                  <>
                    <span className="is-correct" style={{ width: `${correctShare}%` }} />
                    <span className="is-wrong" style={{ width: `${100 - correctShare}%` }} />
                  </>
                ) : <span className="is-unseen" style={{ width: '100%' }} />}
              </div>
              <ul className="an-detail-legend">
                <li><i className="is-correct" />Correct</li>
                <li><i className="is-wrong" />Incorrect</li>
              </ul>
            </div>
            <div className="an-detail-block an-detail-next">
              <div className="an-detail-block-label">Recommended next step:</div>
              <div className="an-detail-actions">
                {row.article_id && (
                  <Link className="btn btn-secondary btn-sm" to={`/articles/${row.article_id}`}>
                    Read {row.article_title}
                  </Link>
                )}
                {/* Practise the row you are looking at, on its own axis: an
                    article's questions, a discipline's, or everything filed under
                    an organ system. */}
                <button className="btn btn-primary btn-sm" onClick={() => onPractise(row)}>
                  Practise this topic
                </button>
              </div>
            </div>
          </div>
        </div>
      )}
    </div>
  )
}

'''
s = s[:start] + new + s[end:]
io.open(p, 'w', encoding='utf-8').write(s)
print("ok")
