Stanley Reid & · Data Scientist
Updated · 2026-09-24

Stanley Reid & Data Scientist
Interview Questions & Guide 2026

THE 60-SECOND BRIEF

A Data Scientist at Stanley Reid & operates at the intersection of complex security challenges and advanced technical innovation. The role is responsible for transforming raw data into actionable intelligence, building analytical platforms, and driving the technical strategy that secures Stanley Reid &'s infrastructure. The work goes beyond model accuracy: it provides the quantitative backbone that lets the organization anticipate risks and optimize performance in high-stakes environments.

When randomisation is off the table, the skill being checked is naming an identification strategy together with the assumption it rests on: parallel trends for difference-in-differences, relevance and exclusion for an instrument, overlap and conditional ignorability for matching. Say the assumption out loud and say how you would try to break it.

PracHub has no confirmed round sequence for Stanley Reid &. Treat the sections below as preparation areas and confirm the format with your recruiter.

Power experiments for heavy-tailed account revenueRead NRR on a fixed account cohortMeasure churn only on renewal-eligible accounts

35 min read

Browse Data Scientist questions

See the practice prompts

13Practice promptsAcross five skill areas
3With worked solutionsIncluded in the practice prompts

A Data Scientist at Stanley Reid & operates at the intersection of complex security challenges and advanced technical innovation. The role is responsible for transforming raw data into actionable intelligence, building analytical platforms, and driving the technical strategy that secures Stanley Reid &'s infrastructure. The work goes beyond model accuracy: it provides the quantitative backbone that lets the organization anticipate risks and optimize performance in high-stakes environments.

In this role, you contribute directly to the development of specialized platforms, particularly in Graph Analysis. You will be expected to handle the full lifecycle of data initiatives, from data parsing and sophisticated modeling to the enhancement of complex graph structures. The position suits candidates who like solving multi-faceted problems and building scalable, reliable data solutions that affect Stanley Reid &'s business outcomes.

01

Preparation focus

editorial

No round sequence has been reported for this company, so work the categories below and confirm the format with your recruiter.

What to demonstrate

  • Breadth across SQL, experimentation and product reasoning
  • Ability to state assumptions before choosing a method

How to prepare

  • Drill the practice exercises below and time yourself
  • Prepare three quantified stories about decisions you drove
PracHub interview preparation framework ↗

PracHub editorial advice for the preparation topics above.

01

Randomising an experiment at the user level when users share an account

Two problems fire at once. Colleagues in one workspace see each other's work and talk to each other, so a treated user changes the behaviour of a control user in the same account, which violates the no-interference assumption and biases the estimate toward zero. Separately, outcomes within an account are strongly correlated, so the effective sample size is roughly n / (1 + (m - 1) * rho) for m users per account and intra-class correlation rho, not n. With rho around 0.3 and twenty users per account that is a design effect near 6.7, meaning a user-level confidence interval is about two and a half times narrower than it should be and results cross significance thresholds on noise alone. Randomise the account and cluster the standard errors.

02

Comparing accounts that received a sales or customer-success touch against those that did not

Assignment of coverage is deliberate and pulls in both directions at once: the largest accounts get a named owner because they are valuable, and the accounts showing distress get one because they are at risk. The comparison therefore mixes a strong positive selection with a strong negative one, and the naive estimate can come out with either sign depending on which assignment rule dominated during the period examined. Nothing about matching on observed size fixes this, because the risk signal that triggered coverage is usually the same signal that predicts the outcome. It needs either an actual randomised or staggered rollout of coverage, or a design built on a capacity constraint or territory boundary that assigns coverage for reasons unrelated to account health.

03

Stopping an experiment the moment it crosses significance

Fix the sample size or duration before launch, or use a method built for continuous monitoring such as a sequential test, always-valid confidence intervals, or group-sequential boundaries. Repeatedly checking a fixed-horizon p-value against 0.05 pushes the real false-positive rate well above 5 percent.

04

Dropping rows with missing values without naming the mechanism

Say whether the values are missing at random, missing by a known process, or missing in a way that depends on the outcome, and handle them accordingly. Deleting incomplete rows silently redefines the population whenever missingness correlates with what you are measuring.

Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.

10 technical prompts3 include a worked solution

Quantify billable volume created by retries after server errors

