1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
// ==============================================================================
// Copyright (C) 2019 - Philip Paquette, Steven Bocco
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option) any
// later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License along
// with this program. If not, see <https://www.gnu.org/licenses/>.
// ==============================================================================
const ProvinceType = {
WATER: 'WATER',
COAST: 'COAST',
PORT: 'PORT',
LAND: 'LAND'
};
export class Province {
constructor(name, type, isSupplyCenter) {
this.name = name;
this.type = type;
this.coasts = {};
this.parent = null;
this.neighbors = {};
this.isSupplyCenter = isSupplyCenter;
this.controller = null; // null or power name.
this.controlType = null; // null, C (center), I (influence) or U (unit).
this.unit = null; // null, A or F
this.retreatController = null;
this.retreatUnit = null; // null or `{unit type} {loc}`
this.aliases = [];
}
compareControlType(a, b) {
const controlTypeLevels = {C: 0, I: 1, U: 2};
return controlTypeLevels[a] - controlTypeLevels[b];
}
__set_controller(controller, controlType) {
this.controller = controller;
this.controlType = controlType;
for (let coast of Object.values(this.coasts))
coast.setController(controller, controlType);
}
setController(controller, controlType) {
if (!['C', 'I', 'U'].includes(controlType))
throw new Error(`Invalid province control type (${controlType}), expected 'C', 'I' or 'U'.`);
if (this.controller && this.controller !== controller) {
const controlTypeComparison = this.compareControlType(controlType, this.controlType);
if (controlTypeComparison === 0)
throw new Error(`Found 2 powers (${this.controller}, ${controller}) trying to control same province ` +
`(${this.name}) with same control type (${controlType} VS ${this.controlType}).`);
if (controlTypeComparison > 0)
this.__set_controller(controller, controlType);
} else
this.__set_controller(controller, controlType);
}
setCoasts(provinces) {
const name = this.name.toUpperCase();
for (let entry of Object.entries(provinces)) {
const pieces = entry[0].split(/[^A-Za-z0-9]+/);
if (pieces.length > 1 && pieces[0].toUpperCase() === name) {
this.coasts[entry[0]] = entry[1];
entry[1].parent = this;
}
}
}
setNeighbors(neighborProvinces) {
for (let province of neighborProvinces)
this.neighbors[province.name] = province;
}
getLocationNames() {
const arr = Object.keys(this.coasts);
arr.splice(0, 0, this.name);
return arr;
}
getOccupied(powerName) {
if (!this.controller)
return null;
if (powerName && this.controller !== powerName)
return null;
if (this.unit)
return this;
for (let coast of Object.values(this.coasts))
if (coast.unit)
return coast;
return null;
}
getRetreated(powerName) {
if (this.retreatController === powerName)
return this;
for (let coast of Object.values(this.coasts))
if (coast.retreatController === powerName)
return coast;
return null;
}
isCoast() {
return this.type === ProvinceType.COAST;
}
isWater() {
return this.type === ProvinceType.WATER;
}
}
|