From 981dae64a62c42ea427b89499d8de2d9db218689 Mon Sep 17 00:00:00 2001 From: Pauljd Date: Tue, 3 Nov 2026 23:22:06 +0000 Subject: [PATCH] Stage 4: read-only schedule audit replay (ScheduleAuditTest) and its first results Co-Authored-By: Claude Opus 5.5 (1M context) --- .../tv/orbit/classic/ScheduleAuditTest.kt | 140 ++++++++ docs/replays/schedule-audit-2026-11-03.md | 314 ++++++++++++++++++ 2 files changed, 454 insertions(+) create mode 100644 android/app/src/test/java/tv/orbit/classic/ScheduleAuditTest.kt create mode 100644 docs/replays/schedule-audit-2026-11-03.md diff --git a/android/app/src/test/java/tv/orbit/classic/ScheduleAuditTest.kt b/android/app/src/test/java/tv/orbit/classic/ScheduleAuditTest.kt new file mode 100644 index 0000000..694326c --- /dev/null +++ b/android/app/src/test/java/tv/orbit/classic/ScheduleAuditTest.kt @@ -0,0 +1,140 @@ +package tv.orbit.classic + +import org.json.JSONObject +import org.junit.Assume.assumeTrue +import org.junit.Test +import java.io.File + +/** + * Stage 4's read-only audit, run by hand on copies of the box's files (never the box itself): + * ORBIT_REPLAY_DIR= ./gradlew :app:testDebugUnitTest --tests '*ScheduleAuditTest*' + * Plays each smart channel forward four weeks from its committed plan with today's rules, and writes schedule-audit.md + * there: what each channel's list finds, how its blocks are followed, rotation, repeats, rest, gaps and what never airs. + */ +class ScheduleAuditTest { + private val dir = System.getenv("ORBIT_REPLAY_DIR")?.let(::File) + private val zone = java.time.ZoneId.of("Europe/London") + private val hour = 60 * 60_000L + private val day = 24 * hour + + private fun plan(file: File): ChannelPlan { + val root = JSONObject(file.readText()) + val rows = root.getJSONArray("entries") + val entries = (0 until rows.length()).map { i -> + val o = rows.getJSONObject(i) + val d = o.getLong("d") + val n = o.getJSONArray("n") + ScheduleEntry(o.getString("s"), EpisodeMark(n.getInt(0), n.getInt(1)), ScheduledMedia(SampleItem(o.getString("t"), o.optString("k", "Episode"), d / 60_000, "", o.getString("i"), d), o.getString("c"), d), + o.getLong("a"), o.optString("w"), o.optString("p")) + } + val t = root.getJSONObject("tail"); val marks = t.getJSONObject("marks") + return ChannelPlan(entries, ScheduleCursor(if (t.isNull("last")) null else t.getString("last"), + marks.keys().asSequence().associateWith { id -> marks.getJSONArray(id).let { EpisodeMark(it.getInt(0), it.getInt(1)) } }, + t.optJSONObject("shown")?.let { s -> s.keys().asSequence().associateWith { s.getLong(it) } }.orEmpty(), + t.optJSONObject("blocks")?.let { b -> b.keys().asSequence().associateWith { b.getString(it) } }.orEmpty())) + } + + private fun pool(file: File): List { + val rows = JSONObject(file.readText()).getJSONArray("series") + return (0 until rows.length()).map { i -> + val o = rows.getJSONObject(i); val eps = o.getJSONArray("episodes") + PoolSeries(o.getString("id"), o.getString("title"), (0 until eps.length()).map { j -> + val e = eps.getJSONArray(j); PoolEpisode(e.getString(0), e.getString(1), EpisodeMark(e.getInt(2), e.getInt(3)), e.getString(4), e.getLong(5)) + }, o.optString("group")) + } + } + + private fun pct(a: Int, b: Int) = if (b == 0) "-" else "${(100.0 * a / b).toInt()}%" + private fun hours(ms: Long) = "%.0f h".format(ms / 3_600_000.0) + + @Test fun auditFourWeeks() { + assumeTrue(dir != null && dir.isDirectory) + val md = StringBuilder("# Schedule audit replay (read-only)\n\nFour weeks from each channel's committed plan, with today's rules, on copies of the box's real pools. " + + "\"Committed\" is the plan on the box now; \"New\" is what today's rules book after it.\n") + val allPlans = mutableMapOf>() + for (programming in SmartChannels) { + val number = programming.number + val pf = File(dir, "schedule-$number.json"); val sf = File(dir, "episodes-$number.json") + if (!pf.exists() || !sf.exists()) { md.append("\n## $number ${programming.name}\n\nNo plan or pool on the box.\n"); continue } + val committed = plan(pf); val series = pool(sf) + val all = committed.entries.toMutableList() + var current = committed + var now = committed.entries.first().startMs + SCHEDULE_KEEP_PAST_MS + val end = now + 28 * day + while (now < end) { + current = topUpPlan(current, current.tail, series, now, programming.filmRestMs, programming.finishTogether, programming.dayParts, zone, + shuffle = programming.shuffleEpisodes, mixed = programming::mixes) ?: break + val known = all.map { it.startMs }.toHashSet() + current.entries.filter { it.startMs !in known }.forEach { all += it } + now += 6 * hour + } + all.sortBy { it.startMs } + allPlans[number] = all + val committedEnd = committed.endMs + val fresh = all.filter { it.startMs >= committedEnd } + // The steady state: three weeks of new bookings. + val steady = fresh.filter { it.startMs < committedEnd + 21 * day } + val listed = programming.searches.map(::seriesKey).toSet() + val found = series.map { seriesKey(it.title) }.toSet() + val filmChannel = programming.filmRestMs != null + md.append("\n## $number ${programming.name}\n\n") + md.append("- **Pool:** ${series.size} ${if (filmChannel) "films" else "shows"}, ${series.sumOf { it.episodes.size }} files. List names ${programming.searches.size}; ") + val missing = programming.searches.filter { name -> seriesKey(name) !in found && seriesKey(FilmIdentity.of(name).title) !in found } + md.append("not in the pool: ${missing.size}" + if (missing.isNotEmpty()) " (${missing.take(12).joinToString()}${if (missing.size > 12) ", +${missing.size - 12}" else ""})" else "") + val extras = series.filter { seriesKey(it.title) !in listed && programming.searches.none { n -> seriesKey(FilmIdentity.of(n).title) == seriesKey(it.title) } } + if (extras.isNotEmpty()) md.append("; in the pool but not on the list: ${extras.size} (${extras.take(8).joinToString { it.title }})") + md.append(".\n") + md.append("- **Committed plan:** ${committed.entries.size} programmes to ${java.time.Instant.ofEpochMilli(committedEnd).atZone(zone).toLocalDate()}; reasons recorded on ${committed.entries.count { it.why.isNotEmpty() }}; " + + "booked from today's blocks: ${committed.entries.count { e -> val r = e.why.substringBefore(';'); r.isNotEmpty() && programming.dayParts.any { p -> r == (if (p.days.isNotEmpty()) "event " else "block ") + p.group.ifEmpty { "${p.fromHour}-${p.toHour}" } } }}.\n") + // Blocks: of the new bookings in each block's hours, how many come from its own titles. + if (programming.dayParts.isNotEmpty() && steady.isNotEmpty()) { + md.append("- **Blocks (new bookings, 3 weeks):** ") + md.append(programming.dayParts.joinToString("; ") { part -> + val keys = part.titles.map(::seriesKey).toSet() + part.titles.map { seriesKey(FilmIdentity.of(it).title) } + val inHours = steady.filter { e -> val l = java.time.Instant.ofEpochMilli(e.startMs).atZone(zone); part.covers(l.hour, l.dayOfWeek) } + val own = inHours.count { e -> seriesKey(guideTitleParts(e.media.item.title).first) in keys || seriesKey(e.media.item.title) in keys || (part.group.isNotEmpty()) } + val label = (if (part.key.isNotEmpty()) part.key else "${part.fromHour}-${part.toHour}") + if (part.days.isNotEmpty()) " ${part.days.joinToString("") { it.name.take(2) }}" else "" + "$label ${pct(own, inHours.size)} of ${inHours.size}" + }) + md.append(".\n") + } + // Fallbacks and deferrals the planner recorded. + val fallbacks = steady.count { "fallback" in it.why }; val noBlock = steady.count { it.why.startsWith("no block") } + if (fallbacks + noBlock > 0) md.append("- **Planner fallbacks (3 weeks):** $fallbacks fallback, $noBlock outside any block.\n") + // Airtime and waits, by show. + val airtime = steady.groupBy { it.seriesId }.mapValues { (_, es) -> es.sumOf { it.media.durationMs } } + val total = airtime.values.sum().coerceAtLeast(1) + val never = series.filter { it.id !in airtime } + val top = airtime.entries.sortedByDescending { it.value }.take(5).map { (id, ms) -> "${series.firstOrNull { it.id == id }?.title ?: id} ${(100 * ms / total)}%" } + md.append("- **Airtime (3 weeks):** ${airtime.size} of ${series.size} aired; biggest shares: ${top.joinToString()}.") + if (never.isNotEmpty()) md.append(" Never aired: ${never.size} (${never.take(10).joinToString { it.title }}${if (never.size > 10) ", +${never.size - 10}" else ""}).") + md.append("\n") + // Repeats: the same file twice within 24 hours or 7 days, and films inside their rest. + val byFile = steady.groupBy { it.media.item.id } + val within = { gap: Long -> byFile.values.sumOf { es -> es.sortedBy { it.startMs }.zipWithNext().count { (a, b) -> b.startMs - a.startMs < gap } } } + md.append("- **Repeats (3 weeks):** same file again within 24 h: ${within(day)}; within 7 days: ${within(7 * day)}") + programming.filmRestMs?.let { md.append(" (rest is ${hours(it)})") } + md.append(".\n") + // Progression: an in-order show should never step backwards except to start again. + val backwards = steady.filter { !programming.mixes(series.firstOrNull { s -> s.id == it.seriesId } ?: return@filter false) && !programming.shuffleEpisodes } + .groupBy { it.seriesId }.values.sumOf { es -> es.zipWithNext().count { (a, b) -> b.mark < a.mark && b.mark != EpisodeMark(series.first { it.id == a.seriesId }.episodes.first().mark.season, series.first { it.id == a.seriesId }.episodes.first().mark.episode) } } + if (!filmChannel) md.append("- **Progression:** in-order steps backwards (other than starting again): $backwards.\n") + // Gaps and overlaps across the whole four weeks. + val gaps = all.zipWithNext().filter { (a, b) -> b.startMs - a.endMs > 60_000 } + val overlaps = all.zipWithNext().count { (a, b) -> b.startMs < a.endMs } + md.append("- **Coverage (4 weeks):** gaps over a minute: ${gaps.size}" + (if (gaps.isNotEmpty()) " (largest ${hours(gaps.maxOf { (a, b) -> b.startMs - a.endMs })})" else "") + "; overlaps: $overlaps.\n") + // Events: when each keyed event starts, week by week. + programming.dayParts.filter { it.key.isNotEmpty() && it.days.isNotEmpty() }.forEach { part -> + val starts = fresh.filter { it.presentation == part.key }.groupBy { java.time.Instant.ofEpochMilli(it.startMs).atZone(zone).let { l -> if (l.hour < part.toHour && part.fromHour > part.toHour) l.toLocalDate().minusDays(1) else l.toLocalDate() } } + md.append(" - Event ${part.key}: ${starts.size} nights; first starts ${starts.entries.take(4).joinToString { (d, es) -> "$d ${java.time.Instant.ofEpochMilli(es.first().startMs).atZone(zone).toLocalTime().withNano(0)}" }}.\n") + } + } + // The same file on two channels at once, in the committed plans and the replay. + val clashes = mutableListOf() + val flat = allPlans.flatMap { (n, es) -> es.map { n to it } }.groupBy { it.second.media.item.id } + flat.values.forEach { es -> es.sortedBy { it.second.startMs }.zipWithNext().forEach { (a, b) -> if (a.first != b.first && b.second.startMs < a.second.endMs) clashes += "${a.second.media.item.title.take(40)} on ${a.first} and ${b.first} at ${java.time.Instant.ofEpochMilli(b.second.startMs).atZone(zone).toLocalDateTime()}" } } + md.append("\n## Across channels\n\nThe same file on two channels at once (replay ignores the live clash check, so new bookings may show some): ${clashes.size}${if (clashes.isNotEmpty()) "\n\n" + clashes.take(20).joinToString("\n") { "- $it" } else ""}\n") + File(dir, "schedule-audit.md").writeText(md.toString()) + println("audit written: ${File(dir, "schedule-audit.md")}") + } +} diff --git a/docs/replays/schedule-audit-2026-11-03.md b/docs/replays/schedule-audit-2026-11-03.md new file mode 100644 index 0000000..fca0287 --- /dev/null +++ b/docs/replays/schedule-audit-2026-11-03.md @@ -0,0 +1,314 @@ +# Schedule audit replay (read-only) + +Four weeks from each channel's committed plan, with today's rules, on copies of the box's real pools. "Committed" is the plan on the box now; "New" is what today's rules book after it. + +## 305 After Dark + +- **Pool:** 170 films, 392 files. List names 69; not in the pool: 0; in the pool but not on the list: 101 (The 'Burbs, [REC]², 'Til Death Do Us Part, The Last Drive-in with Joe Bob Briggs, Shaun of the Dead, The League of Gentlemen Are Behind You, Zombieland, Tucker and Dale vs. Evil). +- **Committed plan:** 99 programmes to 2026-11-10; reasons recorded on 0; booked from today's blocks: 0. +- **Blocks (new bookings, 3 weeks):** afterdark.bmovie FR 100% of 8; afterdark.drivein SA 37% of 8; afterdark.cult SU 100% of 7; 21-5 0% of 97; 5-21 100% of 186. +- **Planner fallbacks (3 weeks):** 184 fallback, 0 outside any block. +- **Airtime (3 weeks):** 127 of 170 aired; biggest shares: Koi... Mil Gaya 2%, Mulholland Drive 1%, Mystic River 1%, Donnie Darko 1%, The Name of the Rose 1%. Never aired: 43 ([REC]², Plan 9 from Outer Space, The Return of the Living Dead, Frankenhooker, Night of the Comet, Bad Taste, Them!, It Came from Outer Space, Withnail & I, Pink Flamingos, +33). +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 136 (rest is 168 h). +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + - Event afterdark.bmovie: 4 nights; first starts 2026-11-13 22:17:05, 2026-11-20 21:22:47, 2026-11-27 21:48:46, 2026-12-04 22:51:59. + - Event afterdark.drivein: 4 nights; first starts 2026-11-14 20:54:08, 2026-11-21 21:15:33, 2026-11-28 21:30:56, 2026-12-05 21:31:52. + - Event afterdark.cult: 4 nights; first starts 2026-11-15 21:47:47, 2026-11-22 22:07:08, 2026-11-29 21:15, 2026-12-06 21:43:57. + +## 601 Vortex + +- **Pool:** 117 shows, 7003 files. List names 33; not in the pool: 7 (Justice League Unlimited, Voltron, Gundam Wing, Tenchi Muyo, Tenchi Universe, Cardcaptors, Zoids); in the pool but not on the list: 91 (Yu-Gi-Oh! Zexal, Teknoman, Shadow Skill, Zoids Fuzors, Mortal Kombat: Defenders of the Realm, Murder Princess, Yu-Gi-Oh! 5D's, Tears to Tiara). +- **Committed plan:** 445 programmes to 2026-11-10; reasons recorded on 64; booked from today's blocks: 64. +- **Blocks (new bookings, 3 weeks):** vortex.movie FRSA 100% of 14; 6-12 100% of 337; 12-16 100% of 224; 16-18 100% of 103; 18-21 100% of 151; 21-23 100% of 93; 23-6 100% of 387. +- **Airtime (3 weeks):** 87 of 117 aired; biggest shares: Yu-Gi-Oh! Duel Monsters 3%, Pokémon 3%, Samurai Jack 3%, ThunderCats 3%, Cardcaptor Sakura 3%. Never aired: 30 (Murder Princess, Pokémon: Origins, Karas, Now and Then, Here and There, Zakuro, Legend of the Galactic Heroes Gaiden, Dragon Ball: Mystical Adventure, Dragon Ball Super: Broly, Dragon Ball Z: Wrath of the Dragon, Dragon Ball Z: Dead Zone, +20). +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 0. +- **Progression:** in-order steps backwards (other than starting again): 0. +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + - Event vortex.movie: 8 nights; first starts 2026-11-13 20:07:33, 2026-11-14 20:14:23, 2026-11-20 20:09:04, 2026-11-21 20:07:13. + +## 201 Terra + +- **Pool:** 39 shows, 412 files. List names 46; not in the pool: 6 (Our Planet II, Dynasties, Dynasties II, Africa, South Pacific, Great Barrier Reef). +- **Committed plan:** 200 programmes to 2026-11-10; reasons recorded on 0; booked from today's blocks: 0. +- **Blocks (new bookings, 3 weeks):** terra.sunday SU 100% of 7; 6-18 100% of 289; 18-23 100% of 118; 23-6 100% of 165. +- **Airtime (3 weeks):** 39 of 39 aired; biggest shares: Natural World 5%, Life on Earth 5%, The Living Planet 4%, Life 4%, Prehistoric Planet 4%. +- **Repeats (3 weeks):** same file again within 24 h: 3; within 7 days: 5. +- **Progression:** in-order steps backwards (other than starting again): 0. +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + - Event terra.sunday: 4 nights; first starts 2026-11-15 20:06:58, 2026-11-22 20:37:50, 2026-11-29 20:19:33, 2026-12-06 20:33:31. + +## 614 Tots + +- **Pool:** 36 shows, 4141 files. List names 36; not in the pool: 0. +- **Committed plan:** 740 programmes to 2026-11-10; reasons recorded on 0; booked from today's blocks: 0. +- **Blocks (new bookings, 3 weeks):** 6-9 100% of 294; 9-17 100% of 765; 17-21 100% of 333; 21-6 100% of 752. +- **Airtime (3 weeks):** 34 of 36 aired; biggest shares: In The Night Garden 38%, Teletubbies 7%, Clangers 6%, CBeebies Bedtime Stories 4%, BeddyByes 3%. Never aired: 2 (Balamory (2026), Andy's Dinosaur Adventures). +- **Repeats (3 weeks):** same file again within 24 h: 5; within 7 days: 352. +- **Progression:** in-order steps backwards (other than starting again): 0. +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 106 Paradox + +- **Pool:** 18 shows, 2324 files. List names 18; not in the pool: 0. +- **Committed plan:** 222 programmes to 2026-11-10; reasons recorded on 222; booked from today's blocks: 222. +- **Blocks (new bookings, 3 weeks):** 6-18 100% of 350; 18-23 100% of 146; 23-6 100% of 185. +- **Airtime (3 weeks):** 18 of 18 aired; biggest shares: The X-Files 9%, Doctor Who (2005) 7%, Star Trek: The Next Generation 6%, Sliders 6%, Eureka 6%. +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 0. +- **Progression:** in-order steps backwards (other than starting again): 0. +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 101 Orbit 1 + +- **Pool:** 46 shows, 6897 files. List names 46; not in the pool: 0. +- **Committed plan:** 451 programmes to 2026-11-10; reasons recorded on 65; booked from today's blocks: 65. +- **Blocks (new bookings, 3 weeks):** 18-20 SU 100% of 8; 6-18 SASU 100% of 148; 6-18 76% of 633; 18-0 97% of 328; 0-6 100% of 328. +- **Airtime (3 weeks):** 45 of 46 aired; biggest shares: The Golden Girls 8%, Frasier 8%, Everybody Loves Raymond 8%, Happy Days 3%, Kenan & Kel 2%. Never aired: 1 (Not Going Out). +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 0. +- **Progression:** in-order steps backwards (other than starting again): 0. +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 104 Orbit Gold + +- **Pool:** 44 shows, 2122 files. List names 44; not in the pool: 0. +- **Committed plan:** 373 programmes to 2026-11-10; reasons recorded on 52; booked from today's blocks: 0. +- **Blocks (new bookings, 3 weeks):** gold.sunday SU 100% of 19; 17-19 SA 100% of 8; 6-17 100% of 481; 17-22 95% of 199; 22-2 100% of 169; 2-6 100% of 167. +- **Airtime (3 weeks):** 44 of 44 aired; biggest shares: Only Fools and Horses 8%, Dad's Army 7%, Waiting for God 6%, As Time Goes By 6%, Are You Being Served? 6%. +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 0. +- **Progression:** in-order steps backwards (other than starting again): 0. +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + - Event gold.sunday: 4 nights; first starts 2026-11-15 18:15:12, 2026-11-22 18:21:55, 2026-11-29 18:07:13, 2026-12-06 18:20:58. + +## 103 Orbit Three + +- **Pool:** 45 shows, 1473 files. List names 45; not in the pool: 0. +- **Committed plan:** 385 programmes to 2026-11-10; reasons recorded on 52; booked from today's blocks: 0. +- **Blocks (new bookings, 3 weeks):** three.scottish FRSA 100% of 39; 6-18 100% of 544; 18-22 92% of 161; 22-2 84% of 179; 2-6 100% of 185. +- **Airtime (3 weeks):** 41 of 45 aired; biggest shares: Still Game 10%, Two Pints of Lager and a Packet of Crisps 9%, Limmy's Show! 6%, The Inbetweeners 5%, Rab C. Nesbitt 5%. Never aired: 4 (Gavin & Stacey, The Mighty Boosh, Spaced, Phoenix Nights). +- **Repeats (3 weeks):** same file again within 24 h: 33; within 7 days: 120. +- **Progression:** in-order steps backwards (other than starting again): 0. +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + - Event three.scottish: 8 nights; first starts 2026-11-13 21:10:18, 2026-11-14 21:12:57, 2026-11-20 21:02:34, 2026-11-21 21:16:53. + +## 105 Riot + +- **Pool:** 49 shows, 6544 files. List names 49; not in the pool: 0. +- **Committed plan:** 474 programmes to 2026-11-10; reasons recorded on 64; booked from today's blocks: 0. +- **Blocks (new bookings, 3 weeks):** riot.stunts SA 100% of 15; 6-18 100% of 688; riot.laughs 100% of 156; riot.afterhours 95% of 304; 2-6 100% of 373. +- **Airtime (3 weeks):** 48 of 49 aired; biggest shares: Futurama 6%, King of the Hill 6%, Bob's Burgers 6%, American Dad! 6%, The Cleveland Show 5%. Never aired: 1 (How I Met Your Mother). +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 0. +- **Progression:** in-order steps backwards (other than starting again): 0. +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + - Event riot.stunts: 4 nights; first starts 2026-11-14 22:26:10, 2026-11-21 22:02:14, 2026-11-28 22:22:47, 2026-12-05 22:21:24. + +## 602 Heroes + +- **Pool:** 19 shows, 1022 files. List names 20; not in the pool: 1 (Justice League Unlimited). +- **Committed plan:** 491 programmes to 2026-11-10; reasons recorded on 68; booked from today's blocks: 0. +- **Blocks (new bookings, 3 weeks):** 7-11 SA 100% of 33; 6-15 100% of 516; 15-18 100% of 176; 18-22 100% of 228; 22-6 100% of 456. +- **Airtime (3 weeks):** 19 of 19 aired; biggest shares: Teen Titans 11%, Young Justice 10%, Justice League 8%, Static Shock 8%, Batman: The Animated Series 8%. +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 82. +- **Progression:** in-order steps backwards (other than starting again): 0. +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 605 ToonZ + +- **Pool:** 17 shows, 2269 files. List names 24; not in the pool: 7 (Popeye, Dastardly and Muttley in Their Flying Machines, The Pink Panther Show, Merrie Melodies, The Bugs Bunny Show, The Tom and Jerry Show, Woody Woodpecker). +- **Committed plan:** 732 programmes to 2026-11-10; reasons recorded on 111; booked from today's blocks: 0. +- **Blocks (new bookings, 3 weeks):** 6-10 100% of 525; 10-16 100% of 795; 16-18 100% of 243; 18-0 100% of 733; 0-6 100% of 748. +- **Airtime (3 weeks):** 17 of 17 aired; biggest shares: Looney Tunes 29%, Tom and Jerry 23%, The Jetsons 6%, The Looney Tunes Show 5%, Scooby-Doo, Where Are You! 5%. +- **Repeats (3 weeks):** same file again within 24 h: 1; within 7 days: 879. +- **Progression:** in-order steps backwards (other than starting again): 0. +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 604 Rewind + +- **Pool:** 23 shows, 3135 files. List names 25; not in the pool: 0. +- **Committed plan:** 558 programmes to 2026-11-10; reasons recorded on 79; booked from today's blocks: 0. +- **Blocks (new bookings, 3 weeks):** 6-9 100% of 197; 9-15 100% of 424; 15-19 100% of 317; 19-23 100% of 282; 23-6 100% of 553. +- **Airtime (3 weeks):** 23 of 23 aired; biggest shares: The Powerpuff Girls 12%, Ed, Edd n Eddy 9%, Codename: Kids Next Door 8%, Courage the Cowardly Dog 7%, Rugrats 6%. +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 86. +- **Progression:** in-order steps backwards (other than starting again): 0. +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 603 Orbit X + +- **Pool:** 21 shows, 2721 files. List names 24; not in the pool: 3 (Digimon Adventure, Mighty Morphin Power Rangers, G.I. Joe: A Real American Hero). +- **Committed plan:** 482 programmes to 2026-11-10; reasons recorded on 65; booked from today's blocks: 0. +- **Blocks (new bookings, 3 weeks):** 7-12 SA 100% of 43; 15-18 MOTUWETHFR 100% of 123; 6-18 93% of 686; 18-23 100% of 291; 23-6 100% of 399. +- **Airtime (3 weeks):** 19 of 21 aired; biggest shares: G.I. Joe 17%, Power Rangers 15%, Teenage Mutant Ninja Turtles 10%, Digimon: Digital Monsters 6%, Captain Planet and the Planeteers 6%. Never aired: 2 (Bucky O'Hare and the Toad Wars!, Visionaries: Knights of the Magical Light). +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 22. +- **Progression:** in-order steps backwards (other than starting again): 0. +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 107 Evidence + +- **Pool:** 30 shows, 5100 files. List names 31; not in the pool: 1 (Castle). +- **Committed plan:** 173 programmes to 2026-11-10; reasons recorded on 25; booked from today's blocks: 0. +- **Blocks (new bookings, 3 weeks):** 20-22 SU 100% of 4; 6-18 100% of 320; 18-21 98% of 50; 21-1 98% of 80; 1-6 100% of 141. +- **Airtime (3 weeks):** 30 of 30 aired; biggest shares: Columbo 9%, CSI: Miami 5%, CSI: Crime Scene Investigation 5%, NCIS 5%, Law & Order 5%. +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 0. +- **Progression:** in-order steps backwards (other than starting again): 0. +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 204 Dark Files + +- **Pool:** 46 shows, 6025 files. List names 52; not in the pool: 6 (The Staircase, Crime Scene: The Vanishing at the Cecil Hotel, Homicide Hunter, Ancient Mysteries, Hangar 1: The UFO Files, My Ghost Story). +- **Committed plan:** 250 programmes to 2026-11-10; reasons recorded on 35; booked from today's blocks: 35. +- **Blocks (new bookings, 3 weeks):** 14-18 SASU 100% of 29; 6-18 100% of 342; 18-21 100% of 91; 21-6 100% of 279. +- **Airtime (3 weeks):** 43 of 46 aired; biggest shares: Making a Murderer 4%, Dateline NBC 4%, The Jinx 4%, Paranormal Witness 3%, Most Haunted 3%. Never aired: 3 (The First 48, Dark Tourist, Haunted). +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 1. +- **Progression:** in-order steps backwards (other than starting again): 0. +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 308 Detour + +- **Pool:** 88 films, 88 files. List names 91; not in the pool: 3 (Van Wilder, Van Wilder: The Rise of Taj, Borat). +- **Committed plan:** 111 programmes to 2026-11-10; reasons recorded on 16; booked from today's blocks: 0. +- **Planner fallbacks (3 weeks):** 257 fallback, 0 outside any block. +- **Airtime (3 weeks):** 88 of 88 aired; biggest shares: The 40 Year Old Virgin 1%, Wedding Crashers 1%, Bridesmaids 1%, The Other Guys 1%, Get Him to the Greek 1%. +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 216 (rest is 168 h). +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 309 BritX + +- **Pool:** 90 films, 90 files. List names 93; not in the pool: 2 (Green Street, Alan Partridge). +- **Committed plan:** 108 programmes to 2026-11-10; reasons recorded on 16; booked from today's blocks: 0. +- **Planner fallbacks (3 weeks):** 252 fallback, 0 outside any block. +- **Airtime (3 weeks):** 90 of 90 aired; biggest shares: Legend 1%, Pride 1%, Quadrophenia 1%, The Krays 1%, Local Hero 1%. +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 204 (rest is 168 h). +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 611 Orbit Junior + +- **Pool:** 48 shows, 6081 files. List names 55; not in the pool: 7 (Thomas & Friends, The Clangers, Rainbow, Noddy, Balamory, Fimbles, Bluey). +- **Committed plan:** 941 programmes to 2026-11-10; reasons recorded on 134; booked from today's blocks: 0. +- **Blocks (new bookings, 3 weeks):** 6-9 100% of 309; 9-15 100% of 365; 15-18 100% of 166; 18-20 100% of 86; 20-6 100% of 580. +- **Airtime (3 weeks):** 48 of 48 aired; biggest shares: Shaun the Sheep 5%, The Story of Tracy Beaker 4%, Byker Grove 4%, Rentaghost 4%, Knightmare 4%. +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 0. +- **Progression:** in-order steps backwards (other than starting again): 0. +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 203 Orbit Wild + +- **Pool:** 25 shows, 2853 files. List names 28; not in the pool: 3 (Crocodile Hunter Diaries, Monster Fish, Dangerous Encounters with Brady Barr). +- **Committed plan:** 248 programmes to 2026-11-10; reasons recorded on 34; booked from today's blocks: 0. +- **Blocks (new bookings, 3 weeks):** 22-6 SA 100% of 29; 6-18 100% of 321; 18-22 100% of 107; 22-6 98% of 219. +- **Airtime (3 weeks):** 24 of 25 aired; biggest shares: Naked and Afraid 15%, Alone 15%, Whale Wars 7%, Man vs. Wild 6%, Swamp People 4%. Never aired: 1 (Dual Survival). +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 0. +- **Progression:** in-order steps backwards (other than starting again): 0. +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 102 Orbit 2 + +- **Pool:** 53 shows, 6951 files. List names 53; not in the pool: 0. +- **Committed plan:** 283 programmes to 2026-11-10; reasons recorded on 35; booked from today's blocks: 35. +- **Blocks (new bookings, 3 weeks):** orbit2.spooky FR 100% of 14; 6-15 100% of 272; 15-18 94% of 101; 18-21 91% of 97; 21-0 100% of 112; orbit2.retro 100% of 173. +- **Airtime (3 weeks):** 53 of 53 aired; biggest shares: Robot Wars 11%, MythBusters 10%, Top Gear 6%, How It's Made 4%, The Gadget Show 3%. +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 0. +- **Progression:** in-order steps backwards (other than starting again): 0. +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + - Event orbit2.spooky: 4 nights; first starts 2026-11-13 17:27:30, 2026-11-20 17:24:30, 2026-11-27 17:17:42, 2026-12-04 17:13:24. + +## 612 Wonder + +- **Pool:** 92 films, 92 files. List names 94; not in the pool: 2 (The Secret World of Arrietty, The Tale of Princess Kaguya). +- **Committed plan:** 117 programmes to 2026-11-10; reasons recorded on 17; booked from today's blocks: 0. +- **Planner fallbacks (3 weeks):** 299 fallback, 0 outside any block. +- **Airtime (3 weeks):** 92 of 92 aired; biggest shares: Princess Mononoke 1%, Spirited Away 1%, Castle in the Sky 1%, Pom Poko 1%, Howl's Moving Castle 1%. +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 255 (rest is 168 h). +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 613 PixelZ + +- **Pool:** 100 films, 100 files. List names 100; not in the pool: 0. +- **Committed plan:** 112 programmes to 2026-11-10; reasons recorded on 15; booked from today's blocks: 0. +- **Planner fallbacks (3 weeks):** 212 fallback, 0 outside any block. +- **Airtime (3 weeks):** 100 of 100 aired; biggest shares: Raya and the Last Dragon 1%, Spider-Man: Across the Spider-Verse 1%, Epic 1%, How to Train Your Dragon 2 1%, Frozen II 1%. +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 209 (rest is 168 h). +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 306 Orbit VHS + +- **Pool:** 96 films, 96 files. List names 97; not in the pool: 0. +- **Committed plan:** 104 programmes to 2026-11-10; reasons recorded on 15; booked from today's blocks: 0. +- **Planner fallbacks (3 weeks):** 232 fallback, 0 outside any block. +- **Airtime (3 weeks):** 96 of 96 aired; biggest shares: Coming to America 1%, Trading Places 1%, Hook 1%, The Mighty Ducks 1%, The Blues Brothers 1%. +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 196 (rest is 168 h). +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 303 Orbit Sci-Fi + +- **Pool:** 98 films, 98 files. List names 100; not in the pool: 1 (Alien 3). +- **Committed plan:** 91 programmes to 2026-11-10; reasons recorded on 12; booked from today's blocks: 0. +- **Airtime (3 weeks):** 98 of 98 aired; biggest shares: Dune: Part Two 1%, Blade Runner 2049 1%, Dune 1%, Aliens 1%, Star Wars: The Last Jedi 1%. +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 0 (rest is 168 h). +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 304 Orbit Horror + +- **Pool:** 113 films, 113 files. List names 115; not in the pool: 2 (Ringu, Pet Sematary Two). +- **Committed plan:** 106 programmes to 2026-11-10; reasons recorded on 15; booked from today's blocks: 0. +- **Blocks (new bookings, 3 weeks):** horror.slasher SA 100% of 12. +- **Planner fallbacks (3 weeks):** 0 fallback, 284 outside any block. +- **Airtime (3 weeks):** 113 of 113 aired; biggest shares: It Chapter Two 1%, Doctor Sleep 1%, The Shining 1%, Rosemary's Baby 1%, The Conjuring 2 1%. +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 0 (rest is 168 h). +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + - Event horror.slasher: 4 nights; first starts 2026-11-14 21:23:22, 2026-11-21 20:34:50, 2026-11-28 20:10:12, 2026-12-05 20:06:49. + +## 302 Orbit Action + +- **Pool:** 104 films, 104 files. List names 108; not in the pool: 4 (Rambo: First Blood, Bloodsport, Crank, Crank). +- **Committed plan:** 98 programmes to 2026-11-10; reasons recorded on 13; booked from today's blocks: 0. +- **Airtime (3 weeks):** 104 of 104 aired; biggest shares: Sicario 1%, Heat 1%, The Raid 2 1%, Bad Boys II 1%, Man on Fire 1%. +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 0 (rest is 168 h). +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 307 Orbit Romance + +- **Pool:** 98 films, 98 files. List names 98; not in the pool: 0. +- **Committed plan:** 96 programmes to 2026-11-10; reasons recorded on 14; booked from today's blocks: 0. +- **Airtime (3 weeks):** 98 of 98 aired; biggest shares: Gone with the Wind 2%, Titanic 1%, The Sound of Music 1%, West Side Story 1%, Sense and Sensibility 1%. +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 0 (rest is 168 h). +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 301 Orbit Premiere + +- **Pool:** 98 films, 98 files. List names 98; not in the pool: 0. +- **Committed plan:** 78 programmes to 2026-11-10; reasons recorded on 11; booked from today's blocks: 0. +- **Airtime (3 weeks):** 98 of 98 aired; biggest shares: Superman 1%, Avengers: Endgame 1%, Saving Private Ryan 1%, No Time to Die 1%, Avatar 1%. +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 0 (rest is 168 h). +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 202 Odyssey + +- **Pool:** 36 shows, 1484 files. List names 49; not in the pool: 13 (Cosmos: A Spacetime Odyssey, Apollo 11, Engineering the Impossible, Big Bigger Biggest, Air Crash Investigation, Civilizations, The Vietnam War, Egypt's Lost Cities, Rome's Greatest Battles, Ancient Apocalypse, Parts Unknown, Michael Palin's Himalaya, +1). +- **Committed plan:** 220 programmes to 2026-11-10; reasons recorded on 32; booked from today's blocks: 0. +- **Blocks (new bookings, 3 weeks):** 14-18 SASU 100% of 29; 6-18 100% of 387; 18-23 100% of 143; 23-6 100% of 193. +- **Airtime (3 weeks):** 23 of 36 aired; biggest shares: The Universe 28%, Mayday 11%, Impossible Engineering 8%, How Do They Do It? 7%, Megastructures 5%. Never aired: 13 (Cosmos, Wonders of the Universe, Wonders of the Solar System, James May's Man Lab, The Ascent of Man, The Story of Maths, Walking with Dinosaurs, Civilisation, The Civil War, The Story of India, +3). +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 41. +- **Progression:** in-order steps backwards (other than starting again): 0. +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + +## 401 Ring X + +- **Pool:** 89 shows, 9129 files. List names 65; not in the pool: 25 (WWE Monday Night RAW, WWF Monday Night RAW, WWF Raw, WWF RAW is WAR, WCW Nitro, TNA iMPACT!, TNA Impact!, TNA Impact Wrestling, TNA Wrestling, AEW Dynamite, AEW Rampage, AEW Collision, +13); in the pool but not on the list: 52 (WWE WrestleMania III, WCW Capital Combat: The Return of RoboCop, ECW Hardcore Heaven 1996, AEW Double or Nothing 2019, WWE WrestleMania 39 Sunday, NWA Starrcade 1983, WWE Survivor Series 1987, NJPW Wrestle Kingdom 11). +- **Committed plan:** 196 programmes to 2026-11-10; reasons recorded on 33; booked from today's blocks: 0. +- **Blocks (new bookings, 3 weeks):** ringx.monday MO 100% of 16; ringx.tuesday TU 100% of 12; ringx.wednesday WE 100% of 10; ringx.thursday TH 100% of 11; ringx.friday FR 100% of 21; ringx.saturday SA 100% of 16; ringx.ppv SU 100% of 3; 6-23 77% of 348; 23-6 100% of 170. +- **Airtime (3 weeks):** 39 of 89 aired; biggest shares: WCW Clash of the Champions 11%, WWF Prime Time Wrestling 9%, WWE NXT 9%, WCW Saturday Night 9%, Biography: WWE Legends 7%. Never aired: 50 (All Elite Wrestling: Battle of the Belts, AEW Double or Nothing 2019, WWE WrestleMania 39 Sunday, NWA Starrcade 1983, WWE Survivor Series 1987, NJPW Wrestle Kingdom 11, TNA Unbreakable 2005, WCW Fall Brawl 1997, WWE Royal Rumble 2022, ECW One Night Stand 2005, +40). +- **Repeats (3 weeks):** same file again within 24 h: 0; within 7 days: 0. +- **Progression:** in-order steps backwards (other than starting again): 0. +- **Coverage (4 weeks):** gaps over a minute: 0; overlaps: 0. + - Event ringx.monday: 4 nights; first starts 2026-11-16 19:45:55, 2026-11-23 18:23:09, 2026-11-30 18:07:57, 2026-12-07 18:11:19. + - Event ringx.tuesday: 4 nights; first starts 2026-11-10 18:48:48, 2026-11-17 18:02:34, 2026-11-24 19:19:33, 2026-12-01 19:03. + - Event ringx.wednesday: 4 nights; first starts 2026-11-11 18:23:24, 2026-11-18 18:06:56, 2026-11-25 19:25:10, 2026-12-02 19:29:37. + - Event ringx.thursday: 4 nights; first starts 2026-11-12 18:10:43, 2026-11-19 18:36:21, 2026-11-26 18:45:18, 2026-12-03 19:06:55. + - Event ringx.friday: 4 nights; first starts 2026-11-13 18:47:46, 2026-11-20 18:06:06, 2026-11-27 18:26:20, 2026-12-04 18:06:19. + - Event ringx.saturday: 4 nights; first starts 2026-11-14 18:41:40, 2026-11-21 18:34:05, 2026-11-28 18:06:08, 2026-12-05 18:25:20. + - Event ringx.ppv: 4 nights; first starts 2026-11-15 19:06:44, 2026-11-22 19:15:52, 2026-11-29 19:02:29, 2026-12-06 19:10:20. + +## Across channels + +The same file on two channels at once (replay ignores the live clash check, so new bookings may show some): 2 + +- Braindead on 305 and 304 at 2026-11-14T11:30:53.898 +- Shaun of the Dead on 309 and 305 at 2026-11-07T14:43:14.483