Skip to content

Commit

Permalink
Add: countdown timer to lap limited multiplayer race events
Browse files Browse the repository at this point in the history
  • Loading branch information
Tamas Cseh committed Jan 19, 2021
1 parent d6036d5 commit 595f8ac
Show file tree
Hide file tree
Showing 13 changed files with 133 additions and 4 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

All notable changes to this project will be documented in this file.

## [2.2.0] - 2021-01-19
### Added
- Add countdown timer to lap limited multiplayer race events
- Support latest rFactor2 release

## [2.1.0] - 2021-01-10
### Added
- Remember selected server filters
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ In this repository you can find small modifications for the new rFactor 2 UI
- highlight current track in setup popup
- disable opacity change animation
- remember selected multiplayer server filters
- add countdown timer to lap limited multiplayer race events

# How to patch UI files
- Compile Better ui: `npm run build.all`
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rf2-better-ui",
"version": "2.1.0",
"version": "2.2.0",
"scripts": {
"ng": "ng",
"start": "ng serve --live-reload=false",
Expand Down
7 changes: 6 additions & 1 deletion projects/rf2-better-ui/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { GarageHandlerComponent } from './components/garage-handler/garage-handl
import { EventHandlerComponent } from './components/event-handler/event-handler.component';
import { SessionsHandlerComponent } from './components/sessions-handler/sessions-handler.component';
import { MultiplayerHandlerComponent } from './components/multiplayer-handler/multiplayer-handler.component';
import { RaceCountdownTimerComponent } from './components/race-countdown-timer/race-countdown-timer.component';

@NgModule({
imports: [
Expand All @@ -27,7 +28,8 @@ import { MultiplayerHandlerComponent } from './components/multiplayer-handler/mu
GarageHandlerComponent,
EventHandlerComponent,
SessionsHandlerComponent,
MultiplayerHandlerComponent
MultiplayerHandlerComponent,
RaceCountdownTimerComponent
],
providers: []
})
Expand Down Expand Up @@ -59,6 +61,9 @@ export class AppModule implements DoBootstrap {

const multiplayerHandlerWebComponent = createCustomElement(MultiplayerHandlerComponent, {injector});
customElements.define("rf-multiplayer-handler", multiplayerHandlerWebComponent);

const raceCountDownTimerWebComponent = createCustomElement(RaceCountdownTimerComponent, {injector});
customElements.define("rf-race-countdown-timer", raceCountDownTimerWebComponent);
}

ngDoBootstrap(appRef: ApplicationRef): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@ export class EventHandlerComponent implements OnInit, OnDestroy {
private observer: MutationObserver;

ngOnInit(): void {
waitForElement('nav em').then((e: Element) => {
const countDown: HTMLElement = document.createElement('rf-race-countdown-timer');
e.parentElement.appendChild(countDown);
});

// add rf-chat component to the DOM
waitForElement('.camera-wrapper').then(() => {
this.tabHolder = document.querySelector("div[ng-if='eventCtrl.gameState.navigationState']");
this.tabHolder = document.querySelector('div[ng-if=\'eventCtrl.gameState.navigationState\']');
this.injectChat();
this.observeTabChange();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ export class GarageHandlerComponent implements OnInit {
}

ngOnInit(): void {
waitForElement('nav em').then((e: Element) => {
const countDown: HTMLElement = document.createElement('rf-race-countdown-timer');
e.parentElement.appendChild(countDown);
});

this.listItems = document.querySelectorAll('main section div.thumbnail');

this.findSetupButtons();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<em *ngIf="timeLeft$ | async as time">{{time}}s</em>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { RaceCountdownTimerComponent } from './race-countdown-timer.component';

describe('RaceCountdownTimerComponent', () => {
let component: RaceCountdownTimerComponent;
let fixture: ComponentFixture<RaceCountdownTimerComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ RaceCountdownTimerComponent ]
})
.compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(RaceCountdownTimerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, timer } from 'rxjs';
import { filter, map, switchMap } from 'rxjs/operators';
import { SessionInfo } from '../../interfaces/session-info';
import { GamePhase } from '../../interfaces/game-phase';

@Component({
selector: 'rf-race-countdown-timer',
templateUrl: './race-countdown-timer.component.html',
styleUrls: ['./race-countdown-timer.component.scss']
})
export class RaceCountdownTimerComponent implements OnInit {

public timeLeft$: Observable<number>;

constructor(private http: HttpClient) {
}

ngOnInit(): void {
this.timeLeft$ = timer(1, 1000).pipe(
switchMap(() => this.http.get<SessionInfo>('/rest/watch/sessionInfo')),
filter((info: SessionInfo) => info.session.startsWith('RACE') // race session
&& info.gamePhase === GamePhase.BEFORE // before formation lap start
&& info.maximumLaps < 1500), // lap limited race
map((info: SessionInfo) => Math.round(info.endEventTime - info.currentEventTime))
);
}

}
12 changes: 12 additions & 0 deletions projects/rf2-better-ui/src/app/interfaces/game-phase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export enum GamePhase {
BEFORE,
RECONNAISSANCE,
WALKTHROUGH,
FORMATION,
COUNTDOWN,
GREEN,
SAFETY_CAR,
RED,
CHECKERED,
INVALID
}
40 changes: 40 additions & 0 deletions projects/rf2-better-ui/src/app/interfaces/session-info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { GamePhase } from './game-phase';

export interface SessionInfo {
trackName: string;
session: string;
currentEventTime: number;
endEventTime: number;
maximumLaps: number;
lapDistance: number;
numberOfVehicles: number;
gamePhase: GamePhase;
yellowFlagState: string;
sectorFlag: string[];
startLightFrame: number;
numRedLights: number;
inRealtime: boolean;
playerName: string;
playerFileName: string;
darkCloud: number;
raining: number;
ambientTemp: number;
trackTemp: number;
windSpeed: {
x: number;
y: number;
z: number;
velocity: number;
};

minPathWetness: number;
averagePathWetness: number;
maxPathWetness: number;
gameMode: string;
passwordProtected: boolean;
serverPort: number;
maxPlayers: number;
serverName: string;
startEventTime: number;
raceCompletion: any;
}

0 comments on commit 595f8ac

Please sign in to comment.