Skip to content

Commit

Permalink
Add RGS Rotary Snowplow No. 2, improve legacy frame support (#221)
Browse files Browse the repository at this point in the history
* Fix legacy frame names
* RGS Rotary Snowplow No. 2
  • Loading branch information
scottanderson authored Oct 5, 2024
1 parent ce2c148 commit 05b93a5
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 27 deletions.
63 changes: 36 additions & 27 deletions ts/Studio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ import {
frameCategories,
frameDefinitions,
frameStateMetadata,
getFrameType,
hasCargoLimits,
isCargoType,
isFrameType,
} from './frames';
import {SplineTrackType} from './SplineTrackType';
import {hermiteToBezier, cubicBezierMinRadius} from './util-bezier';
Expand Down Expand Up @@ -308,16 +308,19 @@ export class Studio {
grpFrameList.classList.add('dropdown');
grpFrameList.replaceChildren(btnFrameList, lstFrameList);
lstFrameList.replaceChildren(...railroad.frames.slice().sort((a, b) => {
if (!isFrameType(a.type)) return isFrameType(b.type) ? 1 : 0;
if (!isFrameType(b.type)) return -1;
const ad = frameDefinitions[a.type];
const bd = frameDefinitions[b.type];
const aType = getFrameType(a.type);
const bType = getFrameType(b.type);
if (aType === null) return bType === null ? 1 : 0;
if (bType === null) return -1;
const ad = frameDefinitions[aType];
const bd = frameDefinitions[bType];
return frameCategories.reduceRight((p, c) => ad[c] === bd[c] ? p : ad[c] ? -1 : 1, 0);
}).flatMap((frame, i, a) => {
const btnFrame = document.createElement('button');
const imgFrame = document.createElement('i');
const frameType = getFrameType(frame.type);
const text =
(isFrameType(frame.type) ? frameDefinitions[frame.type].name + ' ' : '') +
(frameType !== null ? frameDefinitions[frameType].name + ' ' : '') +
(frame.number ? '#' + gvasToString(textToString(frame.number)) + ' ' : '') +
(frame.name ? gvasToString(textToString(frame.name)) : '');
const txtFrame = document.createTextNode(` ${text} `);
Expand All @@ -331,9 +334,10 @@ export class Studio {
if (!this.map.getLayerVisibility('frames')) this.map.toggleLayerVisibility('frames');
});
const prevFrame = i > 0 ? a[i - 1] : undefined;
if (prevFrame && isFrameType(frame.type) && isFrameType(prevFrame.type)) {
const prevFrameDef = frameDefinitions[prevFrame.type];
const frameDef = frameDefinitions[frame.type];
const prevFrameType = getFrameType(prevFrame?.type ?? null);
if (prevFrame && frameType !== null && prevFrameType !== null) {
const prevFrameDef = frameDefinitions[prevFrameType];
const frameDef = frameDefinitions[frameType];
if (frameCategories.some((key) => prevFrameDef[key] !== frameDef[key])) {
const li = document.createElement('li');
const hr = document.createElement('hr');
Expand Down Expand Up @@ -742,12 +746,13 @@ export class Studio {
resetFramePage();
};
const frameInCategory = (f: Frame, c: typeof frameCategories[number] | 'unknown') => {
if (c === 'unknown') return !isFrameType(f.type);
if (!isFrameType(f.type)) return false;
return (frameDefinitions[f.type][c] ?? false);
const frameType = getFrameType(f.type);
if (c === 'unknown') return frameType === null;
if (frameType === null) return false;
return (frameDefinitions[frameType][c] ?? false);
};
const numFramesWithUnknownTypes = railroad.frames
.filter((f) => !isFrameType(f.type))
.filter((f) => getFrameType(f.type) === null)
.length;
const labels: Record<string, string> = {
engine: `Engines (${railroad.frames.filter((f) => frameInCategory(f, 'engine')).length})`,
Expand Down Expand Up @@ -779,8 +784,9 @@ export class Studio {
const displayUnknownFrameTypes = numFramesWithUnknownTypes > 0 && checked['unknown'];
const pageSize = 20;
const filteredCategory = railroad.frames.filter((f) => {
if (!isFrameType(f.type)) return displayUnknownFrameTypes;
const d = frameDefinitions[f.type];
const fType = getFrameType(f.type);
if (fType === null) return displayUnknownFrameTypes;
const d = frameDefinitions[fType];
return frameCategories.every((c) => !d[c] || checked[c]);
});
// Create a dropdown entry for each known frame type
Expand All @@ -796,7 +802,7 @@ export class Studio {
const unknownTypes = filteredCategory
.map((f) => f.type)
.filter((v, i, a) => a.indexOf(v) === i)
.filter((t) => !isFrameType(t))
.filter((t) => getFrameType(t) === null)
.filter(Boolean)
.sort((a, b) => -a.toLowerCase().localeCompare(b.toLowerCase()));
for (const unknownType of unknownTypes) {
Expand Down Expand Up @@ -1179,8 +1185,9 @@ export class Studio {
tbody.appendChild(tr);
// Type
let td = document.createElement('td');
if (isFrameType(frame.type)) {
td.textContent = frameDefinitions[frame.type].name;
const frameType = getFrameType(frame.type);
if (frameType !== null) {
td.textContent = frameDefinitions[frameType].name;
} else {
td.textContent = frame.type;
td.classList.add('table-warning');
Expand Down Expand Up @@ -1227,8 +1234,8 @@ export class Studio {
const setFrameRotation = (rotation: Rotator) => frame.rotation = rotation;
addStat('Rotation', editRotator(this, frame.rotation, setFrameRotation));
// Frame state
if (isFrameType(frame.type)) {
const frameDef = frameDefinitions[frame.type];
if (frameType !== null) {
const frameDef = frameDefinitions[frameType];
const editNumericState = (frame: Frame, key: keyof NumericFrameState) => {
if (typeof frame.state[key] === 'undefined') return;
const meta = frameStateMetadata[key];
Expand Down Expand Up @@ -1314,10 +1321,10 @@ export class Studio {
editNumericState(frame, 'markerLightsRearLeftState');
editNumericState(frame, 'markerLightsRearRightState');
// Freight
if (hasCargoLimits(frame.type)) {
if (hasCargoLimits(frameType)) {
const freightType = frame.state.freightType ?? '';
const setAmount = (amount: number) => frame.state.freightAmount = amount;
const limits: Partial<Record<CargoType, number>> = cargoLimits[frame.type];
const limits: Partial<Record<CargoType, number>> = cargoLimits[frameType];
const limit = isCargoType(freightType) ? limits[freightType] ?? 0 : 0;
const max = String(limit);
const options: InputTextOptions = {max, min: '0'};
Expand All @@ -1342,7 +1349,7 @@ export class Studio {
const form = editDropdown(this, freightType, typeOptions, setFreightType);
addStat('Freight Type', form);
} else {
const title = `Unexpected freight type ${freightType} for ${frame.type}`;
const title = `Unexpected freight type ${freightType} for ${frameType}`;
const c = 'table-warning';
const form = editString(this, freightType, setFreightType);
addStat('Freight Type', form, title, c);
Expand All @@ -1369,8 +1376,9 @@ export class Studio {
if (this.railroad.frames.length === 0) return 0;
let modificationCount = 0;
this.railroad.frames.forEach((frame: Frame) => {
if (!isFrameType(frame.type)) return;
const {max} = frameDefinitions[frame.type];
const frameType = getFrameType(frame.type);
if (frameType === null) return;
const {max} = frameDefinitions[frameType];
if (typeof max === 'undefined') return;
if (max.boilerFuelAmount && frame.state.boilerFuelAmount !== max.boilerFuelAmount) {
frame.state.boilerFuelAmount = max.boilerFuelAmount;
Expand All @@ -1389,8 +1397,9 @@ export class Studio {
if (this.railroad.frames.length === 0) return 0;
let modificationCount = 0;
this.railroad.frames.forEach((frame: Frame) => {
if (!isFrameType(frame.type)) return;
const {max} = frameDefinitions[frame.type];
const frameType = getFrameType(frame.type);
if (frameType === null) return;
const {max} = frameDefinitions[frameType];
if (typeof max === 'undefined') return;
if (max.boilerWaterLevel && frame.state.boilerWaterLevel !== max.boilerWaterLevel) {
frame.state.boilerWaterLevel = max.boilerWaterLevel;
Expand Down
47 changes: 47 additions & 0 deletions ts/frames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export const frameTypes = [
'plow',
'Porter_040',
'Porter_042',
'RGS_Rotary',
'RGS_Rotary_Tender',
'Rubybasin',
'shay',
'SideDumpCar',
Expand Down Expand Up @@ -1289,6 +1291,51 @@ export const frameDefinitions: Record<FrameType, FrameDefinition> = {
name: 'Porter 2',
},

'RGS_Rotary': {
coal: true,
engine: true,
length: 1213,
max: {
boilerFireTemp: 400,
boilerFuelAmount: 70,
boilerPressure: 130,
boilerWaterLevel: 2000,
boilerWaterTemp: 170,
brakeValue: 1,
compressorAirPressure: 100,
compressorValveValue: 1,
headlightType: 1,
paintType: 4,
reverserValue: 1,
smokestackType: 1,
},
min: {
headlightType: 1,
paintType: 1,
reverserValue: -1,
smokestackType: 1,
},
name: 'RGS Rotary Snowplow No. 2',
},

'RGS_Rotary_Tender': {
coal: true,
length: 700,
max: {
headlightType: 1,
paintType: 4,
smokestackType: 1,
tenderFuelAmount: 7000,
},
min: {
headlightType: 1,
paintType: 1,
smokestackType: 1,
},
name: 'RGS Rotary Snowplow No. 2 Tender',
tender: true,
},

'Rubybasin': {
coal: true,
engine: true,
Expand Down

0 comments on commit 05b93a5

Please sign in to comment.