hard
telemetry-hygienepandasunit-economics

From fct_api_request (request_id, account_id, endpoint, idempotency_key, is_retry, http_status, request_at, billable_units), measure how much billable volume in a 28-day window is retry traffic that followed a 5xx. Group requests into attempt chains by (account_id, endpoint, idempotency_key) ordered by request_at; a request is error-driven if any earlier attempt in its chain returned 5xx. Requests with a null idempotency_key cannot be chained, so report them as their own class rather than assuming each is unique. Return billable_units split into first-attempt, error-driven retry, other retry and unchainable, per account.

Approach
  1. Split the population before measuring anything. A null idempotency_key is not a chain of one, it is an unknown; report its share of billable_units first, because if it is 40% of volume then the headline estimate is a lower bound and the deliverable has to say so.
  2. Within chainable rows, sort by (account_id, endpoint, idempotency_key, request_at) and derive 'any earlier attempt failed' with arithmetic rather than a per-group lambda: with is5 = (http_status >= 500), the per-chain cumsum minus the row's own value is positive exactly when an earlier attempt in that chain returned 5xx. A groupby-apply gives the same answer and is unusable at five million rows.
  3. Do not take is_retry as the definition. It is set by the client whenever an idempotency_key is resent, which covers retries after client-side timeouts and after 4xx as well; compute the flag yourself and then cross-tabulate it against is_retry, because the disagreement is a finding in its own right.
  4. Aggregate billable_units by (account_id, class) and assert the classes sum to each account's total. The spine sets billable_units to zero on 5xx responses, so the failed attempt contributes nothing and the whole inflation sits in the successful retry that follows it.
  5. Report the per-account share and look at its distribution, not the fleet total. One account in a retry storm dominates any blended figure, which is the same failure that makes a fleet-wide error rate useless.
Follow-up
  • An account's error-driven share is 22%. Is that the platform's fault or the client's, and what do you look at next?
  • How would you define a consumption-based north-star metric that an outage cannot inflate?
  • Chains straddle the 28-day boundary. How large is that bias and in which direction?

Permutation-test a consumption experiment randomised at account level

hardWorked solution
permutation-testheavy-tailscupedexperiment-readout

An experiment randomised 900 accounts into two arms. You have one row per account: account_id, arm, consumption_28d (billable units after launch) and consumption_pre (the 28 days before). Consumption is heavy-tailed and the largest account is several percent of the total. Write a permutation test from scratch: winsorise at the pooled 99th percentile as a pre-registered rule, use the difference in arm means of the winsorised outcome as the statistic, and obtain a two-sided p-value from 20,000 relabellings of the account-level arm vector. Report the observed effect, the p-value, and the same test on a CUPED-adjusted outcome.

Approach
  1. Be precise about what the permutation test needs. Under the sharp null of no effect for any account, the outcomes are exchangeable across arm labels, and the test is valid for ANY statistic T(outcomes, labels) provided the identical function is applied to the observed labels and to all 20,000 relabellings. The pooled 99th percentile is a function of the outcome vector alone, so recomputing it inside the loop returns the same number 20,000 times: that is wasted CPU, not a bias, and hoisting it out is an optimisation rather than a correctness fix. Say plainly that capping at all changes the estimand from mean consumption to mean capped consumption; it is not a neutral cleaning step.
  2. The mistake that does invalidate the test is an asymmetry between the observed statistic and the permuted ones, and the easiest way to create it is to derive the cleaning rule from the observed arm labels and then freeze it — winsorise each arm at its own observed 99th percentile, hold those two caps fixed, and permute. The observed value is then computed with caps matched to its own partition while every relabelling is scored with caps belonging to a different one, so the null distribution no longer answers the question the p-value claims to answer. A per-arm cap recomputed consistently inside every permutation is a valid test, but it estimates a contrast whose two sides are capped at different thresholds, so prefer the pooled cap on estimand grounds and pre-register it.
  3. Permute the account-level arm vector, because the account is the randomisation unit. Relabelling anything finer — users, workspaces, requests — generates a null distribution narrower than the design actually supports and returns p-values that are anti-conservative.
  4. Vectorise the null: tile the treatment indicator into a (B, n) matrix and permute along axis 1 with rng.permuted(..., out=...). The statistic is a difference of means, so the treated sum alone determines it and the whole null is one matrix-vector product. Use the two-sided p-value (1 + count(|stat_perm| >= |stat_obs|)) / (B + 1); the plus-one on each side is not cosmetic, it keeps the p-value away from exactly zero and keeps the test valid at finite B.
  5. For CUPED, fit theta = cov(y, x) / var(x) on the pooled data and use that same theta for the observed statistic and every relabelling. Pooled theta, like the pooled cap, carries no label information, so where in the loop you compute it is again only a performance question; fitting theta within arms is what goes wrong, because the adjusted outcome then depends on the labels and an observed-label fit frozen across all 20,000 relabellings breaks the match between observed and permuted statistics. x must be measured entirely before launch, which consumption_pre is. Expected variance reduction is about 1 - corr(y, x)^2; measure the achieved reduction from the two null distributions rather than asserting it.
