0.99.0: Ring X weeknight flagships are appointments, so they start near 18:00
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,8 +9,8 @@ android {
|
||||
applicationId = "tv.orbit.classic"
|
||||
minSdk = 26
|
||||
targetSdk = 36
|
||||
versionCode = 129
|
||||
versionName = "0.98.0-weighted-rollout"
|
||||
versionCode = 130
|
||||
versionName = "0.99.0-ringx-weeknights"
|
||||
}
|
||||
buildFeatures { compose = true }
|
||||
compileOptions { sourceCompatibility = JavaVersion.VERSION_17; targetCompatibility = JavaVersion.VERSION_17 }
|
||||
|
||||
@@ -350,10 +350,11 @@ private val RingXSaturday = listOf("Ring of Honor (2002) [imdb-] [tvdb-386985]",
|
||||
private val RingXLate = listOf("Dark Side of the Ring", "The Monday Night War", "WWE Untold", "WWE Rivals", "Biography: WWE Legends", "WWE Icons", "WWE Ruthless Aggression",
|
||||
"Who Killed WCW?", "The Wrestlers", "Wrestlers", "WWE Legends House", "WWE NXT")
|
||||
internal val RingXShows get() = (RingXMonday + RingXTuesday + RingXWednesday + RingXThursday + RingXFriday + RingXSaturday + RingXDaytimeVault + RingXLate + RingXVault).distinct()
|
||||
// The weeknight flagships are appointments (4 November 2026): the vault before 18:00 is chosen to finish in time, so the night starts near its hour.
|
||||
internal val RingXDayParts get() = listOf(
|
||||
DayPart(18, 23, RingXMonday, days = setOf(DayOfWeek.MONDAY), key = "ringx.monday"), DayPart(18, 23, RingXTuesday, days = setOf(DayOfWeek.TUESDAY), key = "ringx.tuesday"),
|
||||
DayPart(18, 23, RingXWednesday, days = setOf(DayOfWeek.WEDNESDAY), key = "ringx.wednesday"), DayPart(18, 23, RingXThursday, days = setOf(DayOfWeek.THURSDAY), key = "ringx.thursday"),
|
||||
DayPart(18, 23, RingXFriday, days = setOf(DayOfWeek.FRIDAY), key = "ringx.friday"), DayPart(18, 23, RingXSaturday, days = setOf(DayOfWeek.SATURDAY), key = "ringx.saturday"),
|
||||
DayPart(18, 23, RingXMonday, days = setOf(DayOfWeek.MONDAY), onTime = true, key = "ringx.monday"), DayPart(18, 23, RingXTuesday, days = setOf(DayOfWeek.TUESDAY), onTime = true, key = "ringx.tuesday"),
|
||||
DayPart(18, 23, RingXWednesday, days = setOf(DayOfWeek.WEDNESDAY), onTime = true, key = "ringx.wednesday"), DayPart(18, 23, RingXThursday, days = setOf(DayOfWeek.THURSDAY), onTime = true, key = "ringx.thursday"),
|
||||
DayPart(18, 23, RingXFriday, days = setOf(DayOfWeek.FRIDAY), onTime = true, key = "ringx.friday"), DayPart(18, 23, RingXSaturday, days = setOf(DayOfWeek.SATURDAY), onTime = true, key = "ringx.saturday"),
|
||||
// PPV Sunday: one event, starting near 19:00 and running to its natural end, however late.
|
||||
DayPart(19, 20, PpvSunday, days = setOf(DayOfWeek.SUNDAY), onTime = true, once = true, key = "ringx.ppv"),
|
||||
DayPart(6, 23, RingXDaytimeVault), DayPart(23, 6, RingXLate))
|
||||
|
||||
@@ -66,7 +66,7 @@ internal class HttpsEmbyTransport(internal val deviceId: String = UUID.randomUUI
|
||||
connection.connectTimeout = 10_000
|
||||
connection.readTimeout = request.readTimeoutMs ?: if (request.path == "/Sessions/Logout") 5_000 else 15_000
|
||||
connection.setRequestProperty("Accept", "application/json")
|
||||
connection.setRequestProperty("X-Emby-Authorization", "Emby Client=\"Orbit TV\", Device=\"Orbit TV\", DeviceId=\"$deviceId\", Version=\"0.98.0\"")
|
||||
connection.setRequestProperty("X-Emby-Authorization", "Emby Client=\"Orbit TV\", Device=\"Orbit TV\", DeviceId=\"$deviceId\", Version=\"0.99.0\"")
|
||||
request.token?.let { connection.setRequestProperty("X-Emby-Token", it) }
|
||||
if (request.method == "POST") {
|
||||
val bytes = request.body.orEmpty().toByteArray(Charsets.UTF_8)
|
||||
|
||||
@@ -33,7 +33,7 @@ internal class SecureMediaDataSource(private val session: EmbySampleSession) : B
|
||||
next.instanceFollowRedirects = false
|
||||
next.connectTimeout = 10_000
|
||||
next.readTimeout = 20_000
|
||||
next.setRequestProperty("User-Agent", "OrbitTV/0.98.0")
|
||||
next.setRequestProperty("User-Agent", "OrbitTV/0.99.0")
|
||||
next.setRequestProperty("Accept-Encoding", "identity")
|
||||
session.mediaHeaders(address).forEach { (key, value) -> next.setRequestProperty(key, value) }
|
||||
if (dataSpec.position != 0L || dataSpec.length != C.LENGTH_UNSET.toLong()) {
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package tv.orbit.classic
|
||||
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import java.time.DayOfWeek
|
||||
|
||||
class RingXWeeknightsTest {
|
||||
private val zone = java.time.ZoneId.of("Europe/London")
|
||||
private val day = 24 * 60 * 60_000L
|
||||
private val ring get() = SmartChannels.first { it.number == 401 }
|
||||
|
||||
@Test fun theSixWeeknightsAreAppointmentsAndNothingElseChanged() {
|
||||
val nights = ring.dayParts.filter { it.fromHour == 18 && it.toHour == 23 }
|
||||
assertEquals(DayOfWeek.entries.filter { it != DayOfWeek.SUNDAY }.toSet(), nights.flatMap { it.days }.toSet())
|
||||
assertTrue(nights.all { it.onTime && !it.once && it.key.startsWith("ringx.") })
|
||||
val ppv = ring.dayParts.single { it.key == "ringx.ppv" }
|
||||
assertTrue(ppv.onTime && ppv.once && ppv.fromHour == 19)
|
||||
assertTrue(ring.dayParts.filter { it.days.isEmpty() }.none { it.onTime })
|
||||
}
|
||||
|
||||
@Test fun theNightStartsNearItsHourWithNothingCut() {
|
||||
// Vault episodes of awkward lengths, so the daytime never lands on 18:00 by itself.
|
||||
fun show(title: String, minutes: Int) = PoolSeries(title, title, (1..300).map { PoolEpisode("$title-$it", "src", EpisodeMark(1, it), "E$it", minutes * 60_000L) })
|
||||
val titles = ring.dayParts.flatMap { it.titles }.distinct()
|
||||
val pool = titles.filter { it in listOf("WWF Prime Time Wrestling", "WWE Heat", "WCW Saturday Night", "WWE Raw", "WCW Monday Nitro", "IMPACT! Wrestling", "All Elite Wrestling: Dynamite",
|
||||
"WWE SmackDown", "ECW Hardcore TV", "NJPW Strong", "Dark Side of the Ring", "WWE Untold") }.mapIndexed { i, t -> show(t, listOf(47, 89, 63, 41, 118, 52)[i % 6]) }
|
||||
val start = java.time.LocalDate.of(2026, 11, 16).atStartOfDay(zone).toInstant().toEpochMilli()
|
||||
val plan = extendSchedule(pool, ScheduleCursor(), start, start + 14 * day, finishTogether = true, dayParts = ring.dayParts, zone = zone)
|
||||
plan.entries.zipWithNext().forEach { (a, b) -> assertEquals(a.endMs, b.startMs) }
|
||||
val firsts = plan.entries.filter { "event 18-23" in it.why }.groupBy { java.time.Instant.ofEpochMilli(it.startMs).atZone(zone).toLocalDate() }
|
||||
.map { (date, es) -> (es.minOf { it.startMs } - date.atTime(18, 0).atZone(zone).toInstant().toEpochMilli()) / 60_000 }
|
||||
assertEquals(12, firsts.size)
|
||||
assertTrue("late by $firsts", firsts.all { it in 0..20 })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
# Orbit TV 0.99.0: Ring X weeknight flagships start on time
|
||||
|
||||
This is the first of the isolated editorial corrections, approved as the next task by Paul on 4 November 2026 at 00:55. The change is to scheduling only, for Ring X (401) only.
|
||||
|
||||
## What's in it
|
||||
|
||||
The six weeknight blocks (Monday to Saturday, 18:00 to 23:00) are now appointments (`onTime = true` in `RingXDayParts`). This is the mechanism PPV Sunday has used since 0.94.0:
|
||||
- In the 90 minutes before 18:00, the vault programmes are picked, in their normal turn where possible, so one ends at the appointment or within its first 20 minutes.
|
||||
- Nothing is cut, no gap is left, and nothing extra is added.
|
||||
|
||||
Unchanged:
|
||||
- the weeknight line-ups and their presentation keys and idents
|
||||
- PPV Sunday
|
||||
- the daytime vault and Late blocks
|
||||
- equal-turns rotation with finish-together, since Ring X isn't weighted
|
||||
- every other channel
|
||||
|
||||
## Checks before install
|
||||
|
||||
- **400 unit tests pass.** Lint has no errors.
|
||||
- **New RingXWeeknightsTest:**
|
||||
- The six weeknights are on time, with PPV Sunday still on time and once a night, and no everyday block changed.
|
||||
- On a pool with awkward episode lengths, every weeknight over two weeks starts 0 to 20 minutes after 18:00, with no gaps.
|
||||
- **Four-week replay on Ring X's real pool, from box copies taken at 00:40** (docs/replays/editorial-corrections-2026-11-04.txt, EditorialCorrectionsAuditTest). It covers 19 weeknights booked after the committed plan, with every channel booking together:
|
||||
|
||||
| | Median late | Worst | Within 10 min | Gaps |
|
||||
|---|---|---|---|---|
|
||||
| 0.98.0 | 34 min | 105 min | 6 of 19 | 0 |
|
||||
| 0.99.0 | 8 min | 37 min | 12 of 19 | 0 |
|
||||
|
||||
The two worst nights (Saturday 37 minutes, Monday 30 minutes) are when no vault programme in its turn fits the run-in. The grace of the existing rule then lets the night start late rather than cut anything.
|
||||
- **Fingerprints** (docs/replays/replay-fingerprints-0.99.0.txt): a four-week replay of all 30 channels on 0.98.0 and 0.99.0.
|
||||
- Every committed fingerprint is identical.
|
||||
- Only 401 differs.
|
||||
- The presentation replay is unchanged (83 transitions, committedKeptExactly=true), and Ring X's weeknight idents still mark their nights.
|
||||
|
||||
## Known limits
|
||||
|
||||
- Ring X's committed plan runs to about 10 November, so new bookings follow this rule from then, in line with Paul's plan for one coordinated cutover later.
|
||||
- Tested here as scheduling logic only.
|
||||
|
||||
## Rollback
|
||||
|
||||
Install 0.98.0. No saved data changes.
|
||||
@@ -0,0 +1,71 @@
|
||||
# Four-week replay fingerprints, 0.98.0 (837f97a) against 0.99.0, from box copies taken 4 November 00:40
|
||||
|
||||
## 0.98.0
|
||||
101 committed=e2a56999e8a008ea kept=true fourWeeks=3de1a3331b6a294b programmes=2129
|
||||
102 committed=06fdb544423630d5 kept=true fourWeeks=c144df512c1e2b22 programmes=1285
|
||||
103 committed=17078bdc852aefc4 kept=true fourWeeks=c85d48a217a10c94 programmes=1797
|
||||
104 committed=811d1bee8e3abe5e kept=true fourWeeks=a2236f9d16315f19 programmes=1706
|
||||
105 committed=d8131ecf0e387195 kept=true fourWeeks=ffe3db054189fe0a programmes=2439
|
||||
106 committed=c6e05fe7b6b8119e kept=true fourWeeks=26f095b2150baf74 programmes=1158
|
||||
107 committed=9d18785a275d37ad kept=true fourWeeks=98d3ec7d2cc2452e programmes=942
|
||||
201 committed=34acd633c3136235 kept=true fourWeeks=4149eaa0e26e856b programmes=945
|
||||
202 committed=9e8f22bca9934da3 kept=true fourWeeks=c01cb292dd50c37b programmes=1077
|
||||
203 committed=aa5ac90cbfbcefed kept=true fourWeeks=48f0b555a13a3877 programmes=1126
|
||||
204 committed=1eb08bd1eea4dc27 kept=true fourWeeks=36e7d32d6fb69942 programmes=1170
|
||||
301 committed=a366040ccc54b12f kept=true fourWeeks=12c5b036edae175e programmes=356
|
||||
302 committed=9369125185fab4ee kept=true fourWeeks=0ebddde50c9a0d2c programmes=437
|
||||
303 committed=b6c2d88f2604a452 kept=true fourWeeks=366e574763b92fb8 programmes=416
|
||||
304 committed=b70f04c56326e54f kept=true fourWeeks=78b73765fc5ce5f4 programmes=491
|
||||
305 committed=43eb0b69d237ab50 kept=true fourWeeks=0e3ecca6fdb30bf6 programmes=466
|
||||
306 committed=cbc6ae14f4c14d65 kept=true fourWeeks=5b351d7577fc61f8 programmes=483
|
||||
307 committed=f823275ad86da4ce kept=true fourWeeks=1ec9cc79f5ac16d1 programmes=433
|
||||
308 committed=0eeae8fbb0089be5 kept=true fourWeeks=737bc88204988895 programmes=507
|
||||
309 committed=ffda2938276695fe kept=true fourWeeks=eb95121ca85adbe2 programmes=490
|
||||
401 committed=39ee211c00f3a145 kept=true fourWeeks=1614f476babcf3c1 programmes=872
|
||||
601 committed=67bd343aeea9b2b0 kept=true fourWeeks=0832e576914da5ff programmes=2130
|
||||
602 committed=0ecddbb6610450c9 kept=true fourWeeks=cd809c919d470daa programmes=2275
|
||||
603 committed=25dbd63f8491396f kept=true fourWeeks=0ab476ba34eedbc5 programmes=2264
|
||||
604 committed=548e765ce48965ab kept=true fourWeeks=dffcb862ff82bfb6 programmes=2903
|
||||
605 committed=5ca17ce6d03a6a9c kept=true fourWeeks=faba8c949f38b864 programmes=4286
|
||||
611 committed=f6b86c8a984bbcec kept=true fourWeeks=21d88866596d5161 programmes=2950
|
||||
612 committed=abc6bb844d11b367 kept=true fourWeeks=3ccdbd30f5827932 programmes=569
|
||||
613 committed=a8a89df382ac4b33 kept=true fourWeeks=26ac416ffee96753 programmes=514
|
||||
614 committed=10ab3c9c03ae82fa kept=true fourWeeks=477e941c7d3a939a programmes=3881
|
||||
|
||||
## 0.99.0
|
||||
101 committed=e2a56999e8a008ea kept=true fourWeeks=3de1a3331b6a294b programmes=2129
|
||||
102 committed=06fdb544423630d5 kept=true fourWeeks=c144df512c1e2b22 programmes=1285
|
||||
103 committed=17078bdc852aefc4 kept=true fourWeeks=c85d48a217a10c94 programmes=1797
|
||||
104 committed=811d1bee8e3abe5e kept=true fourWeeks=a2236f9d16315f19 programmes=1706
|
||||
105 committed=d8131ecf0e387195 kept=true fourWeeks=ffe3db054189fe0a programmes=2439
|
||||
106 committed=c6e05fe7b6b8119e kept=true fourWeeks=26f095b2150baf74 programmes=1158
|
||||
107 committed=9d18785a275d37ad kept=true fourWeeks=98d3ec7d2cc2452e programmes=942
|
||||
201 committed=34acd633c3136235 kept=true fourWeeks=4149eaa0e26e856b programmes=945
|
||||
202 committed=9e8f22bca9934da3 kept=true fourWeeks=c01cb292dd50c37b programmes=1077
|
||||
203 committed=aa5ac90cbfbcefed kept=true fourWeeks=48f0b555a13a3877 programmes=1126
|
||||
204 committed=1eb08bd1eea4dc27 kept=true fourWeeks=36e7d32d6fb69942 programmes=1170
|
||||
301 committed=a366040ccc54b12f kept=true fourWeeks=12c5b036edae175e programmes=356
|
||||
302 committed=9369125185fab4ee kept=true fourWeeks=0ebddde50c9a0d2c programmes=437
|
||||
303 committed=b6c2d88f2604a452 kept=true fourWeeks=366e574763b92fb8 programmes=416
|
||||
304 committed=b70f04c56326e54f kept=true fourWeeks=78b73765fc5ce5f4 programmes=491
|
||||
305 committed=43eb0b69d237ab50 kept=true fourWeeks=0e3ecca6fdb30bf6 programmes=466
|
||||
306 committed=cbc6ae14f4c14d65 kept=true fourWeeks=5b351d7577fc61f8 programmes=483
|
||||
307 committed=f823275ad86da4ce kept=true fourWeeks=1ec9cc79f5ac16d1 programmes=433
|
||||
308 committed=0eeae8fbb0089be5 kept=true fourWeeks=737bc88204988895 programmes=507
|
||||
309 committed=ffda2938276695fe kept=true fourWeeks=eb95121ca85adbe2 programmes=490
|
||||
401 committed=39ee211c00f3a145 kept=true fourWeeks=d84e4c50005d367d programmes=873
|
||||
601 committed=67bd343aeea9b2b0 kept=true fourWeeks=0832e576914da5ff programmes=2130
|
||||
602 committed=0ecddbb6610450c9 kept=true fourWeeks=cd809c919d470daa programmes=2275
|
||||
603 committed=25dbd63f8491396f kept=true fourWeeks=0ab476ba34eedbc5 programmes=2264
|
||||
604 committed=548e765ce48965ab kept=true fourWeeks=dffcb862ff82bfb6 programmes=2903
|
||||
605 committed=5ca17ce6d03a6a9c kept=true fourWeeks=faba8c949f38b864 programmes=4286
|
||||
611 committed=f6b86c8a984bbcec kept=true fourWeeks=21d88866596d5161 programmes=2950
|
||||
612 committed=abc6bb844d11b367 kept=true fourWeeks=3ccdbd30f5827932 programmes=569
|
||||
613 committed=a8a89df382ac4b33 kept=true fourWeeks=26ac416ffee96753 programmes=514
|
||||
614 committed=10ab3c9c03ae82fa kept=true fourWeeks=477e941c7d3a939a programmes=3881
|
||||
|
||||
## Differences
|
||||
21c21
|
||||
< 401 committed=39ee211c00f3a145 kept=true fourWeeks=1614f476babcf3c1 programmes=872
|
||||
---
|
||||
> 401 committed=39ee211c00f3a145 kept=true fourWeeks=d84e4c50005d367d programmes=873
|
||||
Reference in New Issue
Block a user