diff --git a/.gitignore b/.gitignore
index 29395df49..854dc14bc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,7 +37,6 @@ npm-debug.log
/priv/local.json
/priv/local_pending.json
/priv/signs_ui_config.json
-/priv/triptych_player_to_screen_id.json
# local environment variables
/priv/local.env
diff --git a/README.md b/README.md
index 494c3b741..619808a92 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,6 @@ Some examples of the various client apps, as of January 2023:
| [Multimodal LCD][solari sample] | used at high-traffic transfer stations served by many routes/modes |
| [Pre-fare duo LCD][pre_fare sample] | posted outside of fare gates at rapid transit stations; content is split across two portrait-oriented 1080p physical displays |
| ["Digital Urban Panel" LCD][dup sample] | content appears in rotation with ads on screens posted outside rapid transit station entrances |
-| Triptych trio LCD | (:construction: WIP!) posted across the tracks from platforms at major stations; content is split across three portrait-oriented 1080p physical displays and appears in rotation with ads |
and more to come!
@@ -28,11 +27,11 @@ On almost all of our screen types, we use a common "framework" to fet
Check out [ARCHITECTURE.md](/ARCHITECTURE.md) for an overview of the application architecture, as well as links to further more detailed documentation.
-## Packaging the DUP and Triptych apps
+## Packaging the DUP app
-The DUP and Triptych screens require the client app to be packaged into a single HTML file rather than dynamically served from our Phoenix server.
+The DUP screens require the client app to be packaged into a single HTML file rather than dynamically served from our Phoenix server.
-You can find instructions on the DUP packaging process [here](assets/src/components/v2/dup/README.md), the triptych packaging process [here](assets/src/components/v2/triptych/README.md).
+You can find instructions on the DUP packaging process [here](assets/src/components/v2/dup/README.md).
## Version upgrade guide
diff --git a/assets/css/triptych_v2.scss b/assets/css/triptych_v2.scss
deleted file mode 100644
index e427bdf21..000000000
--- a/assets/css/triptych_v2.scss
+++ /dev/null
@@ -1,69 +0,0 @@
-@import "colors";
-@import "fonts/inter_font_face";
-@import "fonts/helvetica_font_face";
-@import "v2/common/widget";
-
-@mixin font--heading-3 {
- font-size: 158px;
- font-weight: 700;
- line-height: 158px;
-}
-
-@mixin font--subtitle {
- font-size: 144px;
- font-weight: 700;
- line-height: 144px;
-}
-
-@mixin font--body-1 {
- font-size: 96px;
- font-weight: 600;
- line-height: 118px;
-}
-
-@mixin font--body-2 {
- font-size: 96px;
- font-weight: 400;
- line-height: 118px;
-}
-
-@mixin font--caption-2 {
- font-size: 32px;
- font-weight: 600;
- line-height: 40px;
-}
-
-@mixin font--caption-3 {
- font-size: 32px;
- font-weight: 700;
- line-height: 40px;
-}
-
-// Top level stuff
-@import "v2/triptych/screen_container";
-@import "v2/triptych/viewport";
-
-// Layout/slot elements
-@import "v2/triptych/screen/full_screen";
-
-// No-data states
-@import "v2/lcd_common/page_load_no_data";
-@import "v2/lcd_common/no_data";
-@import "v2/triptych/no_data";
-
-// Widgets
-@import "v2/train_crowding";
-@import "v2/placeholder";
-
-// Debug overlay for test packages
-@import "v2/outfront_common/debug";
-@import "v2/triptych/debug";
-
-@import "v2/triptych/evergreen";
-@import "v2/simulation_common";
-@import "v2/triptych/simulation";
-
-body {
- margin: 0;
- font-family: Inter, sans-serif;
-}
diff --git a/assets/css/v2/train_crowding.scss b/assets/css/v2/train_crowding.scss
deleted file mode 100644
index 2aed9fac4..000000000
--- a/assets/css/v2/train_crowding.scss
+++ /dev/null
@@ -1,160 +0,0 @@
-.crowding-widget {
- &__header {
- box-sizing: border-box;
- display: flex;
- flex-direction: column;
- height: 578px;
- padding: 72px;
- color: #e5e4e1;
- background-color: #171f26;
- }
-
- &__body {
- position: relative;
- display: flex;
- flex-direction: column;
- height: 920px;
- background-color: #d9d6d0;
- box-shadow: 0 8px 12px 0 rgb(0 0 0 / 32%);
- }
-
- &__footer {
- display: flex;
- height: 422px;
- background-color: #cccbc8;
- }
-}
-
-.crowding-widget__header__top-row {
- display: flex;
-
- .t-logo {
- padding: 4px;
- }
-
- .normal-header-time {
- @include font--body-2;
-
- margin-left: auto;
- }
-}
-
-.crowding-widget__header__destination-sentence {
- @include font--heading-3;
-
- margin-top: auto;
- color: #fff;
-
- .destination {
- padding-left: 109px;
- }
-}
-
-.crowding-widget__footer__segment {
- @include font--body-1;
-
- position: relative;
- display: flex;
- flex: 1 1;
- flex-direction: column;
- justify-content: space-between;
- padding: 71px 72px;
-}
-
-.crowding-widget__footer__key-row {
- @include font--body-2;
-
- display: inline-flex;
- align-items: center;
-
- .key-icon {
- padding-right: 72px;
- }
-}
-
-.crowding-widget__footer__identifiers {
- @include font--caption-2;
-
- position: absolute;
- right: 24px;
- bottom: 18px;
-}
-
-.crowding-widget__train-row {
- display: flex;
- justify-content: space-between;
- padding: 161px 52px 58px;
-}
-
-@keyframes up-arrow {
- 0% {
- transform: translateY(0);
- }
-
- 50% {
- transform: translateY(-20px);
- }
-
- 100% {
- transform: translateY(0);
- }
-}
-
-@keyframes up-left-arrow {
- 0% {
- transform: translateY(0);
- }
-
- 50% {
- transform: translateY(-12px) translateX(-12px);
- }
-
- 100% {
- transform: translateY(0);
- }
-}
-
-@keyframes up-right-arrow {
- 0% {
- transform: translateY(0) rotate(90deg);
- }
-
- 50% {
- transform: translateY(-12px) translateX(12px) rotate(90deg);
- }
-
- 100% {
- transform: translateY(0) rotate(90deg);
- }
-}
-
-.crowding-widget__you-are-here-arrow {
- width: 180px;
- height: 180px;
-
- &--up {
- animation: up-arrow 1.2s infinite ease-in-out;
- }
-
- &--up-left {
- animation: up-left-arrow 1.2s infinite ease-in-out;
- }
-
- &--up-right {
- animation: up-right-arrow 1.2s infinite ease-in-out;
- }
-}
-
-.crowding-widget__you-are-here-text {
- @include font--subtitle;
-
- box-sizing: border-box;
- width: 1080px;
- padding: 0 72px 108px;
- margin-top: auto;
- text-align: left;
-
- &--right-align {
- text-align: right;
- }
-}
diff --git a/assets/css/v2/triptych/debug.scss b/assets/css/v2/triptych/debug.scss
deleted file mode 100644
index ea8b78ea8..000000000
--- a/assets/css/v2/triptych/debug.scss
+++ /dev/null
@@ -1,8 +0,0 @@
-#debug.triptych {
- width: 1080px;
- height: 1920px;
-}
-
-#debug .line {
- width: 540px;
-}
diff --git a/assets/css/v2/triptych/evergreen.scss b/assets/css/v2/triptych/evergreen.scss
deleted file mode 100644
index 20cd4b63b..000000000
--- a/assets/css/v2/triptych/evergreen.scss
+++ /dev/null
@@ -1,22 +0,0 @@
-.left-pane,
-.middle-pane,
-.right-pane {
- .evergreen-content__identifiers {
- position: absolute;
- right: 0;
- bottom: 0;
- padding: 12px 24px 18px;
- color: white;
- text-align: right;
- background-color: rgb(23 31 38 / 70%);
-
- @include font--caption-3;
- }
-}
-
-.evergreen-content-image__image,
-.evergreen-content-video,
-.evergreen-content-video .looping-video {
- width: 1080px;
- height: 1920px;
-}
diff --git a/assets/css/v2/triptych/no_data.scss b/assets/css/v2/triptych/no_data.scss
deleted file mode 100644
index 9086a8a56..000000000
--- a/assets/css/v2/triptych/no_data.scss
+++ /dev/null
@@ -1,11 +0,0 @@
-.no-data-middle {
- position: absolute;
- top: 0;
- left: 1080px;
-}
-
-.no-data-right {
- position: absolute;
- top: 0;
- left: 2160px;
-}
diff --git a/assets/css/v2/triptych/screen/full_screen.scss b/assets/css/v2/triptych/screen/full_screen.scss
deleted file mode 100644
index 3a89d7239..000000000
--- a/assets/css/v2/triptych/screen/full_screen.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-.full-screen {
- position: relative;
- width: 3240px;
- height: 1920px;
- margin-right: auto;
- margin-left: auto;
-}
diff --git a/assets/css/v2/triptych/screen_container.scss b/assets/css/v2/triptych/screen_container.scss
deleted file mode 100644
index 623ca9d9f..000000000
--- a/assets/css/v2/triptych/screen_container.scss
+++ /dev/null
@@ -1,25 +0,0 @@
-.screen-container {
- position: relative;
- width: 3240px;
- height: 1920px;
- margin: 0 auto;
- overflow: hidden;
-}
-
-.left-pane,
-.middle-pane,
-.right-pane {
- position: absolute;
- top: 0;
- width: 1080px;
- height: 1920px;
- overflow: hidden;
-}
-
-.middle-pane {
- left: 1080px;
-}
-
-.right-pane {
- left: 2160px;
-}
diff --git a/assets/css/v2/triptych/simulation.scss b/assets/css/v2/triptych/simulation.scss
deleted file mode 100644
index 6a2a0c747..000000000
--- a/assets/css/v2/triptych/simulation.scss
+++ /dev/null
@@ -1,72 +0,0 @@
-.simulation-screen-scrolling-container {
- display: flex;
- padding-bottom: 20px;
- overflow: auto hidden;
- scrollbar-color: #607180 #2e3f4d;
-
- &::-webkit-scrollbar {
- width: 12px;
- }
-
- &::-webkit-scrollbar-thumb {
- background-color: #607180;
- border: 2px solid #2e3f4d;
- border-radius: 12px;
- }
-
- &::-webkit-scrollbar-track {
- background-color: #2e3f4d;
- border-radius: 12px;
- box-shadow: inset 0 0 6px rgb(0 0 0 / 30%);
- }
-
- .simulation__full-page {
- position: relative;
- z-index: 999;
- display: flex;
- width: 580.5px;
- height: 344px;
- overflow: hidden;
-
- .left-pane,
- .middle-pane,
- .right-pane {
- position: relative;
- left: unset;
- width: 33.33%;
- height: 100%;
- overflow: hidden;
-
- .evergreen-content-image__container,
- .evergreen-content-image__image {
- width: 1080px;
- height: 1920px;
- }
-
- & > * {
- transform: scale(17.92%);
- transform-origin: top left;
- }
-
- .evergreen-content__identifiers {
- transform-origin: bottom right;
- }
- }
- }
-
- .full-screen {
- z-index: 999;
- width: 580.5px;
- height: 344px;
-
- .crowding-widget {
- width: 3240px;
- height: 1920px;
- }
-
- & > * {
- transform: scale(17.92%);
- transform-origin: top left;
- }
- }
-}
diff --git a/assets/css/v2/triptych/viewport.scss b/assets/css/v2/triptych/viewport.scss
deleted file mode 100644
index 1a7042a30..000000000
--- a/assets/css/v2/triptych/viewport.scss
+++ /dev/null
@@ -1,31 +0,0 @@
-.triptych-screen-viewport {
- position: relative;
- width: 1080px;
- height: 1920px;
- margin-right: auto;
- margin-left: auto;
- overflow: hidden;
-
- .triptych-shifter {
- position: absolute;
- width: 3240px;
- height: 1920px;
- overflow: hidden;
- }
-
- .triptych-shifter--left {
- left: 0;
- }
-
- .triptych-shifter--middle {
- left: -1080px;
- }
-
- .triptych-shifter--right {
- right: 0;
- }
-}
-
-.triptych-screen-viewport--all {
- width: 3240px;
-}
diff --git a/assets/src/apps/admin.tsx b/assets/src/apps/admin.tsx
index 6ff08b071..fcfbb3f23 100644
--- a/assets/src/apps/admin.tsx
+++ b/assets/src/apps/admin.tsx
@@ -19,10 +19,8 @@ import {
BusShelterV2ScreensTable,
PreFareV2ScreensTable,
DupV2ScreensTable,
- TriptychV2ScreensTable,
} from "Components/admin/admin_tables";
import AdminScreenConfigForm from "Components/admin/admin_screen_config_form";
-import AdminTriptychPlayerForm from "Components/admin/admin_triptych_player_form";
import ImageManager from "Components/admin/admin_image_manager";
import Devops from "Components/admin/devops";
import Inspector from "Components/admin/inspector";
@@ -37,13 +35,9 @@ const routes: [string, string, ComponentType][][] = [
["gl-eink-v2-screens", "GL E-ink", GLEinkV2ScreensTable],
["pre-fare-v2-screens", "Pre-Fare", PreFareV2ScreensTable],
["busway-v2-screens", "Sectional", BuswayV2ScreensTable],
- ["triptych-v2-screens", "Triptych", TriptychV2ScreensTable],
],
[["solari-screens", "Solari (v1)", SolariScreensTable]],
- [
- ["screens-json-editor", "Config Editor", AdminScreenConfigForm],
- ["triptych-player-json-editor", "Triptych Editor", AdminTriptychPlayerForm],
- ],
+ [["screens-json-editor", "Config Editor", AdminScreenConfigForm]],
[["image-manager", "Image Manager", ImageManager]],
[["devops", "Devops", Devops]],
];
diff --git a/assets/src/apps/v2/triptych.tsx b/assets/src/apps/v2/triptych.tsx
deleted file mode 100644
index 17436bc2e..000000000
--- a/assets/src/apps/v2/triptych.tsx
+++ /dev/null
@@ -1,124 +0,0 @@
-require("../../../css/triptych_v2.scss");
-
-import React from "react";
-import ReactDOM from "react-dom";
-import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
-
-import { usePlayerName } from "Hooks/outfront";
-import { isTriptych } from "Util/outfront";
-
-import { MappingContext } from "Components/v2/widget";
-import {
- ResponseMapper,
- ResponseMapperContext,
-} from "Components/v2/screen_container";
-
-import ScreenPage from "Components/v2/screen_page";
-import MultiScreenPage from "Components/v2/multi_screen_page";
-import SimulationScreenPage from "Components/v2/simulation_screen_page";
-import Viewport from "Components/v2/triptych/viewport";
-
-import FullScreen from "Components/v2/basic_layouts/full_screen";
-import TriptychThreePane from "Components/v2/triptych/triptych_three_pane";
-
-import PageLoadNoData from "Components/v2/triptych/page_load_no_data";
-import NoData from "Components/v2/triptych/no_data";
-
-import Placeholder from "Components/v2/placeholder";
-import TrainCrowding from "Components/v2/train_crowding";
-import OutfrontEvergreenContent from "Components/v2/outfront_evergreen_content";
-
-const TYPE_TO_COMPONENT = {
- // Layouts
- screen_normal: FullScreen,
- screen_split: TriptychThreePane,
- // Components
- page_load_no_data: PageLoadNoData,
- no_data: NoData,
- train_crowding: TrainCrowding,
- evergreen_content: OutfrontEvergreenContent,
- placeholder: Placeholder,
-};
-
-const LOADING_LAYOUT = {
- full_screen: {
- type: "page_load_no_data",
- },
- type: "screen_normal",
-};
-
-const DISABLED_LAYOUT = {
- full_screen: {
- type: "no_data",
- },
- type: "screen_normal",
-};
-
-const FAILURE_LAYOUT = DISABLED_LAYOUT;
-
-const responseMapper: ResponseMapper = (apiResponse) => {
- switch (apiResponse.state) {
- case "success":
- case "simulation_success":
- return apiResponse.data;
- case "disabled":
- return DISABLED_LAYOUT;
- case "failure":
- return FAILURE_LAYOUT;
- case "loading":
- return LOADING_LAYOUT;
- }
-};
-
-const App = (): JSX.Element => {
- if (isTriptych()) {
- const playerName = usePlayerName()!;
-
- return (
-
-
-
-
-
-
-
- );
- }
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-};
-
-ReactDOM.render(, document.getElementById("app"));
diff --git a/assets/src/components/admin/admin_add_modal.tsx b/assets/src/components/admin/admin_add_modal.tsx
index 9117c292e..4fa63bb6a 100644
--- a/assets/src/components/admin/admin_add_modal.tsx
+++ b/assets/src/components/admin/admin_add_modal.tsx
@@ -25,7 +25,6 @@ const fields = [
"solari",
"solari_large",
"solari_large_v2",
- "triptych_v2",
]),
},
{
@@ -90,11 +89,6 @@ const defaultAppParamsByAppId = {
stop_name: "",
},
},
- triptych_v2: {
- header: {
- stop_name: "",
- },
- },
};
const initialFormValues = _.fromPairs(
diff --git a/assets/src/components/admin/admin_tables.tsx b/assets/src/components/admin/admin_tables.tsx
index 5a964229b..00269afff 100644
--- a/assets/src/components/admin/admin_tables.tsx
+++ b/assets/src/components/admin/admin_tables.tsx
@@ -292,31 +292,6 @@ const v2Columns = [
},
];
-const screenIDColumn = {
- Header: "Screen ID",
- accessor: "id",
- Cell: InspectorLink,
- Filter: DefaultColumnFilter,
- FormCell: FormStaticCell,
-};
-
-const screenNameColumn = {
- Header: "Name",
- accessor: "name",
- Cell: EditableCell,
- Filter: DefaultColumnFilter,
- FormCell: FormTextCell,
-};
-
-const evergreenContentColumn = {
- Header: "Evergreen Content",
- accessor: buildAppParamAccessor("evergreen_content"),
- mutator: buildAppParamMutator("evergreen_content"),
- Cell: EditableTextarea,
- disableFilters: true,
- FormCell: FormTextarea,
-};
-
const alertsColumn = {
Header: "Alerts",
accessor: buildAppParamAccessor("alerts"),
@@ -470,33 +445,6 @@ const shuttleBusInfoColumn = {
FormCell: FormTextarea,
};
-const trainCrowdingColumn = {
- Header: "Train Crowding",
- accessor: buildAppParamAccessor("train_crowding"),
- mutator: buildAppParamMutator("train_crowding"),
- Cell: EditableTextarea,
- disableFilters: true,
- FormCell: FormTextarea,
-};
-
-const localEvergreenSetsColumn = {
- Header: "Local Evergreen Content Sets",
- accessor: buildAppParamAccessor("local_evergreen_sets"),
- mutator: buildAppParamMutator("local_evergreen_sets"),
- Cell: EditableTextarea,
- disableFilters: true,
- FormCell: FormTextarea,
-};
-
-const showIdentifiersColumn = {
- Header: "Show Version & Player Name?",
- accessor: buildAppParamAccessor("show_identifiers"),
- mutator: buildAppParamMutator("show_identifiers"),
- Cell: EditableCheckbox,
- Filter: DefaultColumnFilter,
- FormCell: FormBoolean,
-};
-
const PreFareV2ScreensTable = (): JSX.Element => {
const dataFilter = ({ app_id }) => {
return app_id === "pre_fare_v2";
@@ -561,26 +509,6 @@ const BuswayV2ScreensTable = (): JSX.Element => {
return ;
};
-const TriptychV2ScreensTable = (): JSX.Element => {
- const dataFilter = ({ app_id }) => {
- return app_id === "triptych_v2";
- };
-
- return (
-
- );
-};
-
export {
AllScreensTable,
BusEinkV2ScreensTable,
@@ -590,5 +518,4 @@ export {
GLEinkV2ScreensTable,
PreFareV2ScreensTable,
SolariScreensTable,
- TriptychV2ScreensTable,
};
diff --git a/assets/src/components/admin/admin_triptych_player_form.tsx b/assets/src/components/admin/admin_triptych_player_form.tsx
deleted file mode 100644
index a6b562ac7..000000000
--- a/assets/src/components/admin/admin_triptych_player_form.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-import React from "react";
-import _ from "lodash";
-
-import AdminForm from "Components/admin/admin_form";
-
-const fetchConfig = async () => {
- const result = await fetch("/api/admin/triptych_players");
- const resultJson = await result.json();
-
- // Sort the entries alphanumerically by player name.
- return _.chain(JSON.parse(resultJson.config))
- .toPairs()
- .sortBy(([playerName, _screenId]) => playerName)
- .fromPairs()
- .value();
-};
-
-const AdminTriptychPlayerForm = (): JSX.Element => (
-
-);
-
-export default AdminTriptychPlayerForm;
diff --git a/assets/src/components/dup/README.md b/assets/src/components/dup/README.md
index d93c219b8..f0dc996e9 100644
--- a/assets/src/components/dup/README.md
+++ b/assets/src/components/dup/README.md
@@ -1,7 +1,7 @@
# DUP app packaging
- Ensure [Corsica](https://hexdocs.pm/corsica/Corsica.html) is used on the server to allow CORS requests (ideally limited to just the DUP-relevant routes). It should already be configured at [this line](/lib/screens_web/controllers/screen_api_controller.ex#L7) in the API controller--if it is, you don't need to do anything for this step.
-- Double check that any behavior specific to the DUP screen environment happens inside of an `isOFM()` check. This includes:
+- Double check that any behavior specific to the DUP screen environment happens inside of an `isDup()` check. This includes:
- `buildApiPath` in use_api_response.tsx should return a full URL for the API path: prefix `apiPath` string with "https://screens.mbta.com".
- `App` component in dup.tsx should just return ``.
- `imagePath` in util.tsx should return relative paths (no leading `/`).
diff --git a/assets/src/components/v2/dup/README.md b/assets/src/components/v2/dup/README.md
index 61a4f9639..765f1a09c 100644
--- a/assets/src/components/v2/dup/README.md
+++ b/assets/src/components/v2/dup/README.md
@@ -1,7 +1,7 @@
# DUP app packaging v2
- Ensure [Corsica](https://hexdocs.pm/corsica/Corsica.html) is used on the server to allow CORS requests (ideally limited to just the DUP-relevant routes). It should already be configured at [this line](/lib/screens_web/controllers/v2/screen_api_controller.ex#L9) in the API controller--if it is, you don't need to do anything for this step.
-- Double check that any behavior specific to the DUP screen environment happens inside of an `isDup()` or `isOFM()` check. This includes:
+- Double check that any behavior specific to the DUP screen environment happens inside of an `isDup()` check. This includes:
- `buildApiPath` in use_api_response.tsx should return a full URL for the API path: prefix `apiPath` string with "https://screens.mbta.com".
- `imagePath` in util.tsx should return relative paths (no leading `/`).
- Create priv/static/dup-app.html if it doesnโt already exist. Copy paste the following contents in:
diff --git a/assets/src/components/v2/outfront_evergreen_content.tsx b/assets/src/components/v2/outfront_evergreen_content.tsx
deleted file mode 100644
index aaa8ea835..000000000
--- a/assets/src/components/v2/outfront_evergreen_content.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import React, { ComponentType } from "react";
-
-import EvergreenContent from "./evergreen_content";
-import useIsOnScreen from "Hooks/v2/use_is_on_screen";
-import { imagePath } from "Util/util";
-import { TRIPTYCH_VERSION } from "./triptych/version";
-import { usePlayerName } from "Hooks/outfront";
-import { isOFM } from "Util/outfront";
-
-if (isOFM()) {
- require.context("Images/triptych_psas", true, /\.webp$/);
-}
-
-const OutfrontEvergreenContent: ComponentType<{
- asset_url: string;
- show_identifiers: boolean;
-}> = ({ asset_url: assetUrl, show_identifiers: showIdentifiers }) => {
- const dupReadyUrl = imagePath(assetUrl);
- const isPlaying = useIsOnScreen();
- const playerName = usePlayerName();
- const identifiers = `${TRIPTYCH_VERSION} ${playerName ? playerName : ""}`;
- return (
- <>
-
- {showIdentifiers && (
-
{identifiers}
- )}
- >
- );
-};
-
-export default OutfrontEvergreenContent;
diff --git a/assets/src/components/v2/screen_container.tsx b/assets/src/components/v2/screen_container.tsx
index 736968833..9c084bf15 100644
--- a/assets/src/components/v2/screen_container.tsx
+++ b/assets/src/components/v2/screen_container.tsx
@@ -10,12 +10,11 @@ import useApiResponse, {
ApiResponse,
SimulationData,
useDUPApiResponse,
- useTriptychApiResponse,
} from "Hooks/v2/use_api_response";
import WidgetTreeErrorBoundary from "Components/v2/widget_tree_error_boundary";
import Widget, { WidgetData } from "Components/v2/widget";
import useAudioReadout from "Hooks/v2/use_audio_readout";
-import { isDup, isOFM, isTriptych } from "Util/outfront";
+import { isDup } from "Util/outfront";
type ResponseMapper = (apiResponse: ApiResponse) => WidgetData | SimulationData;
@@ -92,7 +91,7 @@ const ScreenLayout: ComponentType = ({
showBlink,
}) => {
const responseMapper = useContext(ResponseMapperContext);
- const ErrorBoundaryOrFragment = isOFM() ? Fragment : WidgetTreeErrorBoundary;
+ const ErrorBoundaryOrFragment = isDup() ? Fragment : WidgetTreeErrorBoundary;
// We know this can only be `WidgetData` and not `SimulationData` here because
// `ScreenPage` is only used in contexts where a "non-simulation" API response
@@ -114,8 +113,6 @@ const ScreenLayout: ComponentType = ({
const getApiResponseHook = () => {
if (isDup()) {
return useDUPApiResponse;
- } else if (isTriptych()) {
- return useTriptychApiResponse;
} else {
return useApiResponse;
}
diff --git a/assets/src/components/v2/train_crowding.tsx b/assets/src/components/v2/train_crowding.tsx
deleted file mode 100644
index a9ea694e2..000000000
--- a/assets/src/components/v2/train_crowding.tsx
+++ /dev/null
@@ -1,261 +0,0 @@
-import React from "react";
-
-import { classWithModifier } from "Util/util";
-import { NormalHeaderTime } from "./normal_header";
-import { usePlayerName } from "Hooks/outfront";
-import { TRIPTYCH_VERSION } from "./triptych/version";
-
-import Logo from "Images/svgr_bundled/logo.svg";
-import ArrowUp from "Images/svgr_bundled/Arrow-90.svg";
-import ArrowUpLeft from "Images/svgr_bundled/Arrow-45.svg";
-
-import KeyNotCrowded from "Images/svgr_bundled/train_crowding/Car-NotCrowded-Key.svg";
-import KeySomeCrowding from "Images/svgr_bundled/train_crowding/Car-SomeCrowding-Key.svg";
-import KeyCrowded from "Images/svgr_bundled/train_crowding/Car-Crowded-Key.svg";
-import KeyNoData from "Images/svgr_bundled/train_crowding/Car-NoData-Key.svg";
-import KeyClosed from "Images/svgr_bundled/train_crowding/Car-Closed-Key.svg";
-
-import CarNotCrowdedLeft from "Images/svgr_bundled/train_crowding/Car-NotCrowded-Left.svg";
-import CarSomeCrowdingLeft from "Images/svgr_bundled/train_crowding/Car-SomeCrowding-Left.svg";
-import CarCrowdedLeft from "Images/svgr_bundled/train_crowding/Car-Crowded-Left.svg";
-import CarNoDataLeft from "Images/svgr_bundled/train_crowding/Car-NoData-Left.svg";
-import CarClosedLeft from "Images/svgr_bundled/train_crowding/Car-Closed-Left.svg";
-
-import CarNotCrowdedMiddle from "Images/svgr_bundled/train_crowding/Car-NotCrowded-Middle.svg";
-import CarSomeCrowdingMiddle from "Images/svgr_bundled/train_crowding/Car-SomeCrowding-Middle.svg";
-import CarCrowdedMiddle from "Images/svgr_bundled/train_crowding/Car-Crowded-Middle.svg";
-import CarNoDataMiddle from "Images/svgr_bundled/train_crowding/Car-NoData-Middle.svg";
-import CarClosedMiddle from "Images/svgr_bundled/train_crowding/Car-Closed-Middle.svg";
-
-import CarNotCrowdedRight from "Images/svgr_bundled/train_crowding/Car-NotCrowded-Right.svg";
-import CarSomeCrowdingRight from "Images/svgr_bundled/train_crowding/Car-SomeCrowding-Right.svg";
-import CarCrowdedRight from "Images/svgr_bundled/train_crowding/Car-Crowded-Right.svg";
-import CarNoDataRight from "Images/svgr_bundled/train_crowding/Car-NoData-Right.svg";
-import CarClosedRight from "Images/svgr_bundled/train_crowding/Car-Closed-Right.svg";
-
-type FrontCarDirection = "left" | "right";
-type OccupancyStatus =
- | "no_data"
- | "not_crowded"
- | "some_crowding"
- | "crowded"
- | "closed";
-
-type CarOrientation = FrontCarDirection | "middle";
-const lookupCarComponent = (
- occupancyStatus: OccupancyStatus,
- carOrientation: CarOrientation,
-) => {
- const lookupKey: `${CarOrientation}/${OccupancyStatus}` = `${carOrientation}/${occupancyStatus}`;
-
- switch (lookupKey) {
- case "left/not_crowded":
- return CarNotCrowdedLeft;
- case "left/some_crowding":
- return CarSomeCrowdingLeft;
- case "left/crowded":
- return CarCrowdedLeft;
- case "left/no_data":
- return CarNoDataLeft;
- case "left/closed":
- return CarClosedLeft;
-
- case "right/not_crowded":
- return CarNotCrowdedRight;
- case "right/some_crowding":
- return CarSomeCrowdingRight;
- case "right/crowded":
- return CarCrowdedRight;
- case "right/no_data":
- return CarNoDataRight;
- case "right/closed":
- return CarClosedRight;
-
- case "middle/not_crowded":
- return CarNotCrowdedMiddle;
- case "middle/some_crowding":
- return CarSomeCrowdingMiddle;
- case "middle/crowded":
- return CarCrowdedMiddle;
- case "middle/no_data":
- return CarNoDataMiddle;
- case "middle/closed":
- return CarClosedMiddle;
- }
-};
-
-interface FooterSegmentProps {
- children: React.ReactNode;
- identifiers: string;
- showIdentifiers: boolean;
-}
-
-// Wrapper for footer segments so there is less code duplication when adding identifiers
-const FooterSegment: React.ComponentType = ({
- children,
- identifiers,
- showIdentifiers,
-}) => {
- return (
-
- {children}
- {showIdentifiers && (
-
- {identifiers}
-
- )}
-
- );
-};
-
-interface Props {
- arrivalTime: string;
- crowding: OccupancyStatus[];
- destination: string;
- front_car_direction: FrontCarDirection;
- now: string;
- platform_position: number;
- show_identifiers: boolean;
-}
-
-const TrainCrowding: React.ComponentType = ({
- crowding,
- destination,
- platform_position: platformPosition,
- front_car_direction: frontCarDirection,
- now,
- show_identifiers: showIdentifiers,
-}) => {
- // If the front car direction is right, the crowding array needs to be reversed
- // so the last car is rendered on the left.
- const trains = crowding.map((occupancyStatus, i) => {
- const CarComponent = lookupCarComponent(
- occupancyStatus,
- i == 0 ? frontCarDirection : "middle",
- );
- return ;
- });
-
- const trainSequence =
- frontCarDirection == "left" ? trains : [...trains].reverse();
-
- // If arrow is between screens, scoot the arrow to the next slot on the right
- // If arrow is beyond the end of the train (slot 25), scoot arrow left
- let arrowSlot;
- if ([1, 9, 17].includes(platformPosition)) {
- arrowSlot = platformPosition + 1;
- } else {
- if (platformPosition == 25) {
- arrowSlot = platformPosition - 1;
- } else arrowSlot = platformPosition;
- }
-
- // The slot arrangement exceeds the edges of the screen, so to properly set the slot positions
- // we need to make a few adjustments.
- const screenWidth = 3240;
- const slotOverhang = 35;
- const slotsWidth = screenWidth + slotOverhang * 2;
- const extraArrowPadding = 24;
- const arrowLeftPadding =
- (arrowSlot - 1) * (slotsWidth / 25) - slotOverhang - extraArrowPadding;
- const arrowDirection = [1, 9, 17].includes(platformPosition)
- ? "up-left"
- : platformPosition == 25
- ? "up-right"
- : "up";
-
- const textPane = Math.floor((arrowSlot / 25) * 3);
- const textPadding = (textPane * 3240) / 3;
-
- const playerName = usePlayerName();
- const identifiers = `${TRIPTYCH_VERSION} ${playerName ? playerName : ""}`;
-
- return (
-
-
-
-
- {now && }
-
-
- Next train to{destination}
-
-
-
-
{trainSequence}
-
- {arrowDirection == "up" ? (
-
- ) : (
-
- )}
-
-
- You are here
-
-
-
-
- Current crowding on board
-
-
-
- {" "}
- Seats available
-
-
- {" "}
- Some crowding
-
-
-
-
- Crowded
-
-
- {crowding.includes("closed") ? (
- <>
- Car
- closed
- >
- ) : (
- crowding.includes("no_data") && (
- <>
- No
- data
- >
- )
- )}
-
-
-
-
- );
-};
-
-export default TrainCrowding;
diff --git a/assets/src/components/v2/triptych/README.md b/assets/src/components/v2/triptych/README.md
deleted file mode 100644
index 64e678b63..000000000
--- a/assets/src/components/v2/triptych/README.md
+++ /dev/null
@@ -1,128 +0,0 @@
-# Triptych app packaging
-
-## Resizing the PSAs
-
-Outfront recommends these asset sizes:
-
-- Images: The boards can take webp, which saves 35% or possibly more. OFM
- recommends using `sharp`, but you can also use
- [webp](https://formulae.brew.sh/formula/webp). `cwebp -resize 1080 0 left.png -o left.webp` will resize left.png to the triptych screen size and convert to
- webp.
-- Videos: Use handbrake video transcoder to reduce size to below 10MB, at least.
- (Perhaps much smaller.) To do so, get [HandBrake](https://handbrake.fr/), load
- the source file, and simply hit "Start". It compresses the file. Check the
- output to make sure it still looks good.
-
-## Prepping the package
-
-- Ensure [Corsica](https://hexdocs.pm/corsica/Corsica.html) is used on the
- server to allow CORS requests (ideally limited to just the triptych-relevant
- routes). It should already be configured at [this
- line](/lib/screens_web/controllers/v2/screen_api_controller.ex#L9) in the API
- controller--if it is, you don't need to do anything for this step.
-- Double check that any behavior specific to the triptych screen environment
- happens inside of an `isTriptych()` or `isOFM()` check. This includes:
-
- - `buildApiPath` in use_api_response.tsx should return a full URL for the API
- path: prefix `apiPath` string with "https://screens.mbta.com".
- - `imagePath` in util.tsx should return relative paths (no leading `/`).
-
-- Set the version string in assets/src/components/v2/triptych/version.tsx to
- `current_year.current_month.current_day.1`.
-- If you've renamed / removed image assets, you might want to delete the
- corresponding folder in `/priv/static`. The folder accumulates assets without
- clearing old ones out, and these will be included in the built bundle!
-- **Only if you are packaging for local testing**
- - add the following to the top of assets/src/apps/v2/triptych.tsx, filling in
- the string values:
- ```ts
- import { __TEST_setFakeMRAID__ } from "Util/outfront";
- __TEST_setFakeMRAID__({
- playerName: "",
- station: "",
- triptychPane: "",
- });
- ```
- This sets up a fake MRAID object that emulates the real one available to the
- client when running on Outfront screens. The MRAID object gives our client
- info about which screen it's running on.
- - replace the definition of `OUTFRONT_BASE_URI` in
- `assets/src/hooks/v2/use_api_response.tsx` with `"http://localhost:4000"`.
- - make sure priv/triptych_player_to_screen_id.json mirrors
- mbta-ctd-config/screens/triptych_player_to_screen_id-prod.json, or at least
- contains a mapping for the `playerName` that you hardcoded two steps ago.
-- `cd` to priv/static and run the following:
- ```sh
- npm --prefix ../../assets run deploy && \
- cp -r css/packaged_triptych_v2.css js/packaged_triptych_polyfills.js js/packaged_triptych_v2.js js/packaged_triptych_v2.js.map ../triptych_preview.png ../triptych-app.html . && \
- cp -r js/triptych_images . && \
- cp ../triptych_template.json ./template.json && \
- zip -r triptych-app.zip packaged_triptych_v2.css packaged_triptych_polyfills.js packaged_triptych_v2.js packaged_triptych_v2.js.map fonts triptych_images triptych-app.html template.json triptych_preview.png
- ```
-- On completion, the packaged client app will be saved at
- `priv/static/triptych-app.zip`.
-- Commit the version bump on a branch, push it, and create a PR to mark the
- deploy.
-
-## Working with Outfront
-
-Once you've created the client app package, you'll need to send it to Outfront
-for them to test and deploy it.
-
-Ask a Screens team member for the email of our contact at Outfront. In your
-message, be sure to specify:
-
-- a player name (or "Liveboard name"), and
-- a triptych pane (or `Array_configuration`--value should be of the form
- "Triple\_(Left|Middle|Right)")
-
-## Debugging
-
-To assist with debugging on the triptych screens, you can paste this at the
-module scope in triptych.tsx to have console logs show up on the screen:
-
-```js
-const Counter = (() => {
- let n = 0;
-
- return {
- next() {
- let cur = n;
- n = (n + 1) % 100;
- return `${cur.toString().padStart(2, "0")}`;
- },
- };
-})();
-
-const dEl = document.createElement("div");
-dEl.id = "debug";
-dEl.className = "triptych";
-document.body.appendChild(dEl);
-// save the original console.log function
-const old_logger = console.log;
-// grab html element for adding console.log output
-const html_logger = document.getElementById("debug");
-// replace console.log function with our own function
-console.log = function (...msgs) {
- // first call old logger for console output
- old_logger.call(this, arguments);
-
- // convert object args to strings and join them together
- const text = msgs
- .map((msg) => {
- if (typeof msg == "object") {
- return JSON && JSON.stringify ? JSON.stringify(msg) : msg;
- } else {
- return msg;
- }
- })
- .join(" ");
-
- // add the log to the html element.
- html_logger.innerHTML = `${Counter.next()} ${text}
${
- html_logger.innerHTML
- }`;
-};
-
-console.log("On-screen logger initialized");
-```
diff --git a/assets/src/components/v2/triptych/no_data.tsx b/assets/src/components/v2/triptych/no_data.tsx
deleted file mode 100644
index 63705602a..000000000
--- a/assets/src/components/v2/triptych/no_data.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import React, { ComponentType } from "react";
-import noDataPNG from "Images/no-data-triptych.png";
-
-interface Props {
- show_alternatives: boolean;
-}
-
-const NoData: ComponentType = () => {
- return (
- <>
-
-
-
-
-
-
-
-
-
- >
- );
-};
-
-export default NoData;
diff --git a/assets/src/components/v2/triptych/page_load_no_data.tsx b/assets/src/components/v2/triptych/page_load_no_data.tsx
deleted file mode 100644
index bda2264bd..000000000
--- a/assets/src/components/v2/triptych/page_load_no_data.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import React, { ComponentType } from "react";
-import loadingPNG from "Images/loading-triptych.png";
-
-const PageLoadNoData: ComponentType = () => {
- return (
- <>
-
-
-
-
-
-
-
-
-
- >
- );
-};
-
-export default PageLoadNoData;
diff --git a/assets/src/components/v2/triptych/triptych_three_pane.tsx b/assets/src/components/v2/triptych/triptych_three_pane.tsx
deleted file mode 100644
index 3c15d9cf9..000000000
--- a/assets/src/components/v2/triptych/triptych_three_pane.tsx
+++ /dev/null
@@ -1,37 +0,0 @@
-import React from "react";
-
-import Widget, { WidgetData } from "Components/v2/widget";
-import { TriptychPane, getTriptychPane } from "Util/outfront";
-
-interface Props {
- left_pane: WidgetData;
- middle_pane: WidgetData;
- right_pane: WidgetData;
-}
-
-const isInViewport = (pane: TriptychPane | null, slotPosition: TriptychPane) =>
- pane == null || pane == slotPosition;
-
-const TriptychThreePane: React.ComponentType = ({
- left_pane: leftPane,
- middle_pane: middlePane,
- right_pane: rightPane,
-}) => {
- const pane = getTriptychPane();
-
- return (
- <>
-
- {isInViewport(pane, "left") && }
-
-
- {isInViewport(pane, "middle") && }
-
-
- {isInViewport(pane, "right") && }
-
- >
- );
-};
-
-export default TriptychThreePane;
diff --git a/assets/src/components/v2/triptych/version.tsx b/assets/src/components/v2/triptych/version.tsx
deleted file mode 100644
index bef9d8f69..000000000
--- a/assets/src/components/v2/triptych/version.tsx
+++ /dev/null
@@ -1 +0,0 @@
-export const TRIPTYCH_VERSION = "24.5.8.1";
diff --git a/assets/src/components/v2/triptych/viewport.tsx b/assets/src/components/v2/triptych/viewport.tsx
deleted file mode 100644
index 7ee1c26c1..000000000
--- a/assets/src/components/v2/triptych/viewport.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import React from "react";
-
-import { getTriptychPane } from "Util/outfront";
-
-/**
- * Shifts one of the three triptych panes into view
- * based on a `data-triptych-pane` data attribute on the #app div.
- * If the param is missing, this will show the full
- * screen content (3240px x 1920px).
- */
-const Viewport: React.ComponentType = ({ children }) => {
- let viewportClassName = "triptych-screen-viewport";
- let shifterClassName = "triptych-shifter";
-
- const pane = getTriptychPane();
- if (pane != null) {
- shifterClassName += ` triptych-shifter--${pane}`;
- } else {
- viewportClassName += " triptych-screen-viewport--all";
- }
-
- return (
-
- );
-};
-
-export default Viewport;
diff --git a/assets/src/hooks/outfront.tsx b/assets/src/hooks/outfront.tsx
index 710de4255..864f72cff 100644
--- a/assets/src/hooks/outfront.tsx
+++ b/assets/src/hooks/outfront.tsx
@@ -1,11 +1,5 @@
import { useMemo } from "react";
-import {
- getMRAID,
- getPlayerName,
- getStationName,
- getTriptychPane,
-} from "Util/outfront";
-import type { TriptychPane } from "Util/outfront";
+import { getMRAID, getPlayerName, getStationName } from "Util/outfront";
/**
* Returns the player name, or null if we fail to determine it for any reason.
@@ -13,12 +7,6 @@ import type { TriptychPane } from "Util/outfront";
export const usePlayerName = (): string | null =>
useMemo(getPlayerName, [getMRAID()]);
-/**
- * Returns the triptych pane, or null if we fail to determine it for any reason.
- */
-export const useTriptychPane = (): TriptychPane | null =>
- useMemo(getTriptychPane, [getMRAID()]);
-
/**
* Returns the station name, or null if we fail to determine it for any reason.
*/
diff --git a/assets/src/hooks/use_api_response.tsx b/assets/src/hooks/use_api_response.tsx
index 12bfafbfc..9836a2245 100644
--- a/assets/src/hooks/use_api_response.tsx
+++ b/assets/src/hooks/use_api_response.tsx
@@ -1,9 +1,9 @@
import { useEffect, useState } from "react";
-import { isOFM } from "Util/outfront";
import { isRealScreen } from "Util/util";
import useInterval from "Hooks/use_interval";
import { getDatasetValue } from "Util/dataset";
import * as SentryLogger from "Util/sentry";
+import { isDup } from "Util/outfront";
const MINUTE_IN_MS = 60_000;
@@ -43,7 +43,7 @@ const useIsRealScreenParam = () => {
};
const useRequestorParam = () => {
- if (isOFM()) return `&requestor=real_screen`;
+ if (isDup()) return `&requestor=real_screen`;
let requestor = getDatasetValue("requestor");
if (!requestor && isRealScreen()) {
@@ -164,7 +164,7 @@ const buildApiPath = ({
apiPath += `&datetime=${datetime}`;
}
- if (isOFM()) {
+ if (isDup()) {
apiPath = "https://screens.mbta.com" + apiPath;
}
diff --git a/assets/src/hooks/v2/use_api_response.tsx b/assets/src/hooks/v2/use_api_response.tsx
index 21e15dc5d..c3df7a13d 100644
--- a/assets/src/hooks/v2/use_api_response.tsx
+++ b/assets/src/hooks/v2/use_api_response.tsx
@@ -3,12 +3,11 @@ import useDriftlessInterval from "Hooks/use_driftless_interval";
import React, { useEffect, useMemo, useState } from "react";
import { getDatasetValue } from "Util/dataset";
import { sendToInspector, useReceiveFromInspector } from "Util/inspector";
-import { isDup, isOFM, isTriptych, getTriptychPane } from "Util/outfront";
+import { isDup } from "Util/outfront";
import { getScreenSide, isRealScreen } from "Util/util";
import * as SentryLogger from "Util/sentry";
import { ROTATION_INDEX } from "Components/v2/dup/rotation_index";
import { DUP_VERSION } from "Components/v2/dup/version";
-import { TRIPTYCH_VERSION } from "Components/v2/triptych/version";
import useRefreshRate from "./use_refresh_rate";
const BASE_PATH = "/v2/api/screen";
@@ -119,11 +118,6 @@ const loggingParams = () => {
rotation_index: ROTATION_INDEX.toString(),
version: DUP_VERSION,
};
- } else if (isTriptych()) {
- return {
- pane: getTriptychPane() ?? "UNKNOWN",
- version: TRIPTYCH_VERSION,
- };
} else {
return {};
}
@@ -131,7 +125,7 @@ const loggingParams = () => {
const useApiPath = (screenId: string, appendPath?: string): string => {
return useMemo(() => {
- const base = isOFM() ? OUTFRONT_BASE_URI : document.baseURI;
+ const base = isDup() ? OUTFRONT_BASE_URI : document.baseURI;
const path = [
BASE_PATH,
getDatasetValue("isPending") === "true" ? "pending" : null,
@@ -281,18 +275,14 @@ const useApiResponse = ({ id }) => useBaseApiResponse(id);
const useSimulationApiResponse = ({ id }) =>
useBaseApiResponse(id, "simulation");
-// For OFM apps--DUP, triptych--we need to request a different
+// For OFM apps--DUPs--we need to request a different
// route that's more permissive of CORS, since these clients are loaded from a local html file
// (and thus their data requests to our server are cross-origin).
//
// The /dup endpoint only has the CORS stuff, and otherwise runs exactly the same backend logic as
// the normal one used by `useApiResponse`.
-//
-// The /triptych endpoint has the CORS stuff, plus an additional step that maps the player name of
-// the individual triptych pane to a screen ID representing the collective trio.
const useDUPApiResponse = ({ id }) => useBaseApiResponse(id, "dup");
-const useTriptychApiResponse = ({ id }) => useBaseApiResponse(id, "triptych");
export default useApiResponse;
export type { ApiResponse, SimulationData };
-export { useSimulationApiResponse, useDUPApiResponse, useTriptychApiResponse };
+export { useSimulationApiResponse, useDUPApiResponse };
diff --git a/assets/src/hooks/v2/use_refresh_rate.ts b/assets/src/hooks/v2/use_refresh_rate.ts
index 7ed368cb4..b8ade5c00 100644
--- a/assets/src/hooks/v2/use_refresh_rate.ts
+++ b/assets/src/hooks/v2/use_refresh_rate.ts
@@ -2,7 +2,7 @@ import _ from "lodash";
import { useMemo, useState } from "react";
import { fetchDatasetValue, getDatasetValue } from "Util/dataset";
import { useReceiveFromInspector } from "Util/inspector";
-import { isOFM } from "Util/outfront";
+import { isDup } from "Util/outfront";
import { useScreenID } from "./use_screen_id";
interface RefreshRateConfig {
@@ -17,7 +17,7 @@ const useRefreshRate = (): RefreshRateConfig => {
return useMemo(() => {
// Live OFM screens ignore any configured refreshRate.
// Hardcoding to 0 prevents an interval from being started unnecessarily.
- const refreshRate = isOFM() ? "0" : fetchDatasetValue("refreshRate");
+ const refreshRate = isDup() ? "0" : fetchDatasetValue("refreshRate");
const refreshRateOffset = getDatasetValue("refreshRateOffset") || "0";
const screenIdsWithOffsetMap = getDatasetValue("screenIdsWithOffsetMap");
diff --git a/assets/src/util/outfront.tsx b/assets/src/util/outfront.tsx
index 08cb21a98..260c0bc81 100644
--- a/assets/src/util/outfront.tsx
+++ b/assets/src/util/outfront.tsx
@@ -1,14 +1,6 @@
import { ROTATION_INDEX } from "Components/v2/dup/rotation_index";
import { getDatasetValue } from "Util/dataset";
-/**
- * Returns true if this client is running on an Outfront Media screen.
- * (A DUP or a triptych.)
- *
- * Use this for OFM-specific logic that is common to both the DUP and triptych apps.
- */
-export const isOFM = () => location.href.startsWith("file:");
-
/**
* Returns true if this client is running on a DUP screen.
*
@@ -16,25 +8,13 @@ export const isOFM = () => location.href.startsWith("file:");
*/
export const isDup = () => /^file:.*dup-app.*/.test(location.href);
-/**
- * Returns true if this client is running on a triptych screen.
- *
- * Use this for triptych-specific logic.
- */
-export const isTriptych = () => /^file:.*triptych-app.*/.test(location.href);
-
type RotationIndex = "0" | "1" | "2";
const isRotationIndex = (value: any): value is RotationIndex => {
return value === "0" || value === "1" || value === "2";
};
-export type TriptychPane = "left" | "middle" | "right";
-const isTriptychPane = (value: any): value is TriptychPane => {
- return value === "left" || value === "middle" || value === "right";
-};
-
export const getRotationIndex = (): RotationIndex | null => {
- const rotationIndex = isOFM()
+ const rotationIndex = isDup()
? ROTATION_INDEX.toString()
: getDatasetValue("rotationIndex");
@@ -44,8 +24,6 @@ export const getRotationIndex = (): RotationIndex | null => {
/**
* Gets Outfront's unique name/ID for the media player we're running on.
*
- * For DUPs, this is just a single ID. For triptychs, each of the 3 panes has its own player name.
- *
* Returns null if we fail to determine the player name for any reason.
*/
export const getPlayerName = (): string | null => {
@@ -63,36 +41,6 @@ export const getPlayerName = (): string | null => {
return playerName;
};
-/**
- * Determines which of the 3 panes of a triptych we're running on (left, middle, or right).
- *
- * If we're running on a real triptych screen, we determine the pane from the `Array_configuration` tag.
- * If we're running in a browser, we determine the pane from the `data-triptych-pane` attribute on the #app div.
- *
- * Returns null if we fail to determine the pane for any reason.
- */
-export const getTriptychPane = (): TriptychPane | null => {
- const pane = isTriptych()
- ? getTriptychPaneFromTags()
- : getDatasetValue("triptychPane");
-
- return isTriptychPane(pane) ? pane : null;
-};
-
-const getTriptychPaneFromTags = () => {
- let pane: TriptychPane | null = null;
-
- const tags = getTags();
- if (tags !== null) {
- const arrayConfiguration =
- tags.find(({ name }) => name === "Array_configuration")?.value?.[0] ??
- null;
- pane = arrayConfigurationToTriptychPane(arrayConfiguration);
- }
-
- return pane;
-};
-
/**
* Gets name of the station (e.g. "Back Bay") from the `Station` tag.
*
@@ -121,25 +69,6 @@ const getTags = (): OFMTag[] | null => {
return tags;
};
-const arrayConfigurationToTriptychPane = (
- arrayConfiguration: string | null,
-): TriptychPane | null => {
- switch (arrayConfiguration) {
- case "Triple_Left":
- return "left";
- case "Triple_Middle":
- return "middle";
- case "Triple_Right":
- return "right";
- default:
- return null;
- }
-};
-
-const triptychPaneToArrayConfiguration = (pane: TriptychPane): string => {
- return `Triple_${pane[0].toUpperCase().concat(pane.slice(1))}`;
-};
-
interface OFMWindow extends Window {
mraid?: MRAID;
}
@@ -167,29 +96,23 @@ interface OFMTag {
}
export const getMRAID = (): MRAID | false => {
- if (!isOFM()) return false;
+ if (!isDup()) return false;
return (parent?.parent as OFMWindow)?.mraid ?? false;
};
/**
- * For use in test DUP/triptych packages only! Sets a fake MRAID object on `window` so that we can test OFM client packages
+ * For use in test DUP packages only! Sets a fake MRAID object on `window` so that we can test OFM client packages
* as if they are running on real OFM screens.
*/
export const __TEST_setFakeMRAID__ = (options: {
playerName: string;
station: string;
- triptychPane?: TriptychPane;
}) => {
- const { playerName, station, triptychPane } = options;
-
- const tags: OFMTag[] = [{ name: "Station", value: [station] }];
- if (triptychPane) {
- tags.push({
- name: "Array_configuration",
- value: [triptychPaneToArrayConfiguration(triptychPane)],
- });
- }
- const tagsJSON = JSON.stringify({ tags });
+ const { playerName, station } = options;
+
+ const tagsJSON = JSON.stringify({
+ tags: [{ name: "Station", value: [station] }],
+ });
const deviceInfoJSON = JSON.stringify({ deviceName: playerName });
diff --git a/assets/src/util/sentry.tsx b/assets/src/util/sentry.tsx
index 47b9fed0d..e4264ca00 100644
--- a/assets/src/util/sentry.tsx
+++ b/assets/src/util/sentry.tsx
@@ -1,4 +1,4 @@
-import { isOFM } from "Util/outfront";
+import { isDup } from "Util/outfront";
import { isRealScreen } from "Util/util";
import { getDataset } from "Util/dataset";
// Previously tried @sentry/react and @sentry/browser as the SDK, but the QtWeb browser on e-inks could not
@@ -29,7 +29,7 @@ const initSentry = (appString: string) => {
if (sentryDsn && isRealScreen()) {
Raven.config(sentryDsn, { environment: env }).install();
- if (isOFM()) {
+ if (isDup()) {
const today = new Date();
const hour = today.getHours();
const min = today.getMinutes();
diff --git a/assets/src/util/util.tsx b/assets/src/util/util.tsx
index 8c064a936..41d41811f 100644
--- a/assets/src/util/util.tsx
+++ b/assets/src/util/util.tsx
@@ -3,7 +3,7 @@ import "moment-timezone";
import { RefObject } from "react";
import { getDatasetValue } from "Util/dataset";
-import { isOFM, isTriptych } from "Util/outfront";
+import { isDup } from "Util/outfront";
export const classWithModifier = (baseClass, modifier) => {
if (!modifier) {
@@ -33,16 +33,13 @@ export const hasOverflowX = (ref: RefObject): boolean =>
!!ref.current && ref.current.scrollWidth > ref.current.clientWidth;
export const imagePath = (fileName: string): string =>
- isOFM() ? outfrontImagePath(fileName) : `/images/${fileName}`;
-
-export const outfrontImagePath = (fileName: string): string =>
- isTriptych() ? `triptych_images/${fileName}` : `images/${fileName}`;
+ isDup() ? `images/${fileName}` : `/images/${fileName}`;
export const pillPath = (fileName: string): string =>
- isOFM() ? `images/pills/${fileName}` : `/images/pills/${fileName}`;
+ isDup() ? `images/pills/${fileName}` : `/images/pills/${fileName}`;
export const isRealScreen = () =>
- isOFM() || getDatasetValue("isRealScreen") === "true";
+ isDup() || getDatasetValue("isRealScreen") === "true";
type ScreenSide = "left" | "right";
const isScreenSide = (value: any): value is ScreenSide => {
diff --git a/assets/static/images/loading-triptych.png b/assets/static/images/loading-triptych.png
deleted file mode 100644
index 35ea5ce01..000000000
Binary files a/assets/static/images/loading-triptych.png and /dev/null differ
diff --git a/assets/static/images/no-data-triptych.png b/assets/static/images/no-data-triptych.png
deleted file mode 100644
index 3630154e5..000000000
Binary files a/assets/static/images/no-data-triptych.png and /dev/null differ
diff --git a/assets/static/images/svgr_bundled/train_crowding/Car-Closed-Key.svg b/assets/static/images/svgr_bundled/train_crowding/Car-Closed-Key.svg
deleted file mode 100644
index ca67fc29f..000000000
--- a/assets/static/images/svgr_bundled/train_crowding/Car-Closed-Key.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-
diff --git a/assets/static/images/svgr_bundled/train_crowding/Car-Closed-Left.svg b/assets/static/images/svgr_bundled/train_crowding/Car-Closed-Left.svg
deleted file mode 100644
index 0f46f2340..000000000
--- a/assets/static/images/svgr_bundled/train_crowding/Car-Closed-Left.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-
diff --git a/assets/static/images/svgr_bundled/train_crowding/Car-Closed-Middle.svg b/assets/static/images/svgr_bundled/train_crowding/Car-Closed-Middle.svg
deleted file mode 100644
index 2a135cec4..000000000
--- a/assets/static/images/svgr_bundled/train_crowding/Car-Closed-Middle.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-
diff --git a/assets/static/images/svgr_bundled/train_crowding/Car-Closed-Right.svg b/assets/static/images/svgr_bundled/train_crowding/Car-Closed-Right.svg
deleted file mode 100644
index 243b1bf3d..000000000
--- a/assets/static/images/svgr_bundled/train_crowding/Car-Closed-Right.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-
diff --git a/assets/static/images/svgr_bundled/train_crowding/Car-Crowded-Key.svg b/assets/static/images/svgr_bundled/train_crowding/Car-Crowded-Key.svg
deleted file mode 100644
index aabd005aa..000000000
--- a/assets/static/images/svgr_bundled/train_crowding/Car-Crowded-Key.svg
+++ /dev/null
@@ -1,26 +0,0 @@
-
diff --git a/assets/static/images/svgr_bundled/train_crowding/Car-Crowded-Left.svg b/assets/static/images/svgr_bundled/train_crowding/Car-Crowded-Left.svg
deleted file mode 100644
index ed8c827e9..000000000
--- a/assets/static/images/svgr_bundled/train_crowding/Car-Crowded-Left.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-
diff --git a/assets/static/images/svgr_bundled/train_crowding/Car-Crowded-Middle.svg b/assets/static/images/svgr_bundled/train_crowding/Car-Crowded-Middle.svg
deleted file mode 100644
index 866ee9ab8..000000000
--- a/assets/static/images/svgr_bundled/train_crowding/Car-Crowded-Middle.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-
diff --git a/assets/static/images/svgr_bundled/train_crowding/Car-Crowded-Right.svg b/assets/static/images/svgr_bundled/train_crowding/Car-Crowded-Right.svg
deleted file mode 100644
index e2c18da07..000000000
--- a/assets/static/images/svgr_bundled/train_crowding/Car-Crowded-Right.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-
diff --git a/assets/static/images/svgr_bundled/train_crowding/Car-NoData-Key.svg b/assets/static/images/svgr_bundled/train_crowding/Car-NoData-Key.svg
deleted file mode 100644
index b5186e768..000000000
--- a/assets/static/images/svgr_bundled/train_crowding/Car-NoData-Key.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-
diff --git a/assets/static/images/svgr_bundled/train_crowding/Car-NoData-Left.svg b/assets/static/images/svgr_bundled/train_crowding/Car-NoData-Left.svg
deleted file mode 100644
index b69a0e3a0..000000000
--- a/assets/static/images/svgr_bundled/train_crowding/Car-NoData-Left.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-
diff --git a/assets/static/images/svgr_bundled/train_crowding/Car-NoData-Middle.svg b/assets/static/images/svgr_bundled/train_crowding/Car-NoData-Middle.svg
deleted file mode 100644
index 9b54906d0..000000000
--- a/assets/static/images/svgr_bundled/train_crowding/Car-NoData-Middle.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-
diff --git a/assets/static/images/svgr_bundled/train_crowding/Car-NoData-Right.svg b/assets/static/images/svgr_bundled/train_crowding/Car-NoData-Right.svg
deleted file mode 100644
index e3e25b4aa..000000000
--- a/assets/static/images/svgr_bundled/train_crowding/Car-NoData-Right.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-
diff --git a/assets/static/images/svgr_bundled/train_crowding/Car-NotCrowded-Key.svg b/assets/static/images/svgr_bundled/train_crowding/Car-NotCrowded-Key.svg
deleted file mode 100644
index f593c1440..000000000
--- a/assets/static/images/svgr_bundled/train_crowding/Car-NotCrowded-Key.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-
diff --git a/assets/static/images/svgr_bundled/train_crowding/Car-NotCrowded-Left.svg b/assets/static/images/svgr_bundled/train_crowding/Car-NotCrowded-Left.svg
deleted file mode 100644
index bfc3648a5..000000000
--- a/assets/static/images/svgr_bundled/train_crowding/Car-NotCrowded-Left.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-
diff --git a/assets/static/images/svgr_bundled/train_crowding/Car-NotCrowded-Middle.svg b/assets/static/images/svgr_bundled/train_crowding/Car-NotCrowded-Middle.svg
deleted file mode 100644
index d56b14c07..000000000
--- a/assets/static/images/svgr_bundled/train_crowding/Car-NotCrowded-Middle.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-
diff --git a/assets/static/images/svgr_bundled/train_crowding/Car-NotCrowded-Right.svg b/assets/static/images/svgr_bundled/train_crowding/Car-NotCrowded-Right.svg
deleted file mode 100644
index b6e90c98b..000000000
--- a/assets/static/images/svgr_bundled/train_crowding/Car-NotCrowded-Right.svg
+++ /dev/null
@@ -1,20 +0,0 @@
-
diff --git a/assets/static/images/svgr_bundled/train_crowding/Car-SomeCrowding-Key.svg b/assets/static/images/svgr_bundled/train_crowding/Car-SomeCrowding-Key.svg
deleted file mode 100644
index 72d16189c..000000000
--- a/assets/static/images/svgr_bundled/train_crowding/Car-SomeCrowding-Key.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-
diff --git a/assets/static/images/svgr_bundled/train_crowding/Car-SomeCrowding-Left.svg b/assets/static/images/svgr_bundled/train_crowding/Car-SomeCrowding-Left.svg
deleted file mode 100644
index 538ac1754..000000000
--- a/assets/static/images/svgr_bundled/train_crowding/Car-SomeCrowding-Left.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-
diff --git a/assets/static/images/svgr_bundled/train_crowding/Car-SomeCrowding-Middle.svg b/assets/static/images/svgr_bundled/train_crowding/Car-SomeCrowding-Middle.svg
deleted file mode 100644
index 14a156861..000000000
--- a/assets/static/images/svgr_bundled/train_crowding/Car-SomeCrowding-Middle.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-
diff --git a/assets/static/images/svgr_bundled/train_crowding/Car-SomeCrowding-Right.svg b/assets/static/images/svgr_bundled/train_crowding/Car-SomeCrowding-Right.svg
deleted file mode 100644
index 2974d3db2..000000000
--- a/assets/static/images/svgr_bundled/train_crowding/Car-SomeCrowding-Right.svg
+++ /dev/null
@@ -1,22 +0,0 @@
-
diff --git a/assets/static/images/triptych_psas/See-Say/left.webp b/assets/static/images/triptych_psas/See-Say/left.webp
deleted file mode 100644
index 808993e68..000000000
Binary files a/assets/static/images/triptych_psas/See-Say/left.webp and /dev/null differ
diff --git a/assets/static/images/triptych_psas/See-Say/middle.webp b/assets/static/images/triptych_psas/See-Say/middle.webp
deleted file mode 100644
index fa85a530a..000000000
Binary files a/assets/static/images/triptych_psas/See-Say/middle.webp and /dev/null differ
diff --git a/assets/static/images/triptych_psas/See-Say/right.webp b/assets/static/images/triptych_psas/See-Say/right.webp
deleted file mode 100644
index 0ffdbcc73..000000000
Binary files a/assets/static/images/triptych_psas/See-Say/right.webp and /dev/null differ
diff --git a/assets/static/images/triptych_psas/Stroll-n-Scroll/left.webp b/assets/static/images/triptych_psas/Stroll-n-Scroll/left.webp
deleted file mode 100644
index c4a27f5e8..000000000
Binary files a/assets/static/images/triptych_psas/Stroll-n-Scroll/left.webp and /dev/null differ
diff --git a/assets/static/images/triptych_psas/Stroll-n-Scroll/middle.webp b/assets/static/images/triptych_psas/Stroll-n-Scroll/middle.webp
deleted file mode 100644
index cc713445f..000000000
Binary files a/assets/static/images/triptych_psas/Stroll-n-Scroll/middle.webp and /dev/null differ
diff --git a/assets/static/images/triptych_psas/Stroll-n-Scroll/right.webp b/assets/static/images/triptych_psas/Stroll-n-Scroll/right.webp
deleted file mode 100644
index 5bd8014be..000000000
Binary files a/assets/static/images/triptych_psas/Stroll-n-Scroll/right.webp and /dev/null differ
diff --git a/assets/webpack.config.js b/assets/webpack.config.js
index ae62fe9b0..80179a8ee 100644
--- a/assets/webpack.config.js
+++ b/assets/webpack.config.js
@@ -8,62 +8,6 @@ const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const { sentryWebpackPlugin } = require("@sentry/webpack-plugin");
-const common_export_body = {
- resolve: {
- extensions: [".ts", ".tsx", ".js", ".jsx"],
- alias: {
- // Please also update the "paths" list in tsconfig.json when you add aliases here!
- Components: path.resolve(__dirname, "src/components"),
- Hooks: path.resolve(__dirname, "src/hooks"),
- Util: path.resolve(__dirname, "src/util"),
- Constants: path.resolve(__dirname, "src/constants"),
- Images: path.resolve(__dirname, "static/images"),
- },
- },
- output: {
- filename: "[name].js",
- path: path.resolve(__dirname, "../priv/static/js"),
- },
- devtool: "source-map",
- optimization: {
- minimizer: [new TerserPlugin(), new OptimizeCSSAssetsPlugin()],
- },
-};
-
-const common_rules = [
- {
- enforce: "pre",
- test: /\.js$/,
- loader: "source-map-loader",
- },
- {
- test: /\.s?css$/,
- use: [
- MiniCssExtractPlugin.loader,
- {
- loader: "css-loader",
- },
- {
- loader: "sass-loader",
- },
- ],
- },
- {
- test: /\.svg$/i,
- issuer: /\.[jt]sx?$/,
- use: ["@svgr/webpack"],
- },
-];
-
-const common_babel_loader_plugins = [
- "@babel/plugin-proposal-export-default-from",
- "@babel/plugin-proposal-logical-assignment-operators",
- ["@babel/plugin-proposal-optional-chaining", { loose: false }],
- ["@babel/plugin-proposal-pipeline-operator", { proposal: "minimal" }],
- ["@babel/plugin-proposal-nullish-coalescing-operator", { loose: false }],
- "@babel/plugin-proposal-do-expressions",
-];
-
module.exports = (env, argv) => {
// Upload source maps to Sentry for prod builds. Must be the last plugin.
const appendPlugins =
@@ -79,7 +23,25 @@ module.exports = (env, argv) => {
return [
{
- ...common_export_body,
+ resolve: {
+ extensions: [".ts", ".tsx", ".js", ".jsx"],
+ alias: {
+ // Please also update the "paths" list in tsconfig.json when you add aliases here!
+ Components: path.resolve(__dirname, "src/components"),
+ Hooks: path.resolve(__dirname, "src/hooks"),
+ Util: path.resolve(__dirname, "src/util"),
+ Constants: path.resolve(__dirname, "src/constants"),
+ Images: path.resolve(__dirname, "static/images"),
+ },
+ },
+ output: {
+ filename: "[name].js",
+ path: path.resolve(__dirname, "../priv/static/js"),
+ },
+ devtool: "source-map",
+ optimization: {
+ minimizer: [new TerserPlugin(), new OptimizeCSSAssetsPlugin()],
+ },
entry: {
polyfills: "./src/polyfills.js",
bus_eink: "./src/apps/bus_eink.tsx",
@@ -95,7 +57,6 @@ module.exports = (env, argv) => {
dup_v2: "./src/apps/v2/dup.tsx",
bus_shelter_v2: "./src/apps/v2/bus_shelter.tsx",
pre_fare_v2: "./src/apps/v2/pre_fare.tsx",
- triptych_v2: "./src/apps/v2/triptych.tsx",
},
module: {
rules: [
@@ -110,76 +71,48 @@ module.exports = (env, argv) => {
"@babel/preset-react",
"@babel/preset-typescript",
],
- plugins: common_babel_loader_plugins,
+ plugins: [
+ "@babel/plugin-proposal-export-default-from",
+ "@babel/plugin-proposal-logical-assignment-operators",
+ [
+ "@babel/plugin-proposal-optional-chaining",
+ { loose: false },
+ ],
+ [
+ "@babel/plugin-proposal-pipeline-operator",
+ { proposal: "minimal" },
+ ],
+ [
+ "@babel/plugin-proposal-nullish-coalescing-operator",
+ { loose: false },
+ ],
+ "@babel/plugin-proposal-do-expressions",
+ ],
},
},
},
- ...common_rules,
{
- test: /\.(woff(2)?|ttf|eot)(\?v=\d+\.\d+\.\d+)?$/,
- use: [
- {
- loader: "file-loader",
- options: {
- name: "[name].[ext]",
- outputPath: "fonts/",
- publicPath: "../fonts/",
- useRelativePaths: true,
- },
- },
- ],
+ enforce: "pre",
+ test: /\.js$/,
+ loader: "source-map-loader",
},
{
- test: /\.(png|jpe?g|gif|webp)$/i,
+ test: /\.s?css$/,
use: [
+ MiniCssExtractPlugin.loader,
{
- loader: "file-loader",
- options: {
- name: "/[folder]/[name].[ext]",
- useRelativePaths: true,
- },
+ loader: "css-loader",
+ },
+ {
+ loader: "sass-loader",
},
],
},
- ],
- },
- plugins: [
- new MiniCssExtractPlugin({ filename: "../css/[name].css" }),
- new CopyWebpackPlugin({ patterns: [{ from: "static/", to: "../" }] }),
- ...appendPlugins,
- ],
- },
- {
- ...common_export_body,
- entry: {
- packaged_triptych_polyfills: "./src/polyfills.js",
- packaged_triptych_v2: "./src/apps/v2/triptych.tsx",
- },
- module: {
- rules: [
{
- test: /\.ts(x?)$/,
- exclude: /node_modules/,
- use: {
- loader: "babel-loader",
- options: {
- presets: [
- // When no targets are specified: Babel will assume you are targeting the oldest browsers possible.
- [
- "@babel/preset-env",
- {
- corejs: { version: 3, proposals: true },
- useBuiltIns: "usage",
- },
- ],
- "@babel/preset-react",
- "@babel/preset-typescript",
- ],
- plugins: common_babel_loader_plugins,
- },
- },
+ test: /\.svg$/i,
+ issuer: /\.[jt]sx?$/,
+ use: ["@svgr/webpack"],
},
- ...common_rules,
{
test: /\.(woff(2)?|ttf|eot)(\?v=\d+\.\d+\.\d+)?$/,
use: [
@@ -188,36 +121,19 @@ module.exports = (env, argv) => {
options: {
name: "[name].[ext]",
outputPath: "fonts/",
- publicPath: "fonts/",
- useRelativePaths: true,
- },
- },
- ],
- },
- {
- test: /\.(png|jpe?g|gif)$/i,
- use: [
- {
- loader: "file-loader",
-
- options: {
- name: "[name].[ext]",
- outputPath: "triptych_images/",
- publicPath: "triptych_images/",
+ publicPath: "../fonts/",
useRelativePaths: true,
},
},
],
},
{
- test: /\.(webp)$/i,
+ test: /\.(png|jpe?g|gif|webp)$/i,
use: [
{
loader: "file-loader",
options: {
name: "/[folder]/[name].[ext]",
- outputPath: "triptych_images/triptych_psas/",
- publicPath: "triptych_images/triptych_psas/",
useRelativePaths: true,
},
},
@@ -227,9 +143,7 @@ module.exports = (env, argv) => {
},
plugins: [
new MiniCssExtractPlugin({ filename: "../css/[name].css" }),
- new CopyWebpackPlugin({
- patterns: [{ from: "static/fonts", to: "../fonts" }],
- }),
+ new CopyWebpackPlugin({ patterns: [{ from: "static/", to: "../" }] }),
...appendPlugins,
],
},
diff --git a/config/config.exs b/config/config.exs
index b0bfaa12b..2a45747ea 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -70,8 +70,6 @@ config :screens,
audio_psa_s3_directory: "/screens/audio_assets/psa/",
signs_ui_s3_path: "config.json",
signs_ui_config_fetcher: Screens.SignsUiConfig.Fetch.S3,
- triptych_player_s3_bucket: "mbta-ctd-config",
- triptych_player_fetcher: Screens.TriptychPlayer.Fetch.S3,
last_deploy_fetcher: Screens.Util.LastDeploy.S3Fetch,
blue_bikes_api_client: Screens.BlueBikes.Client,
blue_bikes_station_information_url:
diff --git a/config/dev.exs b/config/dev.exs
index 69b2c71bd..3f174537c 100644
--- a/config/dev.exs
+++ b/config/dev.exs
@@ -16,13 +16,11 @@ config :screens, ScreensWeb.Endpoint,
config :screens,
config_fetcher: Screens.Config.Fetch.Local,
pending_config_fetcher: Screens.PendingConfig.Fetch.Local,
- triptych_player_fetcher: Screens.TriptychPlayer.Fetch.Local,
last_deploy_fetcher: Screens.Util.LastDeploy.LocalFetch,
local_config_file_spec: {:priv, "local.json"},
local_pending_config_file_spec: {:priv, "local_pending.json"},
local_signs_ui_config_file_spec: {:priv, "signs_ui_config.json"},
- signs_ui_config_fetcher: Screens.SignsUiConfig.Fetch.Local,
- local_triptych_player_file_spec: {:priv, "triptych_player_to_screen_id.json"}
+ signs_ui_config_fetcher: Screens.SignsUiConfig.Fetch.Local
config :screens, ScreensWeb.AuthManager, secret_key: "secret key"
diff --git a/config/test.exs b/config/test.exs
index d6a7662fe..0232e9d1d 100644
--- a/config/test.exs
+++ b/config/test.exs
@@ -13,9 +13,7 @@ config :screens,
local_config_file_spec: {:test, "config.json"},
local_pending_config_file_spec: {:test, "pending_config.json"},
local_signs_ui_config_file_spec: {:test, "signs_ui_config.json"},
- local_triptych_player_file_spec: {:test, "triptych_player_to_screen_id.json"},
signs_ui_config_fetcher: Screens.SignsUiConfig.Fetch.Local,
- triptych_player_fetcher: Screens.TriptychPlayer.Fetch.Local,
# This will help us write testable functions.
# Functions that request external data cause flaky tests, so to stop us from writing tests that execute API requests,
# we pass a non-string as the default URL (causing tests to break.)
diff --git a/lib/screens/application.ex b/lib/screens/application.ex
index 131d9a94c..1aba7fb38 100644
--- a/lib/screens/application.ex
+++ b/lib/screens/application.ex
@@ -13,7 +13,6 @@ defmodule Screens.Application do
Screens.Telemetry,
{Screens.Cache.Owner, engine_module: Screens.Config.Cache.Engine},
{Screens.Cache.Owner, engine_module: Screens.SignsUiConfig.Cache.Engine},
- {Screens.Cache.Owner, engine_module: Screens.TriptychPlayer.Cache.Engine},
:hackney_pool.child_spec(:ex_aws_pool, []),
:hackney_pool.child_spec(:blue_bikes_pool, []),
:hackney_pool.child_spec(:api_v3_pool, max_connections: 100),
@@ -27,8 +26,6 @@ defmodule Screens.Application do
{Task.Supervisor, name: Screens.ScreensByAlert.SelfRefreshRunner.TaskSupervisor},
# ScreensByAlert self-refresh job runner
{Screens.ScreensByAlert.SelfRefreshRunner, name: Screens.ScreensByAlert.SelfRefreshRunner},
- Screens.OlCrowding.DynamicSupervisor,
- {Screens.OlCrowding.Agent, %{}},
# Task supervisor for parallel running of candidate generator variants
{Task.Supervisor, name: Screens.V2.ScreenData.ParallelRunSupervisor},
{Screens.ScreenApiResponseCache, []},
diff --git a/lib/screens/log_screen_data.ex b/lib/screens/log_screen_data.ex
index af791a762..b32418b7c 100644
--- a/lib/screens/log_screen_data.ex
+++ b/lib/screens/log_screen_data.ex
@@ -25,8 +25,6 @@ defmodule Screens.LogScreenData do
if is_screen or not is_nil(requestor) do
screen_side = params["screen_side"]
rotation_index = params["rotation_index"]
- triptych_pane = params["pane"]
- triptych_player_name = params["player_name"]
ofm_app_package_version = params["version"]
data =
@@ -38,8 +36,6 @@ defmodule Screens.LogScreenData do
|> insert_screen_side(screen_side)
|> insert_requestor(requestor)
|> insert_dup_rotation_index(rotation_index)
- |> insert_triptych_pane(triptych_pane)
- |> insert_triptych_player_name(triptych_player_name)
|> insert_version(ofm_app_package_version)
log_message("[screen data request]", data)
@@ -67,10 +63,6 @@ defmodule Screens.LogScreenData do
log_message("[screen frontend error]", data)
end
- def log_unrecognized_triptych_player(player_name) do
- log_message("[unrecognized triptych player name]", %{player_name: player_name})
- end
-
def log_api_response(response, screen_id, last_refresh, is_screen, screen_side \\ nil)
def log_api_response(
@@ -157,16 +149,6 @@ defmodule Screens.LogScreenData do
defp insert_dup_rotation_index(data, rotation_index),
do: Map.put(data, :page_number, rotation_index)
- defp insert_triptych_pane(data, nil), do: data
-
- defp insert_triptych_pane(data, triptych_pane),
- do: Map.put(data, :triptych_pane, triptych_pane)
-
- defp insert_triptych_player_name(data, nil), do: data
-
- defp insert_triptych_player_name(data, triptych_player_name),
- do: Map.put(data, :triptych_player_name, triptych_player_name)
-
defp insert_version(data, nil), do: data
defp insert_version(data, version), do: Map.put(data, :ofm_app_package_version, version)
end
diff --git a/lib/screens/ol_crowding/agent.ex b/lib/screens/ol_crowding/agent.ex
deleted file mode 100644
index 89f49a00f..000000000
--- a/lib/screens/ol_crowding/agent.ex
+++ /dev/null
@@ -1,23 +0,0 @@
-defmodule Screens.OlCrowding.Agent do
- @moduledoc false
- use Agent
-
- def start_link(initial_value) do
- Agent.start_link(fn -> initial_value end, name: __MODULE__)
- end
-
- def get(station_id, direction_id) do
- Agent.get(__MODULE__, &Map.get(&1, "#{station_id}.#{direction_id}"))
- end
-
- def delete(station_id, direction_id) do
- Agent.update(__MODULE__, &Map.delete(&1, "#{station_id}.#{direction_id}"))
- end
-
- def put(station_id, direction_id, previous_station_stopped_prediction) do
- Agent.update(
- __MODULE__,
- &Map.put(&1, "#{station_id}.#{direction_id}", previous_station_stopped_prediction)
- )
- end
-end
diff --git a/lib/screens/ol_crowding/dynamic_supervisor.ex b/lib/screens/ol_crowding/dynamic_supervisor.ex
deleted file mode 100644
index dbd64fb3a..000000000
--- a/lib/screens/ol_crowding/dynamic_supervisor.ex
+++ /dev/null
@@ -1,49 +0,0 @@
-defmodule Screens.OlCrowding.DynamicSupervisor do
- @moduledoc false
-
- require Logger
-
- use DynamicSupervisor
- alias Screens.OlCrowding.LogCrowdingInfo
-
- def start_link(init_arg) do
- DynamicSupervisor.start_link(__MODULE__, init_arg, name: __MODULE__)
- end
-
- @impl true
- def init(_init_arg) do
- DynamicSupervisor.init(strategy: :one_for_one)
- end
-
- def start_logger(
- original_crowding_levels,
- %{
- next_train_prediction: prediction,
- logging_options: logging_options,
- train_crowding_config: train_crowding_config,
- fetch_predictions_fn: fetch_predictions_fn,
- fetch_parent_stop_id_fn: fetch_parent_stop_id_fn,
- fetch_params: fetch_params
- }
- ) do
- spec = %{
- id: LogCrowdingInfo,
- start:
- {LogCrowdingInfo, :start_link,
- [
- %{
- original_crowding_levels: original_crowding_levels,
- prediction: prediction,
- logging_options: logging_options,
- train_crowding_config: train_crowding_config,
- fetch_predictions_fn: fetch_predictions_fn,
- fetch_parent_stop_id_fn: fetch_parent_stop_id_fn,
- fetch_params: fetch_params
- }
- ]},
- restart: :transient
- }
-
- DynamicSupervisor.start_child(__MODULE__, spec)
- end
-end
diff --git a/lib/screens/ol_crowding/logger.ex b/lib/screens/ol_crowding/logger.ex
deleted file mode 100644
index f883702df..000000000
--- a/lib/screens/ol_crowding/logger.ex
+++ /dev/null
@@ -1,81 +0,0 @@
-defmodule Screens.OlCrowding.LogCrowdingInfo do
- @moduledoc false
-
- require Logger
- use GenServer
-
- alias Screens.Predictions.Prediction
- alias Screens.Util
-
- def start_link(opts) do
- GenServer.start_link(__MODULE__, opts)
- end
-
- @impl true
- def init(state) do
- # Widget only shows for a maximum of 15 seconds. Go ahead and schedule the exit.
- Process.send_after(self(), :shutdown, 15_000)
-
- schedule_run()
-
- {:ok, state}
- end
-
- @impl true
- def handle_info(
- :run,
- %{
- original_crowding_levels: original_crowding_levels,
- prediction: prediction,
- logging_options: %{
- is_real_screen: true,
- screen_id: screen_id,
- triptych_pane: triptych_pane
- },
- train_crowding_config: train_crowding_config,
- fetch_predictions_fn: fetch_predictions_fn,
- fetch_parent_stop_id_fn: fetch_parent_stop_id_fn,
- fetch_params: fetch_params
- } = state
- ) do
- schedule_run()
-
- {:ok, predictions} = fetch_predictions_fn.(fetch_params)
- next_train_prediction = List.first(predictions)
-
- crowding_levels =
- Enum.map_join(
- prediction.vehicle.carriages,
- ",",
- &Util.translate_carriage_occupancy_status/1
- )
-
- cond do
- # A car's crowding level changed. Log it and shutdown the process.
- original_crowding_levels != crowding_levels ->
- Logger.info(
- "[train_crowding car_crowding_class_change] screen_id=#{screen_id} triptych_pane=#{triptych_pane} trip_id=#{prediction.trip.id} original_crowding_levels=#{original_crowding_levels} car_crowding_levels=#{crowding_levels}"
- )
-
- {:stop, :shutdown, state}
-
- # The train is now stopped at the current station and no crowding level changed. Shut down the process without logging.
- Prediction.vehicle_status(next_train_prediction) == :stopped_at and
- next_train_prediction |> Prediction.stop_for_vehicle() |> fetch_parent_stop_id_fn.() ==
- train_crowding_config.station_id ->
- {:stop, :shutdown, state}
-
- # Still more work to do.
- true ->
- {:noreply, state}
- end
- end
-
- def handle_info(:shutdown, state) do
- {:stop, :shutdown, state}
- end
-
- defp schedule_run do
- Process.send_after(self(), :run, 2000)
- end
-end
diff --git a/lib/screens/screens_by_alert/self_refresh_runner.ex b/lib/screens/screens_by_alert/self_refresh_runner.ex
index 9b8031d8f..63db62fd8 100644
--- a/lib/screens/screens_by_alert/self_refresh_runner.ex
+++ b/lib/screens/screens_by_alert/self_refresh_runner.ex
@@ -91,13 +91,11 @@ defmodule Screens.ScreensByAlert.SelfRefreshRunner do
# A screen is valid for self-refresh if all of these are true:
# - It's a v2 screen (i.e., it shows widgets)
# - It's not hidden from Screenplay
- # - It's a screen type that can show alerts in some capacity
defp valid_for_self_refresh?(screen_config) do
is_v2 = Screen.v2_screen?(screen_config)
is_visible_to_screenplay = not screen_config.hidden_from_screenplay
- shows_alerts = Screen.shows_alerts?(screen_config)
- is_v2 and is_visible_to_screenplay and shows_alerts
+ is_v2 and is_visible_to_screenplay
end
defp schedule_run do
diff --git a/lib/screens/stops/stop.ex b/lib/screens/stops/stop.ex
index e8d258d43..55cd9e7bf 100644
--- a/lib/screens/stops/stop.ex
+++ b/lib/screens/stops/stop.ex
@@ -17,7 +17,7 @@ defmodule Screens.Stops.Stop do
alias Screens.Stops
alias Screens.Util
alias Screens.V3Api
- alias ScreensConfig.V2.{BusEink, BusShelter, Dup, GlEink, PreFare, Triptych}
+ alias ScreensConfig.V2.{BusEink, BusShelter, Dup, GlEink, PreFare}
defstruct id: nil,
name: nil,
@@ -33,7 +33,7 @@ defmodule Screens.Stops.Stop do
platform_name: String.t() | nil
}
- @type screen_type :: BusEink | BusShelter | GlEink | PreFare | Dup | Triptych
+ @type screen_type :: BusEink | BusShelter | GlEink | PreFare | Dup
@blue_line_stops [
{"place-wondl", {"Wonderland", "Wonderland"}},
@@ -447,7 +447,6 @@ defmodule Screens.Stops.Stop do
# Ashmont should not show Mattapan alerts for PreFare or Dup
def get_route_type_filter(app, "place-asmnl") when app in [PreFare, Dup], do: [:subway]
def get_route_type_filter(PreFare, _), do: [:light_rail, :subway]
- def get_route_type_filter(Triptych, _), do: [:light_rail, :subway]
# WTC is a special bus-only case
def get_route_type_filter(Dup, "place-wtcst"), do: [:bus]
def get_route_type_filter(Dup, _), do: [:light_rail, :subway]
@@ -483,14 +482,12 @@ defmodule Screens.Stops.Stop do
RoutePattern.fetch_tagged_stop_sequences_through_stop(stop_id)
end
- defp fetch_tagged_stop_sequences_by_app(app, stop_id, routes_at_stop)
- when app in [Dup, Triptych] do
+ defp fetch_tagged_stop_sequences_by_app(Dup, stop_id, routes_at_stop) do
route_ids = Route.route_ids(routes_at_stop)
RoutePattern.fetch_tagged_parent_station_sequences_through_stop(stop_id, route_ids)
end
- defp fetch_tagged_stop_sequences_by_app(app, stop_id, routes_at_stop)
- when app == PreFare do
+ defp fetch_tagged_stop_sequences_by_app(PreFare, stop_id, routes_at_stop) do
route_ids = Route.route_ids(routes_at_stop)
# We limit results to canonical route patterns only--no stop sequences for nonstandard patterns.
diff --git a/lib/screens/triptych_player.ex b/lib/screens/triptych_player.ex
deleted file mode 100644
index e859888cc..000000000
--- a/lib/screens/triptych_player.ex
+++ /dev/null
@@ -1,20 +0,0 @@
-defmodule Screens.TriptychPlayer do
- @moduledoc """
- Provides access to a mapping from triptych player name
- (a unique ID for an individual pane of a triptych trio, provided by OFM)
- to screen ID
- (our ID for the collective triptych screen comprising 3 panes).
-
- The mapping is cached in an ETS table controlled by a GenServer
- which checks for updates to the source JSON file every 15 seconds.
- """
-
- alias Screens.TriptychPlayer.Cache
- alias Screens.TriptychPlayer.Validator
-
- defdelegate fetch_screen_id_for_player(player_name), to: Cache
-
- defdelegate fetch_player_names_for_screen_id(player_name), to: Cache
-
- defdelegate validate(mapping), to: Validator
-end
diff --git a/lib/screens/triptych_player/cache.ex b/lib/screens/triptych_player/cache.ex
deleted file mode 100644
index e86c41495..000000000
--- a/lib/screens/triptych_player/cache.ex
+++ /dev/null
@@ -1,38 +0,0 @@
-defmodule Screens.TriptychPlayer.Cache do
- @moduledoc """
- Functions to read data from a cached copy of the triptych player config.
- """
-
- use Screens.Cache.Client, table: :triptych_player
-
- @type table_contents :: list(table_entry)
-
- @type table_entry :: {player_name :: String.t(), screen_id :: String.t()}
-
- def fetch_screen_id_for_player(player_name) do
- with_table default: :error do
- case :ets.match(@table, {player_name, :"$1"}) do
- [[screen_id]] -> {:ok, screen_id}
- [] -> :error
- end
- end
- end
-
- def fetch_player_names_for_screen_id(screen_id) do
- with_table default: :error do
- player_names =
- @table
- # [[name1], [name2], [name3]]
- |> :ets.match({:"$1", screen_id})
- # [name1, name2, name3]
- |> List.flatten()
- # (Just in case)
- |> Enum.uniq()
-
- case player_names do
- [] -> :error
- l -> {:ok, l}
- end
- end
- end
-end
diff --git a/lib/screens/triptych_player/cache/engine.ex b/lib/screens/triptych_player/cache/engine.ex
deleted file mode 100644
index 1f8725039..000000000
--- a/lib/screens/triptych_player/cache/engine.ex
+++ /dev/null
@@ -1,31 +0,0 @@
-defmodule Screens.TriptychPlayer.Cache.Engine do
- @moduledoc """
- Engine for the triptych player config cache.
- """
-
- alias Screens.TriptychPlayer.Fetch
-
- @behaviour Screens.Cache.Engine
-
- @impl true
- def name, do: Screens.TriptychPlayer.Cache.table()
-
- @impl true
- def update_table(current_version) do
- with {:ok, body, new_version} <- Fetch.fetch_config(current_version),
- {:ok, deserialized} <- Jason.decode(body) do
- table_entries = Map.to_list(deserialized)
-
- {:replace, table_entries, new_version}
- else
- :unchanged -> :unchanged
- _ -> :error
- end
- end
-
- @impl true
- def update_interval_ms, do: 15_000
-
- @impl true
- def update_failure_error_log_threshold_minutes, do: 0
-end
diff --git a/lib/screens/triptych_player/fetch.ex b/lib/screens/triptych_player/fetch.ex
deleted file mode 100644
index 409d603ee..000000000
--- a/lib/screens/triptych_player/fetch.ex
+++ /dev/null
@@ -1,21 +0,0 @@
-defmodule Screens.TriptychPlayer.Fetch do
- @moduledoc """
- Defines a behaviour for, and delegates to, a module that provides access to
- the triptych player config file.
- """
-
- alias Screens.Cache.Engine
-
- @callback fetch_config(Engine.table_version()) ::
- {:ok, String.t(), Engine.table_version()} | :unchanged | :error
-
- @callback put_config(String.t()) :: :ok | :error
-
- alias Screens.Cache.Engine
-
- @config_fetcher Application.compile_env(:screens, :triptych_player_fetcher)
-
- defdelegate fetch_config(config_version), to: @config_fetcher
- defdelegate fetch_config(), to: @config_fetcher
- defdelegate put_config(file_contents), to: @config_fetcher
-end
diff --git a/lib/screens/triptych_player/fetch/local.ex b/lib/screens/triptych_player/fetch/local.ex
deleted file mode 100644
index 1684c9601..000000000
--- a/lib/screens/triptych_player/fetch/local.ex
+++ /dev/null
@@ -1,49 +0,0 @@
-defmodule Screens.TriptychPlayer.Fetch.Local do
- @moduledoc """
- Functions to work with a local copy of the triptych player config.
- """
-
- @behaviour Screens.TriptychPlayer.Fetch
-
- @impl true
- def fetch_config(current_version \\ nil) do
- path = local_config_path()
-
- with {:ok, last_modified} <- get_last_modified(path) do
- if last_modified == current_version do
- :unchanged
- else
- do_fetch(path, last_modified)
- end
- end
- end
-
- @impl true
- def put_config(file_contents) do
- case File.write(local_config_path(), file_contents) do
- :ok -> :ok
- {:error, _} -> :error
- end
- end
-
- defp local_config_path do
- case Application.get_env(:screens, :local_triptych_player_file_spec) do
- {:priv, file_name} -> Path.join(:code.priv_dir(:screens), file_name)
- {:test, file_name} -> Path.join(~w[#{File.cwd!()} test fixtures #{file_name}])
- end
- end
-
- defp do_fetch(path, last_modified) do
- case File.read(path) do
- {:ok, contents} -> {:ok, contents, last_modified}
- _ -> :error
- end
- end
-
- defp get_last_modified(path) do
- case File.stat(path) do
- {:ok, %File.Stat{mtime: mtime}} -> {:ok, mtime}
- {:error, _} -> :error
- end
- end
-end
diff --git a/lib/screens/triptych_player/fetch/s3.ex b/lib/screens/triptych_player/fetch/s3.ex
deleted file mode 100644
index 5849b2db0..000000000
--- a/lib/screens/triptych_player/fetch/s3.ex
+++ /dev/null
@@ -1,57 +0,0 @@
-defmodule Screens.TriptychPlayer.Fetch.S3 do
- @moduledoc """
- Functions to work with an S3-hosted copy of the triptych player config.
- """
-
- require Logger
-
- @behaviour Screens.TriptychPlayer.Fetch
-
- @impl true
- def fetch_config(current_version \\ nil) do
- bucket = Application.get_env(:screens, :triptych_player_s3_bucket)
- path = config_path_for_environment()
-
- opts =
- case current_version do
- nil -> []
- _ -> [if_none_match: current_version]
- end
-
- get_operation = ExAws.S3.get_object(bucket, path, opts)
-
- case ExAws.request(get_operation) do
- {:ok, %{status_code: 304}} ->
- :unchanged
-
- {:ok, %{body: body, headers: headers, status_code: 200}} ->
- etag =
- headers
- |> Enum.into(%{})
- |> Map.get("ETag")
-
- {:ok, body, etag}
-
- {:error, err} ->
- _ = Logger.info("s3_triptych_player_config_fetch_error #{inspect(err)}")
- :error
- end
- end
-
- @impl true
- def put_config(file_contents) do
- bucket = Application.get_env(:screens, :triptych_player_s3_bucket)
- path = config_path_for_environment()
- put_operation = ExAws.S3.put_object(bucket, path, file_contents)
-
- case ExAws.request(put_operation) do
- {:ok, %{status_code: 200}} -> :ok
- _ -> :error
- end
- end
-
- defp config_path_for_environment do
- "screens-" <> env = Application.get_env(:screens, :environment_name, "screens-prod")
- "screens/triptych-player-#{env}.json"
- end
-end
diff --git a/lib/screens/triptych_player/validator.ex b/lib/screens/triptych_player/validator.ex
deleted file mode 100644
index 82b148b30..000000000
--- a/lib/screens/triptych_player/validator.ex
+++ /dev/null
@@ -1,54 +0,0 @@
-defmodule Screens.TriptychPlayer.Validator do
- @moduledoc false
-
- @doc """
- Determines whether a term is a valid player name -> screen ID mapping.
- """
- @spec validate(term()) :: :ok | {:error, reason :: String.t()}
- def validate(mapping) do
- with :ok <- validate_map(mapping),
- :ok <- validate_string_keys(mapping) do
- validate_screen_id_values(mapping)
- end
- end
-
- defp validate_map(mapping) when is_map(mapping), do: :ok
- defp validate_map(_), do: {:error, "Not a map"}
-
- defp validate_string_keys(mapping) do
- invalid_keys =
- mapping
- |> Map.keys()
- |> Enum.reject(&is_binary/1)
-
- case invalid_keys do
- [] -> :ok
- keys -> {:error, "Mapping contains non-string keys: #{inspect(keys)}"}
- end
- end
-
- defp validate_screen_id_values(mapping) do
- mapped_screen_ids =
- mapping
- |> Map.values()
- |> MapSet.new()
-
- all_triptych_screen_ids =
- MapSet.new(
- Screens.Config.Cache.screen_ids(&match?({_screen_id, %{app_id: :triptych_v2}}, &1))
- )
-
- if MapSet.subset?(mapped_screen_ids, all_triptych_screen_ids) do
- :ok
- else
- unrecognized_ids =
- mapped_screen_ids
- |> MapSet.difference(all_triptych_screen_ids)
- |> Enum.sort()
-
- {:error,
- "Mapping contains unrecognized triptych screen IDs: #{inspect(unrecognized_ids)}.\n\n" <>
- "Make sure all relevant screens have been configured as triptychs before linking them to triptych player names."}
- end
- end
-end
diff --git a/lib/screens/v2/candidate_generator.ex b/lib/screens/v2/candidate_generator.ex
index fe5bb0eb5..e4128ec20 100644
--- a/lib/screens/v2/candidate_generator.ex
+++ b/lib/screens/v2/candidate_generator.ex
@@ -13,7 +13,7 @@ defmodule Screens.V2.CandidateGenerator do
Fetches data and returns a list of candidate widget instances to be
considered for placement on the template.
"""
- @callback candidate_instances(Screen.t(), keyword()) :: [WidgetInstance.t()]
+ @callback candidate_instances(Screen.t()) :: [WidgetInstance.t()]
@doc """
Receives the finalized list of widget instances that were placed on
diff --git a/lib/screens/v2/candidate_generator/bus_eink.ex b/lib/screens/v2/candidate_generator/bus_eink.ex
index 9a5c1fef9..09a718510 100644
--- a/lib/screens/v2/candidate_generator/bus_eink.ex
+++ b/lib/screens/v2/candidate_generator/bus_eink.ex
@@ -49,7 +49,6 @@ defmodule Screens.V2.CandidateGenerator.BusEink do
# credo:disable-for-next-line Credo.Check.Design.DuplicatedCode
def candidate_instances(
config,
- _opts,
now \\ DateTime.utc_now(),
fetch_stop_name_fn \\ &Stop.fetch_stop_name/1,
departures_instances_fn \\ &Widgets.Departures.departures_instances/2,
diff --git a/lib/screens/v2/candidate_generator/bus_shelter.ex b/lib/screens/v2/candidate_generator/bus_shelter.ex
index 55ae61802..4fdbcd28d 100644
--- a/lib/screens/v2/candidate_generator/bus_shelter.ex
+++ b/lib/screens/v2/candidate_generator/bus_shelter.ex
@@ -47,7 +47,6 @@ defmodule Screens.V2.CandidateGenerator.BusShelter do
# credo:disable-for-next-line Credo.Check.Design.DuplicatedCode
def candidate_instances(
config,
- _opts,
now \\ DateTime.utc_now(),
fetch_stop_name_fn \\ &Stop.fetch_stop_name/1,
departures_instances_fn \\ &Widgets.Departures.departures_instances/2,
diff --git a/lib/screens/v2/candidate_generator/busway.ex b/lib/screens/v2/candidate_generator/busway.ex
index ffc48f399..9231d2f06 100644
--- a/lib/screens/v2/candidate_generator/busway.ex
+++ b/lib/screens/v2/candidate_generator/busway.ex
@@ -30,7 +30,7 @@ defmodule Screens.V2.CandidateGenerator.Busway do
end
@impl CandidateGenerator
- def candidate_instances(config, _opts, deps \\ %Deps{}) do
+ def candidate_instances(config, deps \\ %Deps{}) do
now = deps.now.()
[
diff --git a/lib/screens/v2/candidate_generator/dup.ex b/lib/screens/v2/candidate_generator/dup.ex
index 9bba80765..2e3d8bb7b 100644
--- a/lib/screens/v2/candidate_generator/dup.ex
+++ b/lib/screens/v2/candidate_generator/dup.ex
@@ -76,7 +76,6 @@ defmodule Screens.V2.CandidateGenerator.Dup do
@impl CandidateGenerator
def candidate_instances(
config,
- _opts,
now \\ DateTime.utc_now(),
fetch_stop_name_fn \\ &Stop.fetch_stop_name/1,
evergreen_content_instances_fn \\ &Widgets.Evergreen.evergreen_content_instances/1,
diff --git a/lib/screens/v2/candidate_generator/dup_new.ex b/lib/screens/v2/candidate_generator/dup_new.ex
index b603e7857..a2cc9d898 100644
--- a/lib/screens/v2/candidate_generator/dup_new.ex
+++ b/lib/screens/v2/candidate_generator/dup_new.ex
@@ -11,7 +11,7 @@ defmodule Screens.V2.CandidateGenerator.DupNew do
defdelegate screen_template(), to: DupBase
@impl CandidateGenerator
- def candidate_instances(_config, _opts) do
+ def candidate_instances(_config) do
List.duplicate(
%Placeholder{
color: :gray,
diff --git a/lib/screens/v2/candidate_generator/gl_eink.ex b/lib/screens/v2/candidate_generator/gl_eink.ex
index b81beead3..4bdeffc0f 100644
--- a/lib/screens/v2/candidate_generator/gl_eink.ex
+++ b/lib/screens/v2/candidate_generator/gl_eink.ex
@@ -78,7 +78,6 @@ defmodule Screens.V2.CandidateGenerator.GlEink do
@impl CandidateGenerator
def candidate_instances(
config,
- _opts,
now \\ DateTime.utc_now(),
fetch_destination_fn \\ &fetch_destination/2,
departures_instances_fn \\ &Widgets.Departures.departures_instances/3,
diff --git a/lib/screens/v2/candidate_generator/pre_fare.ex b/lib/screens/v2/candidate_generator/pre_fare.ex
index 0e89b9eea..f3a715f19 100644
--- a/lib/screens/v2/candidate_generator/pre_fare.ex
+++ b/lib/screens/v2/candidate_generator/pre_fare.ex
@@ -64,7 +64,6 @@ defmodule Screens.V2.CandidateGenerator.PreFare do
# credo:disable-for-next-line
def candidate_instances(
config,
- _opts,
now \\ DateTime.utc_now(),
subway_status_instance_fn \\ &Widgets.SubwayStatus.subway_status_instances/2,
reconstructed_alert_instances_fn \\ &Widgets.ReconstructedAlert.reconstructed_alert_instances/1,
diff --git a/lib/screens/v2/candidate_generator/solari_large.ex b/lib/screens/v2/candidate_generator/solari_large.ex
index 8b68d6907..37593bbf7 100644
--- a/lib/screens/v2/candidate_generator/solari_large.ex
+++ b/lib/screens/v2/candidate_generator/solari_large.ex
@@ -25,7 +25,6 @@ defmodule Screens.V2.CandidateGenerator.SolariLarge do
# credo:disable-for-next-line Credo.Check.Design.DuplicatedCode
def candidate_instances(
config,
- _opts,
now \\ DateTime.utc_now(),
departures_instances_fn \\ &Widgets.Departures.departures_instances/2
) do
diff --git a/lib/screens/v2/candidate_generator/triptych.ex b/lib/screens/v2/candidate_generator/triptych.ex
deleted file mode 100644
index f27a9dda2..000000000
--- a/lib/screens/v2/candidate_generator/triptych.ex
+++ /dev/null
@@ -1,39 +0,0 @@
-defmodule Screens.V2.CandidateGenerator.Triptych do
- @moduledoc false
-
- alias Screens.V2.CandidateGenerator
- alias Screens.V2.CandidateGenerator.Widgets
- alias Screens.V2.Template.Builder
-
- @behaviour CandidateGenerator
-
- @impl CandidateGenerator
- def screen_template do
- {:screen,
- %{
- screen_normal: [:full_screen],
- screen_split: [:left_pane, :middle_pane, :right_pane]
- }}
- |> Builder.build_template()
- end
-
- @impl CandidateGenerator
- def candidate_instances(
- config,
- opts,
- crowding_widget_instances_fn \\ &Widgets.TrainCrowding.crowding_widget_instances/2,
- evergreen_content_instances_fn \\ &Widgets.Evergreen.evergreen_content_instances/1,
- local_evergreen_set_instances_fn \\ &Widgets.LocalEvergreenSet.local_evergreen_set_instances/1
- ) do
- [
- fn -> crowding_widget_instances_fn.(config, opts[:logging_options]) end,
- fn -> evergreen_content_instances_fn.(config) end,
- fn -> local_evergreen_set_instances_fn.(config) end
- ]
- |> Task.async_stream(& &1.(), timeout: 20_000)
- |> Enum.flat_map(fn {:ok, instances} -> instances end)
- end
-
- @impl CandidateGenerator
- def audio_only_instances(_widgets, _config), do: []
-end
diff --git a/lib/screens/v2/candidate_generator/widgets/evergreen.ex b/lib/screens/v2/candidate_generator/widgets/evergreen.ex
index 7c0e1c13e..bb1078ec3 100644
--- a/lib/screens/v2/candidate_generator/widgets/evergreen.ex
+++ b/lib/screens/v2/candidate_generator/widgets/evergreen.ex
@@ -5,13 +5,13 @@ defmodule Screens.V2.CandidateGenerator.Widgets.Evergreen do
alias Screens.V2.WidgetInstance.EvergreenContent
alias ScreensConfig.Screen
alias ScreensConfig.V2.EvergreenContentItem
- alias ScreensConfig.V2.{BusEink, BusShelter, Dup, GlEink, PreFare, Triptych}
+ alias ScreensConfig.V2.{BusEink, BusShelter, Dup, GlEink, PreFare}
def evergreen_content_instances(
%Screen{app_params: %app{evergreen_content: evergreen_content}} = config,
now \\ DateTime.utc_now()
)
- when app in [BusEink, BusShelter, Dup, GlEink, PreFare, Triptych] do
+ when app in [BusEink, BusShelter, Dup, GlEink, PreFare] do
Enum.map(evergreen_content, &evergreen_content_instance(&1, config, now))
end
diff --git a/lib/screens/v2/candidate_generator/widgets/local_evergreen_set.ex b/lib/screens/v2/candidate_generator/widgets/local_evergreen_set.ex
deleted file mode 100644
index cc7e213ed..000000000
--- a/lib/screens/v2/candidate_generator/widgets/local_evergreen_set.ex
+++ /dev/null
@@ -1,104 +0,0 @@
-defmodule Screens.V2.CandidateGenerator.Widgets.LocalEvergreenSet do
- @moduledoc """
- Widget for displaying evergreen content that is stored internally.
- Additionally, allows us to set a group of PSAs that appear in conjunction.
- Currently used only by Triptychs, which randomizes which PSA set appears.
- """
-
- require Logger
-
- alias Screens.V2.WidgetInstance.EvergreenContent
- alias ScreensConfig.Screen
- alias ScreensConfig.V2.{LocalEvergreenSet, Triptych}
-
- def local_evergreen_set_instances(
- %Screen{app_params: %app{local_evergreen_sets: local_evergreen_sets}} = config,
- now \\ DateTime.utc_now()
- )
- when app in [Triptych] do
- # Use the current time to help seed the random number generator so that all 3 screens
- # should be in sync. So we'll seed with current time rounded down to the nearest multiple of 15 seconds.
- # (Known risk: it's remotely possible that the screens are panels are out-of-sync on either side of a 15-second boundary)
- seed_number =
- now
- |> DateTime.truncate(:second)
- |> DateTime.to_unix()
- |> div(15)
-
- _ = :rand.seed(:exsss, {seed_number, seed_number, seed_number})
-
- local_evergreen_sets
- |> Enum.random()
- |> get_set_instances(config, now)
- end
-
- def string_to_slot_name(string) do
- cond do
- String.contains?(string, "left") -> :left_pane
- String.contains?(string, "middle") -> :middle_pane
- String.contains?(string, "right") -> :right_pane
- end
- end
-
- defp get_set_instances(
- %LocalEvergreenSet{
- folder_name: folder_name,
- schedule: schedule
- },
- config,
- now
- ) do
- relative_path = Path.join("triptych_psas/", folder_name)
- path = Path.join("assets/static/images/", relative_path)
-
- case File.ls(path) do
- {:ok, files} ->
- build_widget_instances(files, config, relative_path, schedule, now)
-
- {:error, _} ->
- relative_path = "triptych_psas/"
- path = Path.join("assets/static/images/", relative_path)
-
- case File.ls(path) do
- {:ok, triptych_psa_contents} ->
- default_psa_folder = hd(triptych_psa_contents)
- default_psa_path = Path.join(path, default_psa_folder)
-
- Logger.warning(
- "[Triptych PSA filepath not found, using default] configured_folder_name=#{folder_name} default_folder_name=#{default_psa_folder}"
- )
-
- files = File.ls!(default_psa_path)
-
- build_widget_instances(
- files,
- config,
- Path.join(relative_path, default_psa_folder),
- schedule,
- now
- )
-
- {:error, _} ->
- Logger.warning("[Empty triptych PSA folder]")
- []
- end
- end
- end
-
- defp build_widget_instances(files, config, partial_path, schedule, now) do
- Enum.map(files, fn file ->
- slot_name = string_to_slot_name(file)
-
- %EvergreenContent{
- screen: config,
- slot_names: [slot_name],
- asset_url: Path.join([partial_path, "/", file]),
- priority: [2],
- schedule: schedule,
- now: now,
- text_for_audio: "",
- audio_priority: [0]
- }
- end)
- end
-end
diff --git a/lib/screens/v2/candidate_generator/widgets/train_crowding.ex b/lib/screens/v2/candidate_generator/widgets/train_crowding.ex
deleted file mode 100644
index 7223607da..000000000
--- a/lib/screens/v2/candidate_generator/widgets/train_crowding.ex
+++ /dev/null
@@ -1,349 +0,0 @@
-defmodule Screens.V2.CandidateGenerator.Widgets.TrainCrowding do
- @moduledoc false
-
- require Logger
-
- alias Screens.Alerts.Alert
- alias Screens.OlCrowding.Agent
- alias Screens.Predictions.Prediction
- alias Screens.Stops.Stop
- alias Screens.Util
- alias Screens.V2.LocalizedAlert
- alias Screens.V2.WidgetInstance.TrainCrowding, as: CrowdingWidget
- alias ScreensConfig.Screen
- alias ScreensConfig.V2.{TrainCrowding, Triptych}
-
- # {parent_station_id, {sb_platform_id, nb_platform_id}}
- @ol_station_to_platform_map [
- {"place-ogmnl", {"70036", "70036"}},
- {"place-mlmnl", {"70034", "70035"}},
- {"place-welln", {"70032", "70033"}},
- {"place-astao", {"70278", "70279"}},
- {"place-sull", {"70030", "70031"}},
- {"place-ccmnl", {"70028", "70029"}},
- {"place-north", {"70026", "70027"}},
- {"place-haecl", {"70024", "70025"}},
- {"place-state", {"70022", "70023"}},
- {"place-dwnxg", {"70020", "70021"}},
- {"place-chncl", {"70018", "70019"}},
- {"place-tumnl", {"70016", "70017"}},
- {"place-bbsta", {"70014", "70015"}},
- {"place-masta", {"70012", "70013"}},
- {"place-rugg", {"70010", "70011"}},
- {"place-rcmnl", {"70008", "70009"}},
- {"place-jaksn", {"70006", "70007"}},
- {"place-sbmnl", {"70004", "70005"}},
- {"place-grnst", {"70002", "70003"}},
- {"place-forhl", {"70001", "70001"}}
- ]
-
- @spec crowding_widget_instances(Screen.t(), map()) :: list(CrowdingWidget.t())
- def crowding_widget_instances(
- config,
- logging_options,
- now \\ DateTime.utc_now(),
- fetch_predictions_fn \\ &Prediction.fetch/1,
- fetch_location_context_fn \\ &Stop.fetch_location_context/3,
- fetch_parent_stop_id_fn \\ &Stop.fetch_parent_stop_id/1,
- fetch_alerts_fn \\ &Alert.fetch/1
- )
-
- def crowding_widget_instances(
- %Screen{app_params: %Triptych{train_crowding: %TrainCrowding{enabled: false}}},
- _,
- _,
- _,
- _,
- _,
- _
- ) do
- []
- end
-
- def crowding_widget_instances(
- %Screen{app_params: %Triptych{train_crowding: train_crowding}} = config,
- logging_options,
- now,
- fetch_predictions_fn,
- fetch_location_context_fn,
- fetch_parent_stop_id_fn,
- fetch_alerts_fn
- ) do
- params = %{
- direction_id: train_crowding.direction_id,
- route_ids: [train_crowding.route_id],
- stop_ids: [train_crowding.station_id]
- }
-
- with {:ok, predictions} <- fetch_predictions_fn.(params),
- {:ok, location_context} <-
- fetch_location_context_fn.(Triptych, train_crowding.station_id, now),
- {:ok, alerts} <-
- params |> Map.to_list() |> fetch_alerts_fn.() do
- next_train_prediction = List.first(predictions)
-
- if next_train_prediction && logging_options && logging_options.is_real_screen do
- Logger.info(
- "[train_crowding next_prediction] screen_id=#{logging_options.screen_id} triptych_pane=#{logging_options.triptych_pane} next_trip_id=#{next_train_prediction.trip.id}"
- )
- end
-
- common_params = %{
- screen_config: config,
- next_train_prediction: next_train_prediction,
- train_crowding_config: train_crowding,
- logging_options: logging_options,
- fetch_parent_stop_id_fn: fetch_parent_stop_id_fn,
- fetch_predictions_fn: fetch_predictions_fn,
- fetch_params: params,
- now: now
- }
-
- get_instance(
- any_alert_makes_this_a_terminal?(alerts, location_context, now),
- common_params
- )
- else
- :error -> []
- end
- end
-
- defp get_instance(
- alert_makes_this_a_terminal,
- common_params
- )
- when alert_makes_this_a_terminal or is_nil(common_params.next_train_prediction) or
- common_params.next_train_prediction == [],
- do: []
-
- defp get_instance(
- _alert_makes_this_a_terminal,
- common_params
- ) do
- next_train_prediction = common_params.next_train_prediction
-
- # If there is an upcoming train, it's headed to this station,
- # and we're not at a temporary terminal, log the widget.
- if Prediction.vehicle_status(next_train_prediction) in [:in_transit_to, :incoming_at] and
- next_train_prediction
- |> Prediction.stop_for_vehicle()
- |> common_params.fetch_parent_stop_id_fn.() ==
- common_params.train_crowding_config.station_id do
- _ = log_crowding_info(:in_transit, common_params)
-
- Agent.delete(
- common_params.train_crowding_config.station_id,
- common_params.train_crowding_config.direction_id
- )
-
- [
- %CrowdingWidget{
- screen: common_params[:screen_config],
- prediction: next_train_prediction,
- now: common_params[:now]
- }
- ]
-
- # Test other heuristics
- else
- log_heuristics(common_params)
- end
- end
-
- defp log_heuristics(common_params) do
- train_crowding_config = common_params.train_crowding_config
- next_train_prediction = common_params.next_train_prediction
-
- ol_stop_sequence =
- if train_crowding_config.direction_id == 0 do
- @ol_station_to_platform_map
- else
- Enum.reverse(@ol_station_to_platform_map)
- end
-
- previous_stop_index =
- Enum.find_index(
- ol_stop_sequence,
- &(elem(&1, 0) == train_crowding_config.station_id)
- ) - 1
-
- {_, platform_id_tuple} = Enum.at(ol_stop_sequence, previous_stop_index)
-
- previous_platform_id = elem(platform_id_tuple, train_crowding_config.direction_id)
-
- cached_prediction =
- Agent.get(train_crowding_config.station_id, train_crowding_config.direction_id)
-
- cond do
- cached_prediction != nil ->
- # Time-based heuristic
- # We think the train is about to leave the previous station. Log the heuristic.
- _ = check_time_based_heuristic(cached_prediction, common_params, -10)
-
- # Consecutive crowding class heuristic.
- # Crowding class this fetch is the same as last. Log the heuristic.
- _ =
- check_consecutive_crowding_heuristic(
- next_train_prediction,
- previous_platform_id,
- cached_prediction,
- common_params
- )
-
- []
-
- # Cache previous prediction but don't log the widget
- Prediction.vehicle_status(next_train_prediction) == :stopped_at and
- Prediction.stop_for_vehicle(next_train_prediction) == previous_platform_id ->
- previous_station_prediction_current_trip =
- fetch_previous_station_prediction(
- train_crowding_config,
- previous_platform_id,
- next_train_prediction.trip.id,
- common_params.fetch_predictions_fn
- )
-
- if is_nil(previous_station_prediction_current_trip) do
- Logger.warning(
- "[log_heuristics] Failed to fetch previous station's prediction: current_platform_id: #{train_crowding_config.station_id} previous_platform_id: #{previous_platform_id} trip_id: #{next_train_prediction.trip.id}"
- )
-
- []
- else
- # Cache the prediction for the current trip at the previous station.
- Agent.put(
- train_crowding_config.station_id,
- train_crowding_config.direction_id,
- previous_station_prediction_current_trip
- )
-
- []
- end
-
- true ->
- []
- end
- end
-
- defp fetch_previous_station_prediction(
- train_crowding_config,
- relevant_platform_id,
- trip_id,
- fetch_predictions_fn
- ) do
- params = %{
- direction_id: train_crowding_config.direction_id,
- route_ids: [train_crowding_config.route_id],
- stop_ids: [relevant_platform_id],
- trip_id: trip_id
- }
-
- {:ok, predictions} = fetch_predictions_fn.(params)
- List.first(predictions)
- end
-
- defp check_time_based_heuristic(
- cached_prediction,
- common_params,
- previous_departure_time_cushion
- ) do
- # cached_prediction.departure_time minus previous_departure_time_cushion is when we expect crowding to be reliable.
- # When now >= this time, log the widget.
- log_widget_after_time =
- DateTime.add(cached_prediction.departure_time, previous_departure_time_cushion)
-
- if DateTime.compare(
- common_params.now,
- log_widget_after_time
- ) in [
- :eq,
- :gt
- ] do
- log_crowding_info(
- :time_based,
- common_params
- )
- end
- end
-
- defp check_consecutive_crowding_heuristic(
- next_train_prediction,
- relevant_platform_id,
- cached_prediction,
- common_params
- ) do
- if next_train_prediction.vehicle.carriages ==
- cached_prediction.vehicle.carriages do
- log_crowding_info(
- :consecutive_crowding,
- common_params
- )
- else
- # Update the cached prediction so we can check the new crowding classes next fetch.
- # The departure time we use in the other heuristic should not change, and if it does it is changing to a more accurate time.
- # If the prediction is nil, leave the existing one alone just in case the time heuristic can log next refresh.
- previous_station_prediction_current_trip =
- fetch_previous_station_prediction(
- common_params.train_crowding_config,
- relevant_platform_id,
- next_train_prediction.trip.id,
- common_params.fetch_predictions_fn
- )
-
- if previous_station_prediction_current_trip != nil do
- Agent.put(
- common_params.train_crowding_config.station_id,
- common_params.train_crowding_config.direction_id,
- previous_station_prediction_current_trip
- )
- end
- end
- end
-
- # Given alerts at this station, check to see if any alert make this a temporary terminal
- defp any_alert_makes_this_a_terminal?(alerts, location_context, now) do
- Enum.any?(alerts, fn alert ->
- if Alert.happening_now?(alert, now) do
- temporary_terminal?(%{alert: alert, location_context: location_context})
- end
- end)
- end
-
- # credo:disable-for-next-line
- # TODO: This isn't the first time we've written a temporary_terminal function, but this one
- # is a little more reusable? Consider using this func in other places
- defp temporary_terminal?(localized_alert) do
- localized_alert.alert.effect in [:suspension, :shuttle] and
- LocalizedAlert.location(localized_alert) in [:boundary_downstream, :boundary_upstream]
- end
-
- defp log_crowding_info(
- scenario,
- %{
- next_train_prediction: prediction,
- train_crowding_config: train_crowding_config,
- logging_options: %{
- is_real_screen: true,
- screen_id: screen_id,
- triptych_pane: triptych_pane
- }
- } = common_params
- ) do
- Agent.delete(train_crowding_config.station_id, train_crowding_config.direction_id)
-
- crowding_levels =
- Enum.map_join(
- prediction.vehicle.carriages,
- ",",
- &Util.translate_carriage_occupancy_status/1
- )
-
- Logger.info(
- "[train_crowding car_crowding_info] screen_id=#{screen_id} triptych_pane=#{triptych_pane} trip_id=#{prediction.trip.id} car_crowding_levels=#{crowding_levels} scenario=#{scenario}"
- )
-
- Screens.OlCrowding.DynamicSupervisor.start_logger(crowding_levels, common_params)
- end
-
- defp log_crowding_info(_, _), do: :ok
-end
diff --git a/lib/screens/v2/screen_data.ex b/lib/screens/v2/screen_data.ex
index 5f754a95d..68263b8c1 100644
--- a/lib/screens/v2/screen_data.ex
+++ b/lib/screens/v2/screen_data.ex
@@ -26,7 +26,6 @@ defmodule Screens.V2.ScreenData do
@type variants(data) :: {data, %{String.t() => data}}
@type screen_id :: String.t()
@type options :: [
- logging_options: %{atom() => term()},
generator_variant: String.t(),
pending_config: Screen.t(),
run_all_variants?: boolean(),
@@ -69,13 +68,13 @@ defmodule Screens.V2.ScreenData do
Enum.each(other_variants, fn variant ->
{:ok, _pid} =
Task.Supervisor.start_child(ParallelRunSupervisor, fn ->
- config |> Layout.generate(variant, opts) |> then_fn.(config)
+ config |> Layout.generate(variant) |> then_fn.(config)
end)
end)
end
config
- |> Layout.generate(selected_variant, opts)
+ |> Layout.generate(selected_variant)
|> tap(&update_visible_alerts(&1, screen_id, config, opts))
|> then_fn.(config)
end
@@ -90,7 +89,7 @@ defmodule Screens.V2.ScreenData do
|> Task.Supervisor.async_stream(
[nil | @parameters.get_variants(config)],
fn variant ->
- {variant, config |> Layout.generate(variant, opts) |> then_fn.(config)}
+ {variant, config |> Layout.generate(variant) |> then_fn.(config)}
end
)
|> Enum.map(fn {:ok, result} -> result end)
diff --git a/lib/screens/v2/screen_data/layout.ex b/lib/screens/v2/screen_data/layout.ex
index e5697b630..c09b0cc5e 100644
--- a/lib/screens/v2/screen_data/layout.ex
+++ b/lib/screens/v2/screen_data/layout.ex
@@ -32,13 +32,12 @@ defmodule Screens.V2.ScreenData.Layout do
@spec generate(Screen.t()) :: t()
@spec generate(Screen.t(), String.t() | nil) :: t()
- @spec generate(Screen.t(), String.t() | nil, keyword()) :: t()
- def generate(config, variant \\ nil, candidate_generator_opts \\ []) do
+ def generate(config, variant \\ nil) do
candidate_generator = @parameters.get_candidate_generator(config, variant)
screen_template = candidate_generator.screen_template()
config
- |> candidate_generator.candidate_instances(candidate_generator_opts)
+ |> candidate_generator.candidate_instances()
|> Enum.filter(&WidgetInstance.valid_candidate?/1)
|> pick_instances(screen_template)
end
diff --git a/lib/screens/v2/screen_data/parameters.ex b/lib/screens/v2/screen_data/parameters.ex
index 1cbc2f55c..4f28705a0 100644
--- a/lib/screens/v2/screen_data/parameters.ex
+++ b/lib/screens/v2/screen_data/parameters.ex
@@ -13,8 +13,7 @@ defmodule Screens.V2.ScreenData.Parameters do
dup_v2: {
CandidateGenerator.Dup,
%{"new_departures" => CandidateGenerator.DupNew}
- },
- triptych_v2: CandidateGenerator.Triptych
+ }
}
@app_id_to_refresh_rate %{
@@ -24,8 +23,7 @@ defmodule Screens.V2.ScreenData.Parameters do
busway_v2: 15,
solari_large_v2: 15,
pre_fare_v2: 20,
- dup_v2: 30,
- triptych_v2: 30
+ dup_v2: 30
}
@app_id_to_audio_readout_interval %{
@@ -35,8 +33,7 @@ defmodule Screens.V2.ScreenData.Parameters do
busway_v2: 0,
solari_large_v2: 0,
pre_fare_v2: 0,
- dup_v2: 0,
- triptych_v2: 0
+ dup_v2: 0
}
@callback get_candidate_generator(ScreensConfig.Screen.t()) :: module()
diff --git a/lib/screens/v2/widget_instance/evergreen_content.ex b/lib/screens/v2/widget_instance/evergreen_content.ex
index 788510fc5..c4e84e186 100644
--- a/lib/screens/v2/widget_instance/evergreen_content.ex
+++ b/lib/screens/v2/widget_instance/evergreen_content.ex
@@ -4,7 +4,7 @@ defmodule Screens.V2.WidgetInstance.EvergreenContent do
alias Screens.Util
alias Screens.V2.WidgetInstance
alias ScreensConfig.Screen
- alias ScreensConfig.V2.{RecurrentSchedule, Schedule, Triptych}
+ alias ScreensConfig.V2.{RecurrentSchedule, Schedule}
@enforce_keys ~w[screen slot_names asset_url priority now]a
defstruct screen: nil,
@@ -14,8 +14,7 @@ defmodule Screens.V2.WidgetInstance.EvergreenContent do
schedule: [%Schedule{}],
now: nil,
text_for_audio: nil,
- audio_priority: nil,
- show_identifiers: false
+ audio_priority: nil
@type t :: %__MODULE__{
screen: Screen.t(),
@@ -25,18 +24,11 @@ defmodule Screens.V2.WidgetInstance.EvergreenContent do
schedule: list(Schedule.t()) | RecurrentSchedule.t(),
now: DateTime.t(),
text_for_audio: String.t(),
- audio_priority: WidgetInstance.priority(),
- show_identifiers: boolean()
+ audio_priority: WidgetInstance.priority()
}
def priority(%__MODULE__{} = instance), do: instance.priority
- def serialize(%__MODULE__{
- screen: %Screen{app_params: %Triptych{show_identifiers: show_identifiers}},
- asset_url: asset_url
- }),
- do: %{asset_url: asset_url, show_identifiers: show_identifiers}
-
def serialize(%__MODULE__{asset_url: asset_url}), do: %{asset_url: asset_url}
def slot_names(%__MODULE__{slot_names: slot_names}), do: slot_names
diff --git a/lib/screens/v2/widget_instance/train_crowding.ex b/lib/screens/v2/widget_instance/train_crowding.ex
deleted file mode 100644
index 7cb74e766..000000000
--- a/lib/screens/v2/widget_instance/train_crowding.ex
+++ /dev/null
@@ -1,96 +0,0 @@
-defmodule Screens.V2.WidgetInstance.TrainCrowding do
- @moduledoc """
- A widget that displays the crowding on a train that is en route to the current station.
- """
-
- alias Screens.Predictions.Prediction
- alias Screens.Util
- alias ScreensConfig.Screen
- alias ScreensConfig.V2.Triptych
-
- defstruct screen: nil,
- prediction: nil,
- now: nil
-
- @type t :: %__MODULE__{
- screen: Screen.t(),
- prediction: Prediction.t(),
- now: DateTime.t()
- }
-
- @type widget_data :: %{
- destination: String.t(),
- crowding: list(crowding_level),
- # Describes where the "you are here" arrow should be positioned.
- # 1: leftmost, 25: rightmost
- platform_position: 1..25,
- front_car_direction: :left | :right,
- now: String.t(),
- show_identifiers: boolean()
- }
-
- @type crowding_level :: :no_data | :not_crowded | :some_crowding | :crowded | :closed
-
- @spec serialize(t()) :: widget_data()
- def serialize(%__MODULE__{
- screen: %Screen{
- app_params: %Triptych{
- train_crowding: train_crowding,
- show_identifiers: show_identifiers
- }
- },
- prediction: prediction,
- now: now
- }) do
- %{
- destination: prediction.trip.headsign,
- crowding: serialize_carriages(prediction.vehicle.carriages),
- platform_position: train_crowding.platform_position,
- front_car_direction: train_crowding.front_car_direction,
- now: serialize_time(now),
- show_identifiers: show_identifiers
- }
- end
-
- defp serialize_time(%DateTime{} = time) do
- DateTime.to_iso8601(time)
- end
-
- defp serialize_carriages(nil), do: nil
-
- defp serialize_carriages(carriages),
- do:
- Enum.map(
- carriages,
- &Util.translate_carriage_occupancy_status/1
- )
-
- def priority(_instance), do: [1]
-
- def slot_names(_instance), do: [:full_screen]
-
- def widget_type(_instance), do: :train_crowding
-
- def valid_candidate?(_instance), do: true
-
- ### Required audio callbacks. The widget does not have audio equivalence, so these are "stubbed".
- def audio_serialize(_t), do: %{}
- def audio_sort_key(_t), do: [0]
- def audio_valid_candidate?(_t), do: false
- def audio_view(_t), do: nil
-
- defimpl Screens.V2.WidgetInstance do
- alias Screens.V2.WidgetInstance.TrainCrowding
-
- def priority(instance), do: TrainCrowding.priority(instance)
- def serialize(instance), do: TrainCrowding.serialize(instance)
- def slot_names(instance), do: TrainCrowding.slot_names(instance)
- def widget_type(instance), do: TrainCrowding.widget_type(instance)
- def valid_candidate?(instance), do: TrainCrowding.valid_candidate?(instance)
-
- def audio_serialize(instance), do: TrainCrowding.audio_serialize(instance)
- def audio_sort_key(instance), do: TrainCrowding.audio_sort_key(instance)
- def audio_valid_candidate?(instance), do: TrainCrowding.audio_valid_candidate?(instance)
- def audio_view(instance), do: TrainCrowding.audio_view(instance)
- end
-end
diff --git a/lib/screens_web/controllers/admin_api_controller.ex b/lib/screens_web/controllers/admin_api_controller.ex
index 235313092..2daf3e74c 100644
--- a/lib/screens_web/controllers/admin_api_controller.ex
+++ b/lib/screens_web/controllers/admin_api_controller.ex
@@ -4,8 +4,6 @@ defmodule ScreensWeb.AdminApiController do
alias Screens.Config.Cache, as: ConfigCache
alias Screens.Config.Fetch, as: ConfigFetch
alias Screens.Image
- alias Screens.TriptychPlayer
- alias Screens.TriptychPlayer.Fetch, as: TriptychPlayerFetch
alias ScreensConfig.{Config, Devops, Screen}
plug :accepts, ["multipart/form-data"] when action == :upload_image
@@ -61,36 +59,6 @@ defmodule ScreensWeb.AdminApiController do
json(conn, %{success: success})
end
- def index_triptych_players(conn, _params) do
- {:ok, mapping, _version} = TriptychPlayerFetch.fetch_config()
- json(conn, %{config: mapping})
- end
-
- def validate_triptych_players(conn, %{"config" => config}) do
- with {:ok, mapping} <- Jason.decode(config),
- :ok <- TriptychPlayer.validate(mapping) do
- json(conn, %{success: true, config: mapping})
- else
- {:error, message} when is_binary(message) ->
- json(conn, %{success: false, message: message})
-
- {:error, jason_exception} when is_exception(jason_exception) ->
- json(conn, %{success: false, message: Exception.message(jason_exception)})
- end
- end
-
- def confirm_triptych_players(conn, %{"config" => config}) do
- pretty_json = config |> Jason.decode!() |> Jason.encode!(pretty: true)
-
- success =
- case TriptychPlayerFetch.put_config(pretty_json) do
- :ok -> true
- :error -> false
- end
-
- json(conn, %{success: success})
- end
-
def devops(conn, %{"disabled_modes" => _disabled_modes} = json) do
current_screens_config = ConfigCache.screens()
new_devops_config = Devops.from_json(json)
diff --git a/lib/screens_web/controllers/v2/screen_api_controller.ex b/lib/screens_web/controllers/v2/screen_api_controller.ex
index b720a63cd..b63b523c8 100644
--- a/lib/screens_web/controllers/v2/screen_api_controller.ex
+++ b/lib/screens_web/controllers/v2/screen_api_controller.ex
@@ -14,7 +14,7 @@ defmodule ScreensWeb.V2.ScreenApiController do
plug(:check_config)
- plug Corsica, [origins: "*"] when action in [:show_dup, :show_triptych, :log_frontend_error]
+ plug Corsica, [origins: "*"] when action in [:show_dup, :log_frontend_error]
defp check_config(conn, _) do
if Cache.ok?() do
@@ -29,7 +29,6 @@ defmodule ScreensWeb.V2.ScreenApiController do
def show(conn, %{"id" => screen_id, "last_refresh" => last_refresh} = params) do
is_screen = ScreensWeb.UserAgent.screen_conn?(conn, screen_id)
screen_side = params["screen_side"]
- triptych_pane = params["pane"]
variant = params["variant"]
screen = Cache.screen(screen_id)
@@ -85,15 +84,7 @@ defmodule ScreensWeb.V2.ScreenApiController do
response =
screen_id
- |> screen_response(variant,
- run_all_variants?: true,
- update_visible_alerts?: true,
- logging_options: %{
- is_real_screen: is_screen,
- screen_id: screen_id,
- triptych_pane: triptych_pane
- }
- )
+ |> screen_response(variant, run_all_variants?: true, update_visible_alerts?: true)
|> put_extra_fields(screen_id, screen)
json(conn, response)
@@ -135,21 +126,6 @@ defmodule ScreensWeb.V2.ScreenApiController do
def show_dup(conn, params), do: show(conn, params)
- def show_triptych(conn, %{"player_name" => player_name} = params) do
- case Screens.TriptychPlayer.fetch_screen_id_for_player(player_name) do
- {:ok, screen_id} ->
- show(conn, Map.put(params, "id", screen_id))
-
- :error ->
- LogScreenData.log_unrecognized_triptych_player(player_name)
-
- # Reuse the logic + logging in show/2 for nonexistent IDs.
- # This will log a data request for the nonexistent player name and
- # return a 404 response.
- show(conn, Map.put(params, "id", "triptych_player_name--#{player_name}"))
- end
- end
-
def simulation(conn, %{"id" => screen_id, "last_refresh" => last_refresh} = params) do
variant = params["variant"]
@@ -197,16 +173,7 @@ defmodule ScreensWeb.V2.ScreenApiController do
not_found_response(conn)
config ->
- screen_data =
- ScreenData.get(
- screen_id,
- pending_config: config,
- logging_options: %{
- is_real_screen: false,
- screen_id: screen_id,
- triptych_pane: "UNKNOWN"
- }
- )
+ screen_data = ScreenData.get(screen_id, pending_config: config)
json(conn, %{@base_response | data: screen_data})
end
diff --git a/lib/screens_web/controllers/v2/screen_controller.ex b/lib/screens_web/controllers/v2/screen_controller.ex
index 57f467adf..a89390659 100644
--- a/lib/screens_web/controllers/v2/screen_controller.ex
+++ b/lib/screens_web/controllers/v2/screen_controller.ex
@@ -6,7 +6,7 @@ defmodule ScreensWeb.V2.ScreenController do
alias ScreensConfig.Screen
@default_app_id :bus_eink
- @recognized_app_ids ~w[bus_eink_v2 bus_shelter_v2 busway_v2 dup_v2 gl_eink_v2 solari_large_v2 pre_fare_v2 triptych_v2]a
+ @recognized_app_ids ~w[bus_eink_v2 bus_shelter_v2 busway_v2 dup_v2 gl_eink_v2 solari_large_v2 pre_fare_v2]a
@app_id_strings Enum.map(@recognized_app_ids, &Atom.to_string/1)
plug(:check_config)
@@ -55,15 +55,6 @@ defmodule ScreensWeb.V2.ScreenController do
end
end
- defp triptych_pane(params) do
- case params["pane"] do
- "left" -> "left"
- "middle" -> "middle"
- "right" -> "right"
- _ -> nil
- end
- end
-
def index(conn, %{"id" => app_id})
when app_id in @app_id_strings do
app_id = String.to_existing_atom(app_id)
@@ -145,7 +136,6 @@ defmodule ScreensWeb.V2.ScreenController do
screen_side: screen_side(params),
requestor: params["requestor"],
rotation_index: rotation_index(params),
- triptych_pane: triptych_pane(params),
variant: params["variant"],
is_pending: false
]
diff --git a/lib/screens_web/router.ex b/lib/screens_web/router.ex
index 7710c9c7e..f5eff2aed 100644
--- a/lib/screens_web/router.ex
+++ b/lib/screens_web/router.ex
@@ -72,9 +72,6 @@ defmodule ScreensWeb.Router do
get "/image_filenames", AdminApiController, :image_filenames
post "/image", AdminApiController, :upload_image
delete "/image/:filename", AdminApiController, :delete_image
- get "/triptych_players", AdminApiController, :index_triptych_players
- post "/triptych_players/validate", AdminApiController, :validate_triptych_players
- post "/triptych_players/confirm", AdminApiController, :confirm_triptych_players
end
scope "/screen", ScreensWeb do
@@ -108,7 +105,6 @@ defmodule ScreensWeb.Router do
get "/:id/simulation", ScreenApiController, :simulation
get "/:id/dup", ScreenApiController, :show_dup
- get "/:player_name/triptych", ScreenApiController, :show_triptych
get "/pending/:id", ScreenApiController, :show_pending
get "/pending/:id/simulation", ScreenApiController, :simulation_pending
diff --git a/lib/screens_web/templates/v2/screen/index.html.eex b/lib/screens_web/templates/v2/screen/index.html.eex
index a5eb0dbc4..9618a7f6b 100644
--- a/lib/screens_web/templates/v2/screen/index.html.eex
+++ b/lib/screens_web/templates/v2/screen/index.html.eex
@@ -16,9 +16,6 @@
<%= if not is_nil(@rotation_index) do %>
data-rotation-index="<%= @rotation_index %>"
<% end %>
- <%= if not is_nil(@triptych_pane) do %>
- data-triptych-pane="<%= @triptych_pane %>"
- <% end %>
<%= if assigns[:screenplay_fullstory_org_id] do %>
data-screenplay-fullstory-org-id="<%= assigns[:screenplay_fullstory_org_id] %>"
<% end %>
diff --git a/mix.exs b/mix.exs
index 6251959e9..dc1335c2d 100644
--- a/mix.exs
+++ b/mix.exs
@@ -87,7 +87,7 @@ defmodule Screens.MixProject do
{:telemetry_metrics, "~> 0.4"},
{:screens_config,
git: "https://github.com/mbta/screens-config-lib.git",
- ref: "2c67758bca5ec61d08e4194aa19bf289cb4ec6ef"},
+ ref: "594c88ae0a4e9deb43697ab5e0567f1c97f19671"},
{:nebulex, "~> 2.6"},
{:remote_ip, "~> 1.2"},
{:hackney_telemetry, "~> 0.2.0"},
diff --git a/mix.lock b/mix.lock
index d714d14ba..d87cb94db 100644
--- a/mix.lock
+++ b/mix.lock
@@ -61,7 +61,7 @@
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
"remote_ip": {:hex, :remote_ip, "1.2.0", "fb078e12a44414f4cef5a75963c33008fe169b806572ccd17257c208a7bc760f", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "2ff91de19c48149ce19ed230a81d377186e4412552a597d6a5137373e5877cb7"},
"retry": {:hex, :retry, "0.18.0", "dc58ebe22c95aa00bc2459f9e0c5400e6005541cf8539925af0aa027dc860543", [:mix], [], "hexpm", "9483959cc7bf69c9e576d9dfb2b678b71c045d3e6f39ab7c9aa1489df4492d73"},
- "screens_config": {:git, "https://github.com/mbta/screens-config-lib.git", "2c67758bca5ec61d08e4194aa19bf289cb4ec6ef", [ref: "2c67758bca5ec61d08e4194aa19bf289cb4ec6ef"]},
+ "screens_config": {:git, "https://github.com/mbta/screens-config-lib.git", "594c88ae0a4e9deb43697ab5e0567f1c97f19671", [ref: "594c88ae0a4e9deb43697ab5e0567f1c97f19671"]},
"sentry": {:hex, :sentry, "10.7.1", "33392222d80ccff99c503f972998d2858b4c1e5aca2219a34269b68dacba8e7d", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_ownership, "~> 0.3.0 or ~> 1.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.6", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_live_view, "~> 0.20", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "56291312397bf2b6afab6cf4f7aa1f27413b0eb2ceeb63b8aab2d7658aaea882"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
"stream_data": {:hex, :stream_data, "1.1.1", "fd515ca95619cca83ba08b20f5e814aaf1e5ebff114659dc9731f966c9226246", [:mix], [], "hexpm", "45d0cd46bd06738463fd53f22b70042dbb58c384bb99ef4e7576e7bb7d3b8c8c"},
diff --git a/priv/triptych-app.html b/priv/triptych-app.html
deleted file mode 100644
index bc03999bd..000000000
--- a/priv/triptych-app.html
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
- Screens
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/priv/triptych_preview.png b/priv/triptych_preview.png
deleted file mode 100644
index 3630154e5..000000000
Binary files a/priv/triptych_preview.png and /dev/null differ
diff --git a/priv/triptych_template.json b/priv/triptych_template.json
deleted file mode 100644
index fe6c0a1b3..000000000
--- a/priv/triptych_template.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "templates": [
- {
- "displayName": "MBTA - TRIPTYCH APP",
- "preview": "triptych_preview.png",
- "indexTemplate": "triptych-app.html",
- "previewOrientation": "portrait"
- }
- ]
-}
diff --git a/scripts/build_triptych_config.ts b/scripts/build_triptych_config.ts
deleted file mode 100644
index c1cde44bf..000000000
--- a/scripts/build_triptych_config.ts
+++ /dev/null
@@ -1,292 +0,0 @@
-/**
- * This script provides some type checking and "spell-checking" on triptych config entries, and lets you skip duplicating all of the common bits of JSON.
- * To use, go to https://www.typescriptlang.org/play and paste this whole thing in, then hit "Run".
- * You may first need to click "TS Config" and set Target to ES2019 or later.
- *
- * The resulting JSON will be printed to the console. It will be an object with two top-level fields:
- * - `screenConfig`: the main configuration for all of the triptychs, to be merged into the contents of screens-(dev|dev-green|prod).json
- * - `playerNameMapping`: the mapping from player name to screen ID. This should be dropped into triptych-player-(dev|dev-green|prod).json
- *
- * To change the common parts of the config objects, e.g. to make train crowding widget enabled by default or add a new PSA set, edit the body of `makeScreenConfig`.
- */
-
-/**
- * ๐ IMPORTANT NOTES
- * ------------------
- * - Screen IDs are of the form `TRI-${StationName}-${routeID}-${directionID}-${index}`
- * - The last part, the `index`, starts at 1 for the triptych *nearest the front of the train*, and increments from there.
- * So, if the train travels right relative to this platform, the rightmost triptych along that platform has index 1.
- * If the train travels left, the leftmost triptych has index 1.
- * - Try to order the lists of 3 player names associated with each screen ID by left-middle-right.
- */
-
-type ConfigItemParams = [TriptychScreenID, DirID, CarDir, PlatformPosition, StationID, [string, string, string], string];
-
-// vvv Add items to this array vvv
-
-const getDraftConfigs = (): ConfigItemParams[] => [
- // MALDEN CENTER
- ["TRI-MaldenCenter-Orange-0-1", DirID.SB, CarDir.L, 6, "place-mlmnl", ["MAN-DS-001", "MAN-DS-002", "MAN-DS-003"], "Malden Center - OL Inbound 1"],
- ["TRI-MaldenCenter-Orange-0-2", DirID.SB, CarDir.L, 11, "place-mlmnl", ["MAN-DS-004", "MAN-DS-005", "MAN-DS-006"], "Malden Center - OL Inbound 2"],
- ["TRI-MaldenCenter-Orange-0-3", DirID.SB, CarDir.L, 16, "place-mlmnl", ["MAN-DS-007", "MAN-DS-008", "MAN-DS-009"], "Malden Center - OL Inbound 3"],
-
- // WELLINGTON
- ["TRI-Wellington-Orange-0-1", DirID.SB, CarDir.L, 22, "place-welln", ["WEL-DS-001", "WEL-DS-002", "WEL-DS-003"], "Wellington - OL Inbound 1"],
- ["TRI-Wellington-Orange-0-2", DirID.SB, CarDir.L, 23, "place-welln", ["WEL-DS-004", "WEL-DS-005", "WEL-DS-006"], "Wellington - OL Inbound 2"],
- ["TRI-Wellington-Orange-0-3", DirID.SB, CarDir.L, 25, "place-welln", ["WEL-DS-007", "WEL-DS-008", "WEL-DS-009"], "Wellington - OL Inbound 3"],
-
- // SULLIVAN SQUARE
- // ๐ฅ The station map doesn't seem to agree with the spreadsheet for Sullivan.
- // Station map has 01-02-03::left-middle-right, spreadsheet has 01-02-03::right-middle-left
- // We should check to confirm that the player name groupings are reflected accurately, and the panes (`Array_configuration`) are tagged correctly as left/middle/right.
- // If groupings are wrong, we could end up showing the "You are here" arrow in the wrong place, or not at all.
- // If pane tags are wrong, we could end up showing left pane content on the right and vice versa.
- ["TRI-SullivanSquare-Orange-0-1", DirID.SB, CarDir.L, 9, "place-sull", ["SSQ-DS-004", "SSQ-DS-005", "SSQ-DS-006"], "Sullivan Square - OL Inbound 1"],
- ["TRI-SullivanSquare-Orange-0-2", DirID.SB, CarDir.L, 20, "place-sull", ["SSQ-DS-001", "SSQ-DS-002", "SSQ-DS-003"], "Sullivan Square - OL Inbound 2"],
-
- // NORTH STATION
- ["TRI-NorthStation-Orange-0-1", DirID.SB, CarDir.R, 22, "place-north", ["NST-DS-029", "NST-DS-028", "NST-DS-027"], "North Station - OL Inbound 1"],
- ["TRI-NorthStation-Orange-0-2", DirID.SB, CarDir.R, 16, "place-north", ["NST-DS-035", "NST-DS-034", "NST-DS-033"], "North Station - OL Inbound 2"],
- ["TRI-NorthStation-Orange-1-1", DirID.NB, CarDir.R, 10, "place-north", ["NST-DS-036", "NST-DS-037", "NST-DS-038"], "North Station - OL Outbound 1"],
- ["TRI-NorthStation-Orange-1-2", DirID.NB, CarDir.R, 4, "place-north", ["NST-DS-030", "NST-DS-031", "NST-DS-032"], "North Station - OL Outbound 2"],
-
- // HAYMARKET
- ["TRI-Haymarket-Orange-0-1", DirID.SB, CarDir.R, 16, "place-haecl", ["HAT-DS-003", "HAT-DS-002", "HAT-DS-001"], "Haymarket - OL Inbound 1"],
- ["TRI-Haymarket-Orange-0-2", DirID.SB, CarDir.R, 14, "place-haecl", ["HAT-DS-006", "HAT-DS-005", "HAT-DS-004"], "Haymarket - OL Inbound 2"],
- ["TRI-Haymarket-Orange-0-3", DirID.SB, CarDir.R, 12, "place-haecl", ["HAT-DS-009", "HAT-DS-008", "HAT-DS-007"], "Haymarket - OL Inbound 3"],
- ["TRI-Haymarket-Orange-1-1", DirID.NB, CarDir.R, 16, "place-haecl", ["HAT-DS-016", "HAT-DS-017", "HAT-DS-018"], "Haymarket - OL Outbound 1"],
- ["TRI-Haymarket-Orange-1-2", DirID.NB, CarDir.R, 14, "place-haecl", ["HAT-DS-013", "HAT-DS-014", "HAT-DS-015"], "Haymarket - OL Outbound 2"],
- ["TRI-Haymarket-Orange-1-3", DirID.NB, CarDir.R, 12, "place-haecl", ["HAT-DS-010", "HAT-DS-011", "HAT-DS-012"], "Haymarket - OL Outbound 3"],
-
- // STATE
- ["TRI-State-Orange-0-1", DirID.SB, CarDir.L, 10, "place-state", ["STS-DS-010", "STS-DS-011", "STS-DS-012"], "State - OL Inbound/Southbound 1"],
- ["TRI-State-Orange-0-2", DirID.SB, CarDir.L, 14, "place-state", ["STS-DS-013", "STS-DS-014", "STS-DS-015"], "State - OL Inbound/Southbound 2"],
- ["TRI-State-Orange-0-3", DirID.SB, CarDir.L, 22, "place-state", ["STS-DS-016", "STS-DS-017", "STS-DS-018"], "State - OL Inbound/Southbound 3"],
- ["TRI-State-Orange-1-1", DirID.NB, CarDir.R, 17, "place-state", ["STS-DS-007", "STS-DS-008", "STS-DS-009"], "State - OL Outbound/Northbound 1"],
- ["TRI-State-Orange-1-2", DirID.NB, CarDir.R, 10, "place-state", ["STS-DS-004", "STS-DS-005", "STS-DS-006"], "State - OL Outbound/Northbound 2"],
- ["TRI-State-Orange-1-3", DirID.NB, CarDir.R, 6, "place-state", ["STS-DS-001", "STS-DS-002", "STS-DS-003"], "State - OL Outbound/Northbound 3"],
-
- // DOWNTOWN CROSSING
- // NAME CHANGE: DTX / DTX
- // ๐ฅ Travel directions seem mislabeled on the station map for this one.
- // The tracks are also not labeled with their destinations.
- // We should double-check the triptychs at DTX to make sure they're properly configured.
- ["TRI-DTX-Orange-0-1", DirID.SB, CarDir.R, 20, "place-dwnxg", ["DOW-DS-009", "DOW-DS-008", "DOW-DS-007"], "DTX - OL Outbound/Southbound 1"],
- ["TRI-DTX-Orange-0-2", DirID.SB, CarDir.R, 12, "place-dwnxg", ["DOW-DS-030", "DOW-DS-029", "DOW-DS-028"], "DTX - OL Outbound/Southbound 2"],
- ["TRI-DTX-Orange-0-3", DirID.SB, CarDir.R, 3, "place-dwnxg", ["DOW-DS-012", "DOW-DS-011", "DOW-DS-010"], "DTX - OL Outbound/Southbound 3"],
- ["TRI-DTX-Orange-1-1", DirID.NB, CarDir.R, 18, "place-dwnxg", ["DOW-DS-025", "DOW-DS-026", "DOW-DS-027"], "DTX - OL Inbound/Northbound 1"],
- ["TRI-DTX-Orange-1-2", DirID.NB, CarDir.R, 9, "place-dwnxg", ["DOW-DS-004", "DOW-DS-005", "DOW-DS-006"], "DTX - OL Inbound/Northbound 2"],
- ["TRI-DTX-Orange-1-3", DirID.NB, CarDir.R, 3, "place-dwnxg", ["DOW-DS-001", "DOW-DS-002", "DOW-DS-003"], "DTX - OL Inbound/Northbound 3"],
-
- // TUFTS MEDICAL CENTER
- // NAME CHANGE: TuftsMed / Tufts Med
- ["TRI-TuftsMed-Orange-0-1", DirID.SB, CarDir.R, 21, "place-tumnl", ["NMC-DS-015", "NMC-DS-014", "NMC-DS-013"], "Tufts Med - OL Outbound 1"],
- ["TRI-TuftsMed-Orange-0-2", DirID.SB, CarDir.R, 10, "place-tumnl", ["NMC-DS-009", "NMC-DS-008", "NMC-DS-007"], "Tufts Med - OL Outbound 2"],
- ["TRI-TuftsMed-Orange-0-3", DirID.SB, CarDir.R, 5, "place-tumnl", ["NMC-DS-003", "NMC-DS-002", "NMC-DS-001"], "Tufts Med - OL Outbound 3"],
- ["TRI-TuftsMed-Orange-1-1", DirID.NB, CarDir.R, 21, "place-tumnl", ["NMC-DS-004", "NMC-DS-005", "NMC-DS-006"], "Tufts Med - OL Inbound 1"],
- ["TRI-TuftsMed-Orange-1-2", DirID.NB, CarDir.R, 16, "place-tumnl", ["NMC-DS-010", "NMC-DS-011", "NMC-DS-012"], "Tufts Med - OL Inbound 2"],
- ["TRI-TuftsMed-Orange-1-3", DirID.NB, CarDir.R, 5, "place-tumnl", ["NMC-DS-016", "NMC-DS-017", "NMC-DS-018"], "Tufts Med - OL Inbound 3"],
-
- // BACK BAY
- ["TRI-BackBay-Orange-0-1", DirID.SB, CarDir.L, 6, "place-bbsta", ["BKB-DS-001", "BKB-DS-002", "BKB-DS-003"], "Back Bay - OL Outbound 1"],
- ["TRI-BackBay-Orange-0-2", DirID.SB, CarDir.L, 12, "place-bbsta", ["BKB-DS-004", "BKB-DS-005", "BKB-DS-006"], "Back Bay - OL Outbound 2"],
- ["TRI-BackBay-Orange-0-3", DirID.SB, CarDir.L, 18, "place-bbsta", ["BKB-DS-007", "BKB-DS-008", "BKB-DS-009"], "Back Bay - OL Outbound 3"],
- ["TRI-BackBay-Orange-1-1", DirID.NB, CarDir.L, 4, "place-bbsta", ["BKB-DS-018", "BKB-DS-017", "BKB-DS-016"], "Back Bay - OL Inbound 1"],
- ["TRI-BackBay-Orange-1-2", DirID.NB, CarDir.L, 16, "place-bbsta", ["BKB-DS-015", "BKB-DS-014", "BKB-DS-013"], "Back Bay - OL Inbound 2"],
- ["TRI-BackBay-Orange-1-3", DirID.NB, CarDir.L, 19, "place-bbsta", ["BKB-DS-012", "BKB-DS-011", "BKB-DS-010"], "Back Bay - OL Inbound 3"],
-
- // MASSACHUSETTS AVENUE
- // NAME CHANGE: MassAve / Mass Ave
- // ๐ฅ One of the player names in the spreadsheet is concerning--"MAS-DS-010_failed".
- // (This is the right pane of TRI-MassAve-Orange-1-2)
- // I assumed that that name was temporary at time of the spreadsheet's creation, and used the
- // normal naming pattern without the "_failed" suffix.
- // We should check this out.
- // RELATED: Should we use player IDs instead of names? Are those less likely to change?
- // It should be possible to get it from the MRAID object in the same way we get the player name.
- ["TRI-MassAve-Orange-0-1", DirID.SB, CarDir.L, 18, "place-masta", ["MAS-DS-007", "MAS-DS-008", "MAS-DS-009"], "Mass Ave - OL Outbound 1"],
- ["TRI-MassAve-Orange-0-2", DirID.SB, CarDir.L, 22, "place-masta", ["MAS-DS-001", "MAS-DS-002", "MAS-DS-003"], "Mass Ave - OL Outbound 2"],
- ["TRI-MassAve-Orange-1-1", DirID.NB, CarDir.L, 4, "place-masta", ["MAS-DS-006", "MAS-DS-005", "MAS-DS-004"], "Mass Ave - OL Inbound 1"],
- ["TRI-MassAve-Orange-1-2", DirID.NB, CarDir.L, 8, "place-masta", ["MAS-DS-012", "MAS-DS-011", "MAS-DS-010"], "Mass Ave - OL Inbound 2"],
-
- // RUGGLES
- ["TRI-Ruggles-Orange-0-1", DirID.SB, CarDir.L, 11, "place-rugg", ["RUG-DS-001", "RUG-DS-002", "RUG-DS-003"], "Ruggles - OL Outbound 1"],
- ["TRI-Ruggles-Orange-0-2", DirID.SB, CarDir.L, 20, "place-rugg", ["RUG-DS-004", "RUG-DS-005", "RUG-DS-006"], "Ruggles - OL Outbound 2"],
- ["TRI-Ruggles-Orange-1-1", DirID.NB, CarDir.L, 7, "place-rugg", ["RUG-DS-012", "RUG-DS-011", "RUG-DS-010"], "Ruggles - OL Inbound 1"],
- ["TRI-Ruggles-Orange-1-2", DirID.NB, CarDir.L, 15, "place-rugg", ["RUG-DS-009", "RUG-DS-008", "RUG-DS-007"], "Ruggles - OL Inbound 2"]
-];
-
-// ^^^ Add to this ^^^
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-// ----- You normally don't need to edit anything below here, unless changing default config shape or adding new subway lines -----
-
-type TriptychScreenID = `TRI-${string}-Orange-${0 | 1}-${number}`;
-
-type StationID =
- | "place-ogmnl"
- | "place-mlmnl"
- | "place-welln"
- | "place-astao"
- | "place-sull"
- | "place-ccmnl"
- | "place-north"
- | "place-haecl"
- | "place-state"
- | "place-dwnxg"
- | "place-chncl"
- | "place-tumnl"
- | "place-bbsta"
- | "place-masta"
- | "place-rugg"
- | "place-rcmnl"
- | "place-jaksn"
- | "place-sbmnl"
- | "place-grnst"
- | "place-forhl";
-
-enum DirID {
- SB = 0,
- NB = 1,
- WB = 0,
- EB = 1
-}
-
-enum CarDir {
- L = "left",
- R = "right"
-}
-
-type PlatformPosition = number;
-const isPlatformPosition = (value: number): value is PlatformPosition => {
- return value >= 1 && value <= 25;
-};
-
-interface ConfigItem {
- configEntry: [TriptychScreenID, object],
- playerNameEntries: [[string, TriptychScreenID], [string, TriptychScreenID], [string, TriptychScreenID]]
-}
-
-const getConfigs = () => JSON.stringify(validate(mergeConfigs(getDraftConfigs().map((params) => makeConfig.apply(null, params)))));
-
-const mergeConfigs = (configs: ConfigItem[]) =>
- configs.reduce(({ screenConfig, playerNameMapping }, { configEntry: [k, v], playerNameEntries }) => ({
- screenConfig: { ...screenConfig, [k]: v },
- playerNameMapping: { ...playerNameMapping, ...Object.fromEntries(playerNameEntries) }
- }), { screenConfig: {}, playerNameMapping: {} });
-
-const validate = (mergedConfig: { screenConfig: object, playerNameMapping: object }) => {
- const { screenConfig, playerNameMapping } = mergedConfig;
-
- const screenCount = Object.keys(screenConfig).length;
- const playerNameCount = Object.keys(playerNameMapping).length;
-
- if (playerNameCount > 3 * screenCount) {
- throw "There are too few screen configurations compared to player names. Do you have a duplicate screen ID somewhere in the list?";
- } else if (playerNameCount < 3 * screenCount) {
- throw "There are too few player names compared to screens. Do you have a duplicate player name somewhere in the list?";
- } else {
- return mergedConfig;
- }
-};
-
-const makeConfig: (...params: ConfigItemParams) => ConfigItem = (id, directionID, frontCarDirection, platformPosition, stationID, playerNames, name) => {
- if (!isPlatformPosition(platformPosition)) throw "Not a platform position";
-
- return {
- configEntry: [id, makeScreenConfig(directionID, frontCarDirection, platformPosition, stationID, name)],
- playerNameEntries: playerNames.map(name => [name, id]) as ConfigItem["playerNameEntries"]
- };
-};
-
-const makeScreenConfig = (directionID: DirID, frontCarDirection: CarDir, platformPosition: PlatformPosition, stationID: StationID, name: string) => ({
- "app_id": "triptych_v2",
- "app_params": {
- "evergreen_content": [],
- "local_evergreen_sets": [
- {
- "folder_name": "See-Say",
- "schedule": [
- {
- "end_dt": null,
- "start_dt": null
- }
- ]
- },
- {
- "folder_name": "Closing-Doors",
- "schedule": [
- {
- "end_dt": null,
- "start_dt": null
- }
- ]
- }
- ],
- "show_identifiers": false,
- "train_crowding": {
- "direction_id": directionID,
- "enabled": true,
- "front_car_direction": frontCarDirection,
- "platform_position": platformPosition,
- "route_id": "Orange",
- "station_id": stationID
- }
- },
- "device_id": "N/A",
- "disabled": false,
- "hidden_from_screenplay": true,
- "name": name,
- "refresh_if_loaded_before": "2023-05-09T18:41:27.318063Z",
- "tags": [],
- "vendor": "outfront"
-});
-
-// This line actually runs the thing.
-console.log(getConfigs());
diff --git a/scripts/pull_configs.sh b/scripts/pull_configs.sh
index be9af8bbe..ca7e22a39 100755
--- a/scripts/pull_configs.sh
+++ b/scripts/pull_configs.sh
@@ -33,5 +33,4 @@ maybe_cp() {
maybe_cp s3://mbta-ctd-config/screens/screens-"$1".json priv/local.json
maybe_cp s3://mbta-ctd-config/screens/pending-screens-"$1".json priv/local_pending.json
-maybe_cp s3://mbta-ctd-config/screens/triptych-player-"$1".json priv/triptych_player_to_screen_id.json
maybe_cp s3://mbta-signs/config.json priv/signs_ui_config.json
diff --git a/test/fixtures/triptych_player_to_screen_id.json b/test/fixtures/triptych_player_to_screen_id.json
deleted file mode 100644
index 0967ef424..000000000
--- a/test/fixtures/triptych_player_to_screen_id.json
+++ /dev/null
@@ -1 +0,0 @@
-{}
diff --git a/test/screens/v2/candidate_generator/bus_eink_test.exs b/test/screens/v2/candidate_generator/bus_eink_test.exs
index ba409599a..b96ccc6bc 100644
--- a/test/screens/v2/candidate_generator/bus_eink_test.exs
+++ b/test/screens/v2/candidate_generator/bus_eink_test.exs
@@ -52,7 +52,7 @@ defmodule Screens.V2.CandidateGenerator.BusEinkTest do
end
end
- describe "candidate_instances/3" do
+ describe "candidate_instances/7" do
test "returns expected header", %{config: config} do
departures_instances_fn = fn _, _ -> [] end
alerts_instances_fn = fn _ -> [] end
@@ -60,12 +60,10 @@ defmodule Screens.V2.CandidateGenerator.BusEinkTest do
now = ~U[2020-04-06T10:00:00Z]
evergreen_content_instances_fn = fn _ -> [] end
subway_status_instances_fn = fn _, _ -> [] end
- opts = []
actual_instances =
BusEink.candidate_instances(
config,
- opts,
now,
fetch_stop_fn,
departures_instances_fn,
diff --git a/test/screens/v2/candidate_generator/bus_shelter_test.exs b/test/screens/v2/candidate_generator/bus_shelter_test.exs
index 66c74e0c0..ac8eb53c0 100644
--- a/test/screens/v2/candidate_generator/bus_shelter_test.exs
+++ b/test/screens/v2/candidate_generator/bus_shelter_test.exs
@@ -72,7 +72,7 @@ defmodule Screens.V2.CandidateGenerator.BusShelterTest do
end
end
- describe "candidate_instances/3" do
+ describe "candidate_instances/7" do
test "returns expected header and footer", %{config: config} do
departures_instances_fn = fn _, _ -> [] end
alert_instances_fn = fn _ -> [] end
@@ -80,7 +80,6 @@ defmodule Screens.V2.CandidateGenerator.BusShelterTest do
now = ~U[2020-04-06T10:00:00Z]
evergreen_content_instances_fn = fn _ -> [] end
subway_status_instances_fn = fn _, _ -> [] end
- opts = []
expected_header = %NormalHeader{
screen: config,
@@ -94,7 +93,6 @@ defmodule Screens.V2.CandidateGenerator.BusShelterTest do
actual_instances =
BusShelter.candidate_instances(
config,
- opts,
now,
fetch_stop_fn,
departures_instances_fn,
@@ -117,7 +115,6 @@ defmodule Screens.V2.CandidateGenerator.BusShelterTest do
now = ~U[2020-04-06T10:00:00Z]
evergreen_content_instances_fn = fn _ -> [] end
subway_status_instances_fn = fn _, _ -> [] end
- opts = []
expected_header = %NormalHeader{
screen: config,
@@ -129,7 +126,6 @@ defmodule Screens.V2.CandidateGenerator.BusShelterTest do
actual_instances =
BusShelter.candidate_instances(
config,
- opts,
now,
fetch_stop_fn,
departures_instances_fn,
diff --git a/test/screens/v2/candidate_generator/busway_test.exs b/test/screens/v2/candidate_generator/busway_test.exs
index 09219078f..1ca4188ba 100644
--- a/test/screens/v2/candidate_generator/busway_test.exs
+++ b/test/screens/v2/candidate_generator/busway_test.exs
@@ -39,14 +39,14 @@ defmodule Screens.V2.CandidateGenerator.BuswayTest do
deps = struct!(deps, now: fn -> now end)
expected_header = %NormalHeader{screen: config, icon: :logo, text: "Ruggles", time: now}
- assert expected_header in Busway.candidate_instances(config, [], deps)
+ assert expected_header in Busway.candidate_instances(config, deps)
end
test "includes departures instances", %{config: config, deps: deps} do
no_data = %DeparturesNoData{screen: config, show_alternatives?: true}
deps = struct!(deps, departures_instances: fn ^config, _ -> [no_data] end)
- assert no_data in Busway.candidate_instances(config, [], deps)
+ assert no_data in Busway.candidate_instances(config, deps)
end
end
end
diff --git a/test/screens/v2/candidate_generator/dup_test.exs b/test/screens/v2/candidate_generator/dup_test.exs
index 43cea3f99..1347cc002 100644
--- a/test/screens/v2/candidate_generator/dup_test.exs
+++ b/test/screens/v2/candidate_generator/dup_test.exs
@@ -83,14 +83,13 @@ defmodule Screens.V2.CandidateGenerator.DupTest do
end
end
- describe "candidate_instances/4" do
+ describe "candidate_instances/6" do
test "returns expected header", %{config: config} do
now = ~U[2020-04-06T10:00:00Z]
fetch_stop_fn = fn "place-gover" -> "Government Center" end
departures_instances_fn = fn _, _ -> [] end
evergreen_content_instances_fn = fn _ -> [] end
alerts_instances_fn = fn _, _ -> [] end
- opts = []
expected_headers =
List.duplicate(
@@ -106,7 +105,6 @@ defmodule Screens.V2.CandidateGenerator.DupTest do
actual_instances =
Dup.candidate_instances(
config,
- opts,
now,
fetch_stop_fn,
evergreen_content_instances_fn,
diff --git a/test/screens/v2/candidate_generator/solari_large_test.exs b/test/screens/v2/candidate_generator/solari_large_test.exs
index e4c1c776c..cd5e839a9 100644
--- a/test/screens/v2/candidate_generator/solari_large_test.exs
+++ b/test/screens/v2/candidate_generator/solari_large_test.exs
@@ -30,11 +30,10 @@ defmodule Screens.V2.CandidateGenerator.SolariLargeTest do
end
end
- describe "candidate_instances/2" do
+ describe "candidate_instances/3" do
test "returns expected header", %{config: config} do
departures_instances_fn = fn _, _ -> [] end
now = ~U[2020-04-06T10:00:00Z]
- opts = []
expected_header = %NormalHeader{
screen: config,
@@ -44,7 +43,7 @@ defmodule Screens.V2.CandidateGenerator.SolariLargeTest do
}
actual_instances =
- SolariLarge.candidate_instances(config, opts, now, departures_instances_fn)
+ SolariLarge.candidate_instances(config, now, departures_instances_fn)
assert expected_header in actual_instances
end
diff --git a/test/screens/v2/candidate_generator/triptych_test.exs b/test/screens/v2/candidate_generator/triptych_test.exs
deleted file mode 100644
index 4d5c85e18..000000000
--- a/test/screens/v2/candidate_generator/triptych_test.exs
+++ /dev/null
@@ -1,36 +0,0 @@
-defmodule Screens.V2.CandidateGenerator.TriptychTest do
- use ExUnit.Case, async: true
-
- alias ScreensConfig.{Screen, V2}
- alias Screens.V2.CandidateGenerator.Triptych
-
- setup do
- config = %Screen{
- app_params: %V2.Triptych{
- local_evergreen_sets: [],
- train_crowding: %V2.TrainCrowding{
- station_id: "place-dwnxg",
- direction_id: 1,
- platform_position: 3,
- front_car_direction: "right"
- }
- },
- vendor: :outfront,
- device_id: "TEST",
- name: "TEST",
- app_id: :triptych_v2
- }
-
- %{config: config}
- end
-
- describe "screen_template/0" do
- test "returns template" do
- assert {:screen,
- %{
- screen_normal: [:full_screen],
- screen_split: [:left_pane, :middle_pane, :right_pane]
- }} == Triptych.screen_template()
- end
- end
-end
diff --git a/test/screens/v2/candidate_generator/widgets/train_crowding_test.exs b/test/screens/v2/candidate_generator/widgets/train_crowding_test.exs
deleted file mode 100644
index 0a47caae2..000000000
--- a/test/screens/v2/candidate_generator/widgets/train_crowding_test.exs
+++ /dev/null
@@ -1,303 +0,0 @@
-defmodule Screens.V2.CandidateGenerator.Widgets.TrainCrowdingTest do
- use ExUnit.Case, async: true
-
- import Screens.V2.CandidateGenerator.Widgets.TrainCrowding
-
- alias ScreensConfig.Screen
- alias ScreensConfig.V2.{TrainCrowding, Triptych}
- alias Screens.Predictions.Prediction
- alias Screens.Vehicles.{Carriage, Vehicle}
- alias Screens.V2.WidgetInstance.TrainCrowding, as: CrowdingWidget
-
- setup :setup_base
-
- defp setup_base(_) do
- config = %Screen{
- app_params: %Triptych{
- train_crowding: %TrainCrowding{
- station_id: "place-masta",
- direction_id: 1,
- platform_position: 3,
- front_car_direction: "right",
- enabled: true
- },
- local_evergreen_sets: []
- },
- vendor: :outfront,
- device_id: "TEST",
- name: "TEST",
- app_id: :triptych_v2
- }
-
- now = ~U[2023-08-16 21:04:00Z]
-
- next_train_prediction =
- struct(Prediction, %{
- vehicle:
- struct(Vehicle, %{
- stop_id: "10001",
- current_status: :incoming_at,
- carriages: [struct(Carriage)]
- })
- })
-
- location_context = %Screens.LocationContext{
- home_stop: "place-masta",
- tagged_stop_sequences: %{
- "Orange" => [
- [
- "place-ogmnl",
- "place-mlmnl",
- "place-welln",
- "place-astao",
- "place-sull",
- "place-ccmnl",
- "place-north",
- "place-haecl",
- "place-state",
- "place-dwnxg",
- "place-chncl",
- "place-tumnl",
- "place-bbsta",
- "place-masta",
- "place-rugg",
- "place-rcmnl",
- "place-jaksn",
- "place-sbmnl",
- "place-grnst",
- "place-forhl"
- ]
- ]
- },
- upstream_stops:
- MapSet.new([
- "place-astao",
- "place-bbsta",
- "place-ccmnl",
- "place-chncl",
- "place-dwnxg",
- "place-haecl",
- "place-mlmnl",
- "place-north",
- "place-ogmnl",
- "place-state",
- "place-sull",
- "place-tumnl",
- "place-welln"
- ]),
- downstream_stops:
- MapSet.new([
- "place-forhl",
- "place-grnst",
- "place-jaksn",
- "place-rcmnl",
- "place-rugg",
- "place-sbmnl"
- ]),
- routes: [
- %{
- active?: true,
- direction_destinations: ["Forest Hills", "Oak Grove"],
- long_name: "Orange Line",
- route_id: "Orange",
- short_name: "",
- type: :subway
- }
- ],
- alert_route_types: [:light_rail, :subway]
- }
-
- alerts = [
- %Screens.Alerts.Alert{
- id: "141245",
- cause: :unknown,
- effect: :shuttle,
- severity: 7,
- header: "Shuttle buses replacing Orange Line service",
- informed_entities: [
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "70012"},
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "70013"},
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "70014"},
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "70015"},
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "70016"},
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "70017"},
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "70018"},
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "70019"},
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "70020"},
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "70021"},
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "70022"},
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "70023"},
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "70024"},
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "70025"},
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "place-bbsta"},
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "place-chncl"},
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "place-dwnxg"},
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "place-haecl"},
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "place-masta"},
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "place-state"},
- %{direction_id: nil, route: "Orange", route_type: 1, stop: "place-tumnl"}
- ],
- active_period: [{DateTime.add(now, -1, :hour), DateTime.add(now, 2, :hour)}],
- lifecycle: "NEW",
- timeframe: nil,
- created_at: ~U[2023-08-16 20:04:02Z],
- updated_at: ~U[2023-08-16 20:04:02Z],
- url: nil,
- description:
- "Affected stops:\r\nHaymarket\r\nState\r\nDowntown Crossing\r\nChinatown\r\nTufts Medical Center\r\nBack Bay\r\nMassachusetts Avenue"
- }
- ]
-
- %{
- config: config,
- logging_options: %{is_real_screen: false, screen_id: "TEST", triptych_pane: nil},
- now: now,
- next_train_prediction: next_train_prediction,
- fetch_predictions_fn: fn _ -> {:ok, [next_train_prediction]} end,
- fetch_location_context_fn: fn _, _, _ -> {:ok, location_context} end,
- fetch_parent_stop_id_fn: fn "10001" -> "place-masta" end,
- fetch_empty_alerts_fn: fn _ -> {:ok, []} end,
- fetch_alerts_fn: fn _ -> {:ok, alerts} end
- }
- end
-
- defp disable_widget(config) do
- %{
- config
- | app_params: %{
- config.app_params
- | train_crowding: %{config.app_params.train_crowding | enabled: false}
- }
- }
- end
-
- describe "crowding_widget_instances/3" do
- test "returns crowding widget if train is on the way to this station", context do
- assert crowding_widget_instances(
- context.config,
- context.logging_options,
- context.now,
- context.fetch_predictions_fn,
- context.fetch_location_context_fn,
- context.fetch_parent_stop_id_fn,
- context.fetch_empty_alerts_fn
- ) == [
- %CrowdingWidget{
- screen: context.config,
- prediction: context.next_train_prediction,
- now: context.now
- }
- ]
- end
-
- test "returns empty if train is not coming yet", context do
- alt_prediction =
- struct(Prediction, %{
- vehicle: struct(Vehicle, %{stop_id: "9999", current_status: :incoming_at})
- })
-
- assert crowding_widget_instances(
- context.config,
- context.logging_options,
- context.now,
- fn _ -> {:ok, [alt_prediction]} end,
- context.fetch_location_context_fn,
- fn "9999" -> "place-bbsta" end,
- context.fetch_empty_alerts_fn
- ) == []
- end
-
- test "returns empty if train has already arrived at this station", context do
- alt_prediction =
- struct(Prediction, %{
- vehicle: struct(Vehicle, %{stop_id: "10001", current_status: :stopped_at})
- })
-
- assert crowding_widget_instances(
- context.config,
- context.logging_options,
- context.now,
- fn _ -> {:ok, [alt_prediction]} end,
- context.fetch_location_context_fn,
- context.fetch_parent_stop_id_fn,
- context.fetch_empty_alerts_fn
- ) == []
- end
-
- test "returns empty if there is a shuttle / suspension that makes this station a temp terminal",
- context do
- assert crowding_widget_instances(
- context.config,
- context.logging_options,
- context.now,
- context.fetch_predictions_fn,
- context.fetch_location_context_fn,
- context.fetch_parent_stop_id_fn,
- context.fetch_alerts_fn
- ) == []
- end
-
- test "returns empty if there are no predictions", context do
- assert crowding_widget_instances(
- context.config,
- context.logging_options,
- context.now,
- fn _ -> {:ok, []} end,
- context.fetch_location_context_fn,
- context.fetch_parent_stop_id_fn,
- context.fetch_empty_alerts_fn
- ) == []
- end
-
- test "returns empty if any fetches fail", context do
- assert crowding_widget_instances(
- context.config,
- context.logging_options,
- context.now,
- fn _ -> :error end,
- context.fetch_location_context_fn,
- context.fetch_parent_stop_id_fn,
- context.fetch_empty_alerts_fn
- ) == []
-
- assert crowding_widget_instances(
- context.config,
- context.logging_options,
- context.now,
- context.fetch_predictions_fn,
- fn _, _, _ -> :error end,
- context.fetch_parent_stop_id_fn,
- context.fetch_empty_alerts_fn
- ) == []
-
- assert crowding_widget_instances(
- context.config,
- context.logging_options,
- context.now,
- context.fetch_predictions_fn,
- context.fetch_location_context_fn,
- fn _ -> :error end,
- context.fetch_empty_alerts_fn
- ) == []
-
- assert crowding_widget_instances(
- context.config,
- context.logging_options,
- context.now,
- context.fetch_predictions_fn,
- context.fetch_location_context_fn,
- context.fetch_parent_stop_id_fn,
- fn _ -> :error end
- ) == []
- end
-
- test "returns empty if widget is disabled", %{
- config: config,
- logging_options: logging_options
- } do
- config = disable_widget(config)
-
- assert crowding_widget_instances(config, logging_options) == []
- end
- end
-end
diff --git a/test/screens/v2/screen_data_test.exs b/test/screens/v2/screen_data_test.exs
index 7fe3e69b2..374d6066e 100644
--- a/test/screens/v2/screen_data_test.exs
+++ b/test/screens/v2/screen_data_test.exs
@@ -12,7 +12,7 @@ defmodule Screens.V2.ScreenDataTest.Stub do
def screen_template(), do: Builder.build_template({:screen, %{normal: [:main]}})
@impl CandidateGenerator
- def candidate_instances(config, _opts) do
+ def candidate_instances(config) do
unquote(instances_fn).(config)
end
diff --git a/test/screens/v2/widget_instance/train_crowding_test.exs b/test/screens/v2/widget_instance/train_crowding_test.exs
deleted file mode 100644
index db2b7ff1d..000000000
--- a/test/screens/v2/widget_instance/train_crowding_test.exs
+++ /dev/null
@@ -1,181 +0,0 @@
-defmodule Screens.V2.WidgetInstance.TrainCrowdingTest do
- use ExUnit.Case, async: true
-
- alias Screens.Predictions.Prediction
- alias Screens.V2.WidgetInstance.TrainCrowding, as: WidgetInstance
- alias Screens.Vehicles.{Carriage, Vehicle}
-
- defp put_crowding_levels(widget, carriages) do
- put_in(widget.prediction.vehicle.carriages, carriages)
- end
-
- setup do
- config =
- struct(ScreensConfig.Screen, %{
- app_params:
- struct(ScreensConfig.V2.Triptych, %{
- train_crowding: %ScreensConfig.V2.TrainCrowding{
- station_id: "place-masta",
- direction_id: 1,
- platform_position: 3,
- front_car_direction: "right",
- enabled: true
- }
- })
- })
-
- prediction =
- struct(Prediction, %{
- trip: %{
- headsign: "Oak Grove"
- },
- vehicle:
- struct(Vehicle, %{
- stop_id: "10001",
- current_status: :incoming_at,
- carriages: [
- %Carriage{
- car_number: "1",
- occupancy_status: :crushed_standing_room_only,
- occupancy_percentage: 45
- },
- %Carriage{
- car_number: "2",
- occupancy_status: :few_seats_available,
- occupancy_percentage: 5
- },
- %Carriage{
- car_number: "3",
- occupancy_status: :standing_room_only,
- occupancy_percentage: 20
- },
- %Carriage{
- car_number: "4",
- occupancy_status: :many_seats_available,
- occupancy_percentage: 5
- },
- %Carriage{car_number: "5", occupancy_status: :full, occupancy_percentage: 45},
- %Carriage{
- car_number: "6",
- occupancy_status: :not_accepting_passengers,
- occupancy_percentage: -1
- }
- ]
- })
- })
-
- widget = %WidgetInstance{
- screen: config,
- prediction: prediction,
- now: ~U[2023-08-16 21:04:00Z]
- }
-
- %{widget: widget}
- end
-
- describe "serialize/1" do
- test "serializes data, 6/7 possible crowding levels", %{widget: widget} do
- expected = %{
- destination: "Oak Grove",
- crowding: [:crowded, :not_crowded, :some_crowding, :not_crowded, :crowded, :closed],
- platform_position: 3,
- front_car_direction: "right",
- now: "2023-08-16T21:04:00Z",
- show_identifiers: false
- }
-
- assert expected == WidgetInstance.serialize(widget)
- end
-
- test "serializes data, last crowding level (no_data)", %{widget: widget} do
- widget =
- put_crowding_levels(widget, [
- %Carriage{
- car_number: "1",
- occupancy_status: :no_data_available,
- occupancy_percentage: -1
- },
- %Carriage{
- car_number: "2",
- occupancy_status: :no_data_available,
- occupancy_percentage: -1
- },
- %Carriage{
- car_number: "3",
- occupancy_status: :standing_room_only,
- occupancy_percentage: 25
- },
- %Carriage{
- car_number: "4",
- occupancy_status: :many_seats_available,
- occupancy_percentage: 5
- },
- %Carriage{car_number: "5", occupancy_status: :full, occupancy_percentage: 45},
- %Carriage{
- car_number: "6",
- occupancy_status: :not_accepting_passengers,
- occupancy_percentage: -1
- }
- ])
-
- expected = %{
- destination: "Oak Grove",
- crowding: [:no_data, :no_data, :some_crowding, :not_crowded, :crowded, :closed],
- platform_position: 3,
- front_car_direction: "right",
- now: "2023-08-16T21:04:00Z",
- show_identifiers: false
- }
-
- assert expected == WidgetInstance.serialize(widget)
- end
- end
-
- describe "priority/1" do
- test "returns max priority", %{widget: widget} do
- assert [1] == WidgetInstance.priority(widget)
- end
- end
-
- describe "slot_names/1" do
- test "returns [:full_screen]", %{widget: widget} do
- assert [:full_screen] == WidgetInstance.slot_names(widget)
- end
- end
-
- describe "widget_type/1" do
- test "returns :train_crowding", %{widget: widget} do
- assert :train_crowding == WidgetInstance.widget_type(widget)
- end
- end
-
- describe "valid_candidate?/1" do
- test "returns true", %{widget: widget} do
- assert WidgetInstance.valid_candidate?(widget)
- end
- end
-
- describe "audio_serialize/1" do
- test "returns empty", %{widget: widget} do
- assert %{} == WidgetInstance.audio_serialize(widget)
- end
- end
-
- describe "audio_sort_key/1" do
- test "returns [0]", %{widget: widget} do
- assert [0] == WidgetInstance.audio_sort_key(widget)
- end
- end
-
- describe "audio_valid_candidate?/1" do
- test "returns false", %{widget: widget} do
- assert not WidgetInstance.audio_valid_candidate?(widget)
- end
- end
-
- describe "audio_view/1" do
- test "returns nil", %{widget: widget} do
- assert nil == WidgetInstance.audio_view(widget)
- end
- end
-end