Worked solution 45 min
  1. cap_y = np.quantile(df.consumption_28d, 0.99); y = np.minimum(df.consumption_28d.to_numpy(float), cap_y); cap_x = np.quantile(df.consumption_pre, 0.99); x = np.minimum(df.consumption_pre.to_numpy(float), cap_x)
  2. t = (df.arm == 'treatment').to_numpy(); n1 = int(t.sum()); n0 = len(t) - n1; obs = y[t].mean() - y[~t].mean()
  3. rng = np.random.default_rng(11); L = np.tile(t.astype(np.int8), (20_000, 1)); rng.permuted(L, axis=1, out=L); s1 = L @ y; stats = s1/n1 - (y.sum() - s1)/n0
  4. p = (1 + int(np.sum(np.abs(stats) >= abs(obs)))) / (20_000 + 1)
  5. theta = np.cov(y, x, ddof=1)[0,1] / np.var(x, ddof=1); y_adj = y - theta*(x - x.mean()); repeat steps 2 to 4 on y_adj and compare stats.std(ddof=1) between the two runs.
EXPECTED RESULTA two-sided p-value strictly between 1/20001 and 1, an observed effect expressed in capped billable units per account, and a CUPED null whose standard deviation is smaller than the unadjusted one by roughly sqrt(1 - corr(y, x)^2). The CUPED point estimate stays close to the unadjusted one, since the adjustment removes variance rather than shifting the effect.
Follow-up
  • The p-value is 0.04 with the cap and 0.31 without it. What do you report, and what did you pre-register?
  • Colleagues in a shared workspace can see the treated behaviour. How does that change the design and the estimate?
  • How many accounts would you need to detect a 5% lift given this outcome's distribution?

Implement seven-day activation rate from its written definition

easy
metricspandasactivation

Given dim_account (account_id, created_at, is_internal, is_current) and fct_api_request (account_id, request_at, http_status, api_key_id, traffic_class), implement activation_rate(accounts, requests, week_start). Definition: the numerator is accounts whose first request with http_status < 400, api_key_id not null and traffic_class != 'synthetic_monitor' occurs no later than 168 hours after created_at; the denominator is non-internal accounts created during the ISO week starting week_start. All timestamps are tz-aware UTC. Return the rate and both counts, and refuse to report a week until every account in it has had its full 168 hours.

Approach
  1. Reduce dim_account to one row per account_id before joining anything. It is a type 2 dimension, so several versions of the same account exist; joining the versioned table to requests multiplies the denominator by the number of plan changes an account happened to make.
  2. Build the denominator first and freeze it: is_internal == False and week_start <= created_at < week_start + 7 days. Everything after this is a filter on the numerator only, because an account that never sent a request must still sit in the bottom of the fraction.
  3. Filter requests to qualifying rows and only then take groupby('account_id').request_at.min(). The first qualifying request is not the same object as the global first request filtered afterwards, and the two answers differ for every account whose first call was a 4xx.
  4. Left-join the first qualifying timestamp onto the cohort and test (first_ok - created_at) <= Timedelta(hours=168). NaT propagates to False in that comparison, which is the behaviour you want, but assert it rather than assume it.
  5. Guard reportability explicitly: if week_start + 7 days + 168 hours exceeds the maximum request_at in the data, the week is censored and will read as a drop, so return None or raise rather than emit a number.
