102 lines
3.1 KiB
TypeScript
102 lines
3.1 KiB
TypeScript
import * as tinycolor from 'tinycolor2';
|
|
|
|
import Direction, { getPointDirection } from './Direction';
|
|
import LineConnection from './LineConnection';
|
|
import { distance, randomPoint, weightedRandom } from './utils';
|
|
|
|
let stationCount = 0;
|
|
|
|
export default class Station {
|
|
// Utility methods for working with arrays of Stations
|
|
public static largestStation(stations: Station[]): Station {
|
|
let largest: Station = null;
|
|
for (const station of stations) {
|
|
if (largest === null || station.population > largest.population) {
|
|
largest = station;
|
|
}
|
|
}
|
|
return largest;
|
|
}
|
|
|
|
public static stationsWithinRadius(stations: Station[], point: PIXI.Point,
|
|
radius: number): Station[] {
|
|
return stations.filter(station => distance(point, station.location) <= radius);
|
|
}
|
|
|
|
public static stationsInDirection(stations: Station[], point: PIXI.Point,
|
|
direction: Direction): Station[] {
|
|
return stations.filter(station => getPointDirection(point, station.location) === direction);
|
|
}
|
|
|
|
public static closestStation(stations: Station[], point: PIXI.Point): Station {
|
|
return stations.reduce(
|
|
(prev, curr) => distance(point, prev.location) < distance(point, curr.location) ? prev : curr,
|
|
);
|
|
}
|
|
|
|
public static randomCloseLargeStation(stations: Station[], point: PIXI.Point,
|
|
radius: number): Station {
|
|
const closeStations = Station.stationsWithinRadius(stations, point,
|
|
radius);
|
|
const closeStationWeights = closeStations.map(station => station.population);
|
|
return weightedRandom(closeStations, closeStationWeights);
|
|
}
|
|
|
|
public static isPointDistant(point: PIXI.Point, stations: Station[],
|
|
minDistance: number): boolean {
|
|
for (const station of stations) {
|
|
if (distance(point, station.location) < minDistance) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public static randomDistantPoint(stations: Station[], minDistance: number): PIXI.Point | null {
|
|
let tries = 100;
|
|
while (tries > 0) {
|
|
const point = randomPoint();
|
|
if (Station.isPointDistant(point, stations, minDistance)) {
|
|
return point;
|
|
}
|
|
tries -= 1;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public location: PIXI.Point;
|
|
public population: number;
|
|
public connections: LineConnection[];
|
|
public id: number;
|
|
public label: PIXI.Text;
|
|
public color: tinycolorInstance;
|
|
|
|
private textStyle: object;
|
|
|
|
constructor(
|
|
location: PIXI.Point,
|
|
population: number,
|
|
color: tinycolorInstance,
|
|
connections?: LineConnection[],
|
|
) {
|
|
this.location = location;
|
|
this.population = population;
|
|
this.color = color;
|
|
this.connections = connections || [];
|
|
|
|
// for debugging
|
|
stationCount += 1;
|
|
this.id = stationCount;
|
|
this.textStyle = {
|
|
fill: '#FFA500',
|
|
fontFamily: 'monospace',
|
|
fontSize: '12px',
|
|
};
|
|
this.renderLabel();
|
|
}
|
|
|
|
public renderLabel() {
|
|
this.label = new PIXI.Text(`${this.id}`, this.textStyle);
|
|
}
|
|
}
|