Skip to content

Commit

Permalink
Merge pull request #2 from rpitv/sync
Browse files Browse the repository at this point in the history
  • Loading branch information
robere2 committed Dec 15, 2023
1 parent ed0d4e3 commit 1b74333
Show file tree
Hide file tree
Showing 42 changed files with 4,064 additions and 620 deletions.
3 changes: 3 additions & 0 deletions apps/glimpse-graphics/docker-compose-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ services:
ports:
- "9090:80"
- "3000:3000"
environment:
- NODE_ENV=development
- LOG_LEVEL=trace
volumes:
- ./.nodecg/cfg:/usr/src/app/cfg
- ./.nodecg/db:/usr/src/app/db
Expand Down
2 changes: 2 additions & 0 deletions apps/glimpse-graphics/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ services:
build: .
ports:
- "9090:80"
environment:
- NODE_ENV=production
volumes:
- ./.nodecg/cfg:/usr/src/app/cfg
- ./.nodecg/db:/usr/src/app/db
Expand Down
1,583 changes: 1,521 additions & 62 deletions apps/glimpse-graphics/package-lock.json

Large diffs are not rendered by default.

31 changes: 25 additions & 6 deletions apps/glimpse-graphics/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,22 @@
"license": "MIT",
"scripts": {
"start": "node ../..",
"start-dev": "npx nodemon ../.. | npx pino-pretty -c",
"clean": "rm -rf node_modules/.cache && rm -rf shared/dist && rm -rf dashboard && rm -rf graphics && rm -rf extension",
"build": "run-s clean build:*",
"build:browser": "vite build",
"build:extension": "tsc -b tsconfig.extension.json",
"dev": "run-p start watch:*",
"dev": "run-p watch:* start-dev",
"watch:browser": "vite --host=0.0.0.0",
"watch:extension": "tsc -b tsconfig.extension.json -w"
},
"dependencies": {
"@vueuse/core": "^9.5.0",
"animejs": "^3.2.1",
"module-alias": "^2.2.2",
"pinia": "^2.0.23",
"pino": "^8.7.0",
"serialport": "^10.4.0",
"uuid": "^8.3.2"
},
"devDependencies": {
Expand All @@ -34,7 +39,9 @@
"naive-ui": "^2.32.1",
"nodecg-cli": "^8.0.1",
"nodecg-types": "^1.9.0",
"nodemon": "^2.0.20",
"npm-run-all": "^4.1.5",
"pino-pretty": "^9.1.1",
"sass": "^1.54.4",
"typescript": "^4.7.4",
"vite": "^2.9.14",
Expand All @@ -50,9 +57,16 @@
"name": "game-settings",
"title": "Game Settings",
"file": "game-settings.html",
"workspace": "General",
"workspace": "Settings",
"width": "8"
},
{
"name": "sync-settings",
"title": "Sync Settings",
"file": "sync-settings.html",
"workspace": "Settings",
"width": "4"
},
{
"name": "command-palette",
"title": "Command Palette",
Expand All @@ -61,9 +75,9 @@
"width": "2"
},
{
"name": "score",
"title": "Score",
"file": "score.html",
"name": "teams",
"title": "Teams",
"file": "teams.html",
"workspace": "Scoreboard",
"width": "6"
},
Expand Down Expand Up @@ -100,7 +114,12 @@
{
"name": "images",
"title": "Images",
"allowedTypes": ["jpg", "jpeg", "gif", "png"]
"allowedTypes": [
"jpg",
"jpeg",
"gif",
"png"
]
}
]
}
Expand Down
15 changes: 11 additions & 4 deletions apps/glimpse-graphics/src/browser-common/replicant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,20 @@ import {ReplicantOptions} from "nodecg-types/types/lib/replicant";
export async function replicant<T = any>(name: string, namespace?: string, options?: ReplicantOptions<T>): Promise<Ref<T>> { // @ts-ignore
const realReplicant = nodecg.Replicant<T>(name, namespace, options);

let value: Ref<T|undefined> = ref(undefined);
let value: Ref<T|null|undefined> = ref(undefined);
realReplicant.on('change', () => {
// FIXME updating the value directly does not trigger the computed property to recompute for some reason.
if(Array.isArray(realReplicant.value)) {
value.value = <T><unknown>[...realReplicant.value];
// This is a workaround for now.
if(typeof realReplicant.value === "object") {
if(realReplicant.value === null) {
value.value = null;
} else if(Array.isArray(realReplicant.value)) {
value.value = <T><unknown>[...realReplicant.value];
} else {
value.value = <T><unknown>{...realReplicant.value};
}
} else {
value.value = <T>realReplicant.value; // Will not be undefined
value.value = <T>realReplicant.value;
}
});

Expand Down
85 changes: 55 additions & 30 deletions apps/glimpse-graphics/src/browser-common/replicants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,57 +3,82 @@ import {DisplayableMessage} from "../common/DisplayableMessage";

export async function loadReplicants() {
return {
sync: {
availablePorts: await replicant<string[]>("availablePorts", "glimpse-graphics.sync-settings", {
defaultValue: [],
persistent: false
}),
selectedPort: await replicant<string | null>("selectedPort", "glimpse-graphics.sync-settings", {defaultValue: null}),
selectedSport: await replicant<string>("selectedSport", "glimpse-graphics.sync-settings", {defaultValue: 'Hockey/Lacrosse'}),
status: await replicant<{ connected: boolean, bitrate: number }>("status", "glimpse-graphics.sync-settings", {
defaultValue: {
connected: false,
bitrate: 0
}, persistent: false
}),
values: {
clock: await replicant<boolean>("clock", "glimpse-graphics.sync-settings.values", {defaultValue: false}),
period: await replicant<boolean>("period", "glimpse-graphics.sync-settings.values", {defaultValue: false}),
teams: [
{
score: await replicant<boolean>("score", "glimpse-graphics.sync-settings.values.team1", {defaultValue: false}),
name: await replicant<boolean>("name", "glimpse-graphics.sync-settings.values.team1", {defaultValue: false}),
abbreviation: await replicant<boolean>("abbreviation", "glimpse-graphics.sync-settings.values.team1", {defaultValue: false}),
}, {
score: await replicant<boolean>("score", "glimpse-graphics.sync-settings.values.team2", {defaultValue: false}),
name: await replicant<boolean>("name", "glimpse-graphics.sync-settings.values.team2", {defaultValue: false}),
abbreviation: await replicant<boolean>("abbreviation", "glimpse-graphics.sync-settings.values.team2", {defaultValue: false}),
}
],
baseball: {
bottomTop: await replicant<boolean>("bottomTop", "glimpse-graphics.sync-settings.values.baseball", {defaultValue: false}),
outsStrikesBalls: await replicant<boolean>("outsStrikesBall", "glimpse-graphics.sync-settings.values.baseball", {defaultValue: false}),
},
football: {
downs: await replicant<boolean>("downs", "glimpse-graphics.sync-settings.values.football", {defaultValue: false}),
possession: await replicant<boolean>("possession", "glimpse-graphics.sync-settings.values.football", {defaultValue: false}),
yardsToGo: await replicant<boolean>("yardsToGo", "glimpse-graphics.sync-settings.values.football", {defaultValue: false}),
playClock: await replicant<boolean>("playClock", "glimpse-graphics.sync-settings.values.football", {defaultValue: false}),
}
}
},
gameSettings: {
style: await replicant<'espn'|'rpitv-modern'|'rpitv-classic'>('style', 'glimpse-graphics.game-settings.style', {defaultValue: 'rpitv-modern'}),
style: await replicant<'espn' | 'rpitv-modern' | 'rpitv-classic'>('style', 'glimpse-graphics.game-settings.style', {defaultValue: 'rpitv-modern'}),
clock: {
enabled: await replicant<boolean>("enabled", "glimpse-graphics.game-settings.clock", {defaultValue: true}),
synced: await replicant<boolean>("synced", "glimpse-graphics.game-settings.clock", {defaultValue: false})
},
periods: {
enabled: await replicant<boolean>("enabled", "glimpse-graphics.game-settings.periods", {defaultValue: true}),
synced: await replicant<boolean>("synced", "glimpse-graphics.game-settings.periods", {defaultValue: false}),
count: await replicant<number>('count', 'glimpse-graphics.game-settings.periods', {defaultValue: 3}),
length: await replicant<number>('length', 'glimpse-graphics.game-settings.periods', {defaultValue: 1200_000}),
overtime: {
enabled: await replicant<boolean>('enabled', 'glimpse-graphics.game-settings.periods.overtime', {defaultValue: false}),
count: await replicant<number>('count', 'glimpse-graphics.game-settings.periods.overtime', {defaultValue: 0}),
isInfinite: await replicant<boolean>('isInfinite', 'glimpse-graphics.game-settings.periods.overtime', {defaultValue: false}),
length: await replicant<number>('length', 'glimpse-graphics.game-settings.periods.overtime', {defaultValue: 300_000}),
}
},
shootouts: await replicant<boolean>('shootouts', 'glimpse-graphics.game-settings.periods', {defaultValue: false}),
},

baseball: {
bases: {
enabled: await replicant<boolean>("enabled", "glimpse-graphics.game-settings.baseball.bases", {defaultValue: false}),
synced: await replicant<boolean>("synced", "glimpse-graphics.game-settings.baseball.bases", {defaultValue: false}),
},
bottomTop: {
enabled: await replicant<boolean>("enabled", "glimpse-graphics.game-settings.baseball.bottomTop", {defaultValue: false}),
synced: await replicant<boolean>("synced", "glimpse-graphics.game-settings.baseball.bottomTop", {defaultValue: false}),
},
outsStrikesBalls: {
enabled: await replicant<boolean>("enabled", "glimpse-graphics.game-settings.baseball.outsStrikesBalls", {defaultValue: false}),
synced: await replicant<boolean>("synced", "glimpse-graphics.game-settings.baseball.outsStrikesBalls", {defaultValue: false}),
}
bases: await replicant<boolean>("bases", "glimpse-graphics.game-settings.baseball", {defaultValue: false}),
bottomTop: await replicant<boolean>("bottomTop", "glimpse-graphics.game-settings.baseball", {defaultValue: false}),
outsStrikesBalls: await replicant<boolean>("outsStrikesBalls", "glimpse-graphics.game-settings.baseball", {defaultValue: false}),
},
football: {
downs: {
enabled: await replicant<boolean>("enabled", "glimpse-graphics.game-settings.football.downs", {defaultValue: false}),
synced: await replicant<boolean>("synced", "glimpse-graphics.game-settings.football.downs", {defaultValue: false}),
},
possession: {
enabled: await replicant<boolean>("enabled", "glimpse-graphics.game-settings.football.possession", {defaultValue: false}),
synced: await replicant<boolean>("synced", "glimpse-graphics.game-settings.football.possession", {defaultValue: false}),
},
playClock: {
enabled: await replicant<boolean>("enabled", "glimpse-graphics.game-settings.football.playClock", {defaultValue: false}),
synced: await replicant<boolean>("synced", "glimpse-graphics.game-settings.football.playClock", {defaultValue: false}),
}
downs: await replicant<boolean>("downs", "glimpse-graphics.game-settings.football", {defaultValue: false}),
possession: await replicant<boolean>("possession", "glimpse-graphics.game-settings.football", {defaultValue: false}),
yardsToGo: await replicant<boolean>("yardsToGo", "glimpse-graphics.game-settings.football", {defaultValue: false}),
playClock: await replicant<boolean>("playClock", "glimpse-graphics.game-settings.football", {defaultValue: false}),
}
},
scoreboard: {
visible: await replicant<boolean>('visible', 'glimpse-graphics.scoreboard', {defaultValue: true}),
clock: {
time: await replicant<number>('time', 'glimpse-graphics.scoreboard.clock', {defaultValue: 1200_000}),
isRunning: await replicant<boolean>('isRunning', 'glimpse-graphics.scoreboard.clock', {defaultValue: false, persistent: false}),
isRunning: await replicant<boolean>('isRunning', 'glimpse-graphics.scoreboard.clock', {
defaultValue: false,
persistent: false
}),
},
period: await replicant<number>('period', 'glimpse-graphics.scoreboard', {defaultValue: 1})
},
Expand Down
22 changes: 20 additions & 2 deletions apps/glimpse-graphics/src/common/MessageComposable.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,33 @@
type ListenerFn = (argument?: any, ack?: (error: Error, returnVal: any) => void) => void;

export class MessageComposable {

public channel: string;
public namespace: string;

private listeners: ListenerFn[] = [];

public constructor(channel: string, namespace?: string) {
this.channel = channel;
this.namespace = namespace ?? "";
}

public async send(argument?: any): Promise<void> {
public async send(argument?: any): Promise<any> {
// @ts-ignore
await nodecg.sendMessage(this.namespace + '.' + this.channel, argument)
return await nodecg.sendMessage(this.namespace + '.' + this.channel, argument);
}

public listen(callback: ListenerFn): void {
this.listeners.push(callback);
// @ts-ignore
nodecg.listenFor(this.namespace + '.' + this.channel, callback)
}

public destroy(): void {
for(const listener of this.listeners) {
// @ts-ignore
nodecg.unlisten(this.namespace + '.' + this.channel, listener);
}
this.listeners = [];
}
}
Loading

0 comments on commit 1b74333

Please sign in to comment.