Follow-up
  • Median time-to-first-call is more informative. What breaks if you take the median over activated accounts only, and what estimator fixes it?
  • How would you decide whether 168 hours is the right window rather than 72 or 336?
  • An account signs up, does nothing for 20 days, then integrates heavily. Where does it land in this metric, and is that what you want?

For someone who has spent the last year in notebooks, dashboards or modelling work and has not written raw SQL under time pressure. The first four days rebuild query fluency against a fixture you control and can verify by hand; the last three attach that fluency to the rest of the loop.

Small steps. Visible outcomes.0 / 7 completed
ONE WEEK · YOUR PACE

Prepare, practise & reflect

One practical outcome each day. Spend longer where you need it.

0 / 7 done
01Build a fixture you can check answers against
  • Create a local Postgres or SQLite database with four tables (users, sessions, events, orders) holding roughly 200 rows you generated yourself, so you know the contents well enough to predict every result.
  • Deliberately seed the cases that break queries: a user with no sessions, a session with no events, two orders sharing a timestamp, a NULL in one join key, and one duplicated user row.
  • Before writing any SQL, hand-compute five answers on paper (how many users placed at least one order, median orders per ordering user, and three others) and save them as the ground truth for the week.

Deliverable: A one-command seed script plus a text file of five hand-computed answers to grade every later query against.

Practice prompt ↗Practice prompt ↗Worked solution ↗
02Joins, filters and NULL semantics
  • Answer "which users have no orders" three ways (LEFT JOIN with IS NULL, NOT EXISTS, NOT IN) and confirm that the NOT IN version returns zero rows once the subquery contains a NULL, because the comparison is never TRUE.
  • Reproduce the LEFT JOIN that silently collapses to an inner join by putting a right-table predicate in WHERE, then fix it by moving the predicate into the ON clause, and record both row counts.
  • Create a fan-out bug on purpose by joining orders to order_items and summing the order total, then correct it with a pre-aggregated subquery and explain in one line which table changed the grain.

Deliverable: One annotated .sql file holding the three join traps, each with the wrong result and the corrected result side by side.

Practice prompt ↗Practice prompt ↗
03Window functions and frames
  • Write three window queries against the fixture: a running order total per user, the rank of each order within its user by value, and the day gap to that user's previous order, then check each against the day-one ground truth.
  • Run ROW_NUMBER, RANK and DENSE_RANK over a column containing ties, print all three side by side, and write one sentence on when each is the correct choice.
  • Switch one query from the default frame (RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, which is what you get when ORDER BY is present and no frame is written) to ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, and explain why the output differs only when the ORDER BY column has duplicates.

Deliverable: Three verified window queries plus a short note explaining the RANGE versus ROWS difference in your own words.

Practice prompt ↗Practice prompt ↗
04The four analytical query patterns
  • Write a monthly retention grid: first order month per user, then months-since-first as the column, and verify that month zero equals the cohort size exactly.
  • Sessionize the events table under a 30-minute inactivity rule using LAG plus a cumulative sum over a new-session flag.
  • Build a four-step funnel that counts distinct users rather than events at each step, and state the rule you applied to a user who reaches step three without ever logging step two.

Deliverable: One file with the retention, sessionization and funnel patterns, each carrying a one-line note on the assumption it bakes in.

Practice prompt ↗Practice prompt ↗Worked solution ↗
05Write SQL the way you will have to write it live
  • Set a 12-minute timer and solve three medium prompts in a plain editor with no execution and no autocomplete, then run them and tally syntax errors separately from logic errors.
  • Narrate one solution aloud while writing it, stating the grain of each intermediate result (one row per user, one row per user-day) before you type its body.
  • Rewrite your slowest solution as a CTE chain where every CTE name states its grain, and time yourself re-solving it from blank.

Deliverable: A recording of one narrated solution plus an error tally that separates syntax from logic.

Practice prompt ↗Practice prompt ↗
06One day for everything that is not SQL
  • Write the preconditions of the two-sample t-test from memory, then check them: independent observations, and a difference in means whose sampling distribution is approximately normal, which at large sample sizes follows from the central limit theorem rather than from normality of the raw values.
  • Write the difference between an odds ratio from logistic regression and a relative risk, and state the condition under which the two are close (low outcome prevalence).
  • Prepare a 90-second answer to "how would you know this model is any good" that names the metric, the baseline you would beat, and the cost of the errors you care about.

Deliverable: One page of notes covering test preconditions, the odds-ratio caveat and the model-quality answer.

Practice prompt ↗Practice prompt ↗
07Full loop rehearsal
  • Run a 45-minute mock with someone willing to interrupt: 20 minutes of SQL, 15 minutes defining a metric, 10 minutes on a past project.
  • Re-solve from blank the two queries you were slowest on this week and compare the times against day five.
  • Write a five-line answer to "walk me through a project" that puts a number in the first sentence and names the decision the work changed.

Deliverable: Mock feedback notes plus a timed project narrative you can deliver without reading it.

Practice prompt ↗Worked solution ↗

Expand any day for tasks and deliverables. Your progress is saved on this device.

A number you shipped turned out to be wrong, and someone had already acted on it. That is one of the most useful stories a data person can carry. What is being scored is how fast you noticed, who you told first, and what you changed in the process so the same class of error could not repeat quietly.

Describe a time you had to parse complex, unstructured data; what tech…

medium
behavioural and stakeholder questions

Describe a time you had to parse complex, unstructured data; what techniques did you use?

Approach
  1. Name the disagreement or constraint, and how you resolved it with evidence.
  2. Quantify the outcome, including what you would not claim credit for.
  3. Pick a story where you drove the decision, not one where you observed it.
Follow-up
  • How did you know the outcome was caused by your change?
  • What would you do differently if you ran that project again?

Report an underpowered consumption test to a non-technical executive

medium
communicationuncertaintyexperimentation

An account-randomised packaging change ran six weeks across 900 paying accounts. The effect on billable units per account per month is plus 4.1 percent, with a 95 percent interval from minus 3.2 to plus 11.8 after clustering standard errors at the account and applying the pre-registered winsorisation at the 99th percentile. An executive with no statistical background wants one number this week to decide a full rollout. Produce a three-sentence spoken answer, one chart, and an explicit recommendation of ship, stop or keep running, with the cost of each option stated.

Approach
  1. The interviewer is probing whether you can be decision-useful without either hiding the uncertainty or hiding behind it. Start from the decision rather than the statistics: establish what the executive would do differently at plus 4 percent versus zero, because if the action is identical the interval does not matter.
  2. Translate the interval into consequences in units the executive already reasons about. Multiply both endpoints by the cohort's baseline consumption and contracted rates to give an annualised revenue range, so the answer is a range of dollars rather than a range of percentages.
  3. Price the option to wait. Using the observed variance, state roughly how many additional account-weeks halve the interval width, so keep running becomes a quantified choice instead of a stall.
  4. Offer a cheaper path to the same decision: a lower-variance proximate outcome such as successful billable units on the new SKU, or CUPED using each account's pre-period consumption, quoting the expected variance reduction as one minus the squared pre-post correlation.
  5. Give a recommendation and name the single observation that would reverse it. A strong answer commits; a generic one recites the interval and leaves the decision on the table.
Follow-up
  • The executive says it clearly works and is just not provable, so ship it. What is your answer?
  • How much of the interval width comes from clustering and how much from the revenue tail, and what would you do about each?
  • If you had to ship this week with no more data, which guardrail would you watch for the first fortnight and at what threshold would you roll back?

Defend a churn number twelve times the one in the board deck

hard
stakeholder managementretention metricsdefinitions

You recompute logo churn on the renewal-eligible base from fct_subscription_period, counting only accounts whose term_end_date fell in the month and allowing a 45-day grace for late paperwork. Annualised, about 14 percent of accounts that reach a renewal date do not renew. A revenue leader has been quoting 1.2 percent to the board for two quarters, computed by dividing non-renewed accounts by the entire customer base in each month and printing that monthly figure with no period attached. You have 20 minutes with that leader and the finance lead. Decide which number is reported from now on, and what happens to the two quarters already published.

Approach
  1. The interviewer is probing whether you can hold a correct definition under social pressure without turning it into a competence dispute. Open by reproducing their 1.2 percent exactly, with their denominator and their months, so the disagreement is arithmetic both sides can see rather than a claim about who was careless.
  2. Separate the two defects, because they are different in kind. The denominator is wrong: on annual contracts only about one twelfth of the base reaches a renewal date in any month, so an account eleven months from renewal sits in the denominator while being structurally incapable of entering the numerator, which suppresses the rate by a factor near twelve. The period is merely unstated: a monthly figure printed beside annual revenue targets gets read as an annual rate.
  3. Say out loud that those two defects nearly cancel in the level, before the leader finds it. Twelve times 1.2 percent is about 14 percent, which is your number. That is the strongest thing you can say in the room, because it proves both figures rest on the same non-renewal count and moves the meeting onto which denominator and which period get published rather than onto whose query is right.
  4. The level is recoverable; the series is not. Non-renewals in a month are the eligible base for that month times the churn rate, so dividing by a fixed whole base makes the published line proportional to how many contracts happen to come up that month. Where signings cluster at quarter ends, the eligible base in a quarter-end month can be several times a quiet month's, and the month-over-month moves the board has been reading as satisfaction are the signing calendar.
  5. Separate the measurement change from a business change. Nothing got worse this week; the loss rate was always this. Bring net revenue retention over the same period as a ratio of sums on a cohort frozen twelve months earlier, because logo churn concentrated in small accounts can sit beside healthy revenue retention, and that combination is the actual story.
  6. Offer a migration path rather than a correction. Report both rates for one quarter with a written bridge, restate the prior two quarters in an appendix instead of silently, and pin the definition, including the period it is stated over, somewhere finance and product both read it. Concede the limits of your own number: the 45-day grace means the most recent 45 days are not reportable, and churn must be dated on term_end_date rather than on updated_at. A strong answer volunteers this; a generic one only defends.
Follow-up
  • The leader multiplies their monthly figure by twelve, lands on your annual number, and concludes nothing was ever wrong. What do you say?
  • The leader says publishing the corrected rate costs the team its credibility with the board this quarter. What do you do?
  • Gross logo retention worsened while net revenue retention improved. Which do you lead with, and what does the combination tell you about who is leaving?
  • 01

    Describe a time you had to parse complex, unstructured data; what techniques did you use?

  • 02

    An account-randomised packaging change ran six weeks across 900 paying accounts. The effect on billable units per account per month is plus 4.1 percent, with a 95 percent interval from minus 3.2 to plus 11.8 after clustering standard errors at the account and applying the pre-registered winsorisation at the 99th percentile. An executive with no statistical background wants one number this week to decide a full rollout. Produce a three-sentence spoken answer, one chart, and an explicit recommendation of ship, stop or keep running, with the cost of each option stated.

  • 03

    You recompute logo churn on the renewal-eligible base from fct_subscription_period, counting only accounts whose term_end_date fell in the month and allowing a 45-day grace for late paperwork. Annualised, about 14 percent of accounts that reach a renewal date do not renew. A revenue leader has been quoting 1.2 percent to the board for two quarters, computed by dividing non-renewed accounts by the entire customer base in each month and printing that monthly figure with no period attached. You have 20 minutes with that leader and the finance lead. Decide which number is reported from now on, and what happens to the two quarters already published.

PracHub interview preparation framework ↗
Is this an official Stanley Reid & interview guide?

No. It is PracHub's own research and practice material for the Data Scientist role at Stanley Reid &. Rounds and questions reflect what candidates have reported, not a process Stanley Reid & has published, and they change over time. Confirm the current format and scope with your recruiter.

PracHub interview research ↗
How difficult are the technical assessments?

The assessments are designed to test practical application rather than rote memorization. You should be prepared to solve problems that mirror the work you would do on the job.

PracHub interview research ↗
What differentiates successful candidates?

Candidates who succeed typically demonstrate a "builder" mindset—they don't just solve the problem, they consider the long-term maintainability and business value of their solution.

PracHub interview research ↗
How long is the typical interview process?

While it varies, most candidates complete the cycle within a few weeks. Stay responsive and prepared so you can move through the stages efficiently.

PracHub interview research ↗
What is the culture like at Stanley Reid &?

Candidates report that interviewers weigh precision, collaboration, and a focus on high-impact results. Interviewers also look for team players who can navigate ambiguity and advocate for the best technical solutions.

PracHub interview research ↗
Sources & methodology 3 sources ↗

No official company page is cited. Rounds and questions come from candidate reports and PracHub editorial material; each source shows the date it was read.