Merge pull request #1121 from StempunkDev/vite

options.ts + byId with types
This commit is contained in:
Azgaar 2024-09-03 22:57:49 +02:00 committed by GitHub
commit 2ad1e75cfd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 523 additions and 314 deletions

View file

@ -3,12 +3,7 @@ import * as d3 from "d3";
import { closeDialogs } from "dialogs/utils";
import { layerIsOn, toggleLayer } from "layers";
import { clearMainTip, tip } from "scripts/tooltips";
import {findGridCell, getGridPolygon} from "utils/graphUtils";
import {getInputNumber} from "utils/nodeUtils";
import {rn} from "utils/numberUtils";
import {rand} from "utils/probabilityUtils";
import {byId} from "utils/shorthands";
import {parseTransform} from "utils/stringUtils";
import { byId, findGridCell, getGridPolygon, getInputNumber, parseTransform, rand, rn } from "utils";
// @ts-expect-error js module
import { editStyle } from "modules/style";
import { setDefaultEventHandlers } from "scripts/events";
@ -21,7 +16,7 @@ export function open() {
closeDialogs(".stable");
if (!layerIsOn("toggleIce")) toggleLayer("toggleIce");
elSelected = d3.select(d3.event.target);
const elSelected = d3.select<SVGPolygonElement, any>(d3.event.target);
const type = elSelected.attr("type") ? "Glacier" : "Iceberg";
if (byId("iceRandomize")) byId("iceRandomize")!.style.display = type === "Glacier" ? "none" : "inline-block";
@ -31,7 +26,7 @@ export function open() {
$iceSize.style.display = type === "Glacier" ? "none" : "inline-block";
if (type === "Iceberg") $iceSize.value = elSelected.attr("size");
}
ice.selectAll("*").classed("draggable", true).call(d3.drag().on("drag", dragElement));
ice.selectAll<SVGPolygonElement, any>("*").classed("draggable", true).on("drag", dragElement);
$("#iceEditor").dialog({
title: "Edit " + type,
@ -58,7 +53,7 @@ export function open() {
const cn = grid.points[i];
const poly = getGridPolygon(i).map(p => [p[0] - cn[0], p[1] - cn[1]]);
const points = poly.map(p => [rn(c[0] + p[0] * s, 2), rn(c[1] + p[1] * s, 2)]);
elSelected.attr("points", points);
elSelected.attr("points", points.flat().toString());
}
function changeSize(this: HTMLInputElement) {
@ -74,13 +69,13 @@ export function open() {
const poly = pairs.map(p => [(p[0] - c[0]) / s, (p[1] - c[1]) / s]);
const size = +this.value;
const points = poly.map(p => [rn(c[0] + p[0] * size, 2), rn(c[1] + p[1] * size, 2)]);
elSelected.attr("points", points).attr("size", size);
elSelected.attr("points", points.toString()).attr("size", size);
}
function toggleAdd() {
byId("iceNew")?.classList.toggle("pressed");
if (byId("iceNew")?.classList.contains("pressed")) {
viewbox.style("cursor", "crosshair").on("click", addIcebergOnClick);
viewbox.style("cursor", "crosshair").on("click",() => addIcebergOnClick);
tip("Click on map to create an iceberg. Hold Shift to add multiple", true);
} else {
clearMainTip();
@ -95,8 +90,8 @@ export function open() {
const s = getInputNumber("iceSize");
const points = getGridPolygon(i).map(p => [(p[0] + (c[0] - p[0]) / s) | 0, (p[1] + (c[1] - p[1]) / s) | 0]);
const iceberg = ice.append("polygon").attr("points", points).attr("cell", i).attr("size", s);
iceberg.call(d3.drag().on("drag", dragElement));
const iceberg = ice.append("polygon").attr("points", points.flat().toString()).attr("cell", i).attr("size", s);
iceberg.on("drag", dragElement);
if (d3.event.shiftKey === false) toggleAdd();
}
@ -119,7 +114,7 @@ export function open() {
});
}
function dragElement(this: Element) {
function dragElement(this: SVGPolygonElement) {
const tr = parseTransform(this.getAttribute("transform"));
const dx = +tr[0] - d3.event.x;
const dy = +tr[1] - d3.event.y;
@ -131,7 +126,7 @@ export function open() {
}
function closeEditor() {
ice.selectAll("*").classed("draggable", false).call(d3.drag().on("drag", null));
ice.selectAll("*").classed("draggable", false).on("drag", null);
clearMainTip();
byId("iceNew")?.classList.remove("pressed");
unselect();

View file

@ -3,23 +3,32 @@ import {drawBiomes} from "./drawBiomes";
import {drawBorders} from "./drawBorders";
import {drawBurgs} from "./drawBurgs";
import {drawCells} from "./drawCells";
import {drawCoordinates} from "./drawCoordinates";
// @ts-expect-error js-module
import {drawCoordinates} from "./drawCoordinates.js"; //MARKER: drawCoordinates.js
import {drawCultures} from "./drawCultures";
import {drawEmblems} from "./drawEmblems";
// @ts-expect-error js-module
import {drawEmblems} from "./drawEmblems.js"; //MARKER: drawEmblems.js
import {drawFeatures} from "./drawFeatures";
import {drawGrid} from "./drawGrid";
import {drawHeightmap} from "./drawHeightmap";
import {drawIce} from "./drawIce";
// @ts-expect-error js-module
import {drawGrid} from "./drawGrid.js"; //MARKER: drawGrid.js
// @ts-expect-error js-module
import {drawHeightmap} from "./drawHeightmap.js";
// @ts-expect-error js-module
import {drawIce} from "./drawIce.js"; //MARKER: drawIce.js
import {drawLabels} from "./drawLabels";
import {drawMarkers} from "./drawMarkers";
import {drawPopulation} from "./drawPopulation";
import {drawPrecipitation} from "./drawPrecipitation";
// @ts-expect-error js-module
import {drawMarkers} from "./drawMarkers.js"; //MARKER: drawMarkers.js
// @ts-expect-error js-module
import {drawPopulation} from "./drawPopulation.js"; //MARKER: drawPopulation.js
// @ts-expect-error js-module
import {drawPrecipitation} from "./drawPrecipitation.js"; //MARKER: drawPrecipitation.js
import {drawProvinces} from "./drawProvinces";
import {drawReligions} from "./drawReligions";
import {drawRivers} from "./drawRivers";
import {drawRoutes} from "./drawRoutes";
import {drawStates} from "./drawStates";
import {drawTemperature} from "./drawTemperature";
// @ts-expect-error js-module
import {drawTemperature} from "./drawTemperature.js"; //MARKER: drawTemperature.js
// Note: missed renderers are in toggle functions
const layerRenderersMap = {
@ -46,9 +55,11 @@ const layerRenderersMap = {
temperature: drawTemperature
};
export function renderLayer(layerName: keyof typeof layerRenderersMap, ...args: any[]) {
// export function renderLayer(layerName: keyof typeof layerRenderersMap, ...args: any[]) {
export function renderLayer(layerName: keyof typeof layerRenderersMap) {
const renderer = layerRenderersMap[layerName];
TIME && console.time(renderer.name);
renderer(...args);
// renderer(...args); MARKER: for now we are not passing any arguments
renderer();
TIME && console.timeEnd(renderer.name);
}

View file

@ -9,6 +9,7 @@ import {calculateFriendlyGridSize, editStyle, shiftCompass} from "modules/ui/sty
import {getInputNumber, getInputValue} from "utils/nodeUtils";
import {renderLayer} from "./renderers";
import {layerIsOn, turnLayerButtonOff, turnLayerButtonOn} from "./utils";
import { isCulture, isReligion } from "utils/typeUtils";
const layerTogglesMap = {
toggleBiomes,
@ -187,7 +188,7 @@ function toggleIce(event?: MouseEvent) {
}
function toggleCultures(event?: MouseEvent) {
const cultures = pack.cultures.filter(({i, removed}) => i && !removed);
const cultures = pack.cultures.filter((culture) => isCulture(culture) && !culture.removed);
const empty = !cults.selectAll("path").size();
if (empty && cultures.length) {
turnLayerButtonOn("toggleCultures");
@ -204,7 +205,7 @@ function toggleCultures(event?: MouseEvent) {
}
function toggleReligions(event?: MouseEvent) {
const religions = pack.religions.filter(({i, removed}) => i && !removed);
const religions = pack.religions.filter((religion) => isReligion(religion) && !religion.removed);
if (!relig.selectAll("path").size() && religions.length) {
turnLayerButtonOn("toggleReligions");
renderLayer("religions");
@ -363,7 +364,7 @@ function toggleTexture(event?: MouseEvent) {
function toggleRivers(event?: MouseEvent) {
if (!layerIsOn("toggleRivers")) {
turnLayerButtonOn("toggleRivers");
renderLayer("rivers", pack);
renderLayer("rivers");
if (isCtrlPressed(event)) editStyle("rivers");
} else {
if (isCtrlPressed(event)) return editStyle("rivers");

View file

@ -8,7 +8,6 @@ import {defineSvg} from "./modules/define-svg";
import {clearLegend} from "./modules/legend";
// @ts-expect-error js-module
import {Rulers} from "./modules/measurers";
// @ts-expect-error js-module
import {applyStoredOptions} from "./modules/ui/options";
import {addGlobalListeners} from "./scripts/listeners";
import {checkForUpdates} from "./scripts/updater";
@ -20,7 +19,8 @@ options = {
pinNotes: false,
showMFCGMap: true,
winds: [225, 45, 225, 315, 135, 315],
stateLabelsMode: "auto"
stateLabelsMode: "auto",
year: 0,
};
checkForUpdates();

View file

@ -1,6 +1,6 @@
import {ERROR} from "config/logging";
window.COArenderer = (function () {
export const COArenderer = (function () {
const colors = {
argent: "#fafafa",
or: "#ffe066",

View file

@ -0,0 +1,6 @@
export type DropboxFile = {
name: string,
updated: any, // MARKER: Type unclear
size: number,
path: string
};

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,8 @@ import {openDialog} from "dialogs";
import {tip} from "scripts/tooltips";
import {handleMapClick} from "./onclick";
import {onMouseMove} from "./onhover";
import {clearLegend, dragLegendBox} from "modules/legend";
// @ts-expect-error js-module
import {clearLegend, dragLegendBox} from "modules/legend.js"; //MARKER: modules/legend.js
export function setDefaultEventHandlers() {
window.Zoom.setZoomBehavior();

View file

@ -1,7 +1,7 @@
import * as d3 from "d3";
import {layerIsOn} from "layers";
import {updateCellInfo} from "modules/ui/cell-info";
import {updateCellInfo} from "modules/ui/cell-info.js";
import {debounce} from "utils/functionUtils";
import {findCell, findGridCell, isLand} from "utils/graphUtils";
import {byId} from "utils/shorthands";
@ -16,7 +16,7 @@ import {
} from "utils/unitUtils";
import {showMainTip, tip} from "scripts/tooltips";
import {defineEmblemData} from "./utils";
import {isState} from "utils/typeUtils";
import {isBurg, isProvince, isReligion, isState} from "utils/typeUtils";
export const onMouseMove = debounce(handleMouseMove, 100);
@ -107,7 +107,7 @@ const onHoverEventsMap: OnHoverEventMap = {
const emblemData = defineEmblemData(element);
if (emblemData) {
const {type, el} = emblemData;
const name = ("fullName" in el && el.fullName) || el.name;
const name = el !== 0 && (("fullname" in el && el.fullname) || el.name); //MARKER: el nutral check
tip(`${name} ${type} emblem. Click to edit`);
}
},
@ -127,7 +127,10 @@ const onHoverEventsMap: OnHoverEventMap = {
burg: ({path}) => {
const burgId = +(path.at(-10)?.dataset.id || 0);
const {population, name} = pack.burgs[burgId];
const burg = pack.burgs[burgId];
let population = 0;
const name = burg.name;
isBurg(burg) && (population = burg.population);
tip(`${name}. Population: ${si(getBurgPopulation(population))}. Click to edit`);
highlightDialogLine("burgOverview", burgId, 5000);
@ -153,7 +156,8 @@ const onHoverEventsMap: OnHoverEventMap = {
lake: ({element, subgroup}) => {
const lakeId = +(element.dataset.f || 0);
const name = pack.features[lakeId]?.name;
const lake = pack.features[lakeId];
const name = lake ? (lake as IPackFeatureLake).name : ""; //MARKER: as IPackFeatureLake
const fullName = subgroup === "freshwater" ? name : name + " " + subgroup;
tip(`${fullName} lake. Click to edit`);
},
@ -187,7 +191,8 @@ const onHoverEventsMap: OnHoverEventMap = {
religionsLayer: ({packCellId}) => {
const religionId = pack.cells.religion[packCellId];
const {type, name} = pack.religions[religionId] || {};
const religion = pack.religions[religionId];
const {type, name} = isReligion(religion) ? religion : {type: "None", name: "None"}; //MARKER: religion check
const typeTip = type === "Cult" || type == "Heresy" ? type : type + " religion";
tip(`${typeTip}: ${name}`);
@ -200,7 +205,8 @@ const onHoverEventsMap: OnHoverEventMap = {
const stateName = isState(state) ? state.fullName : state.name;
const provinceId = pack.cells.province[packCellId];
const provinceName = provinceId ? `${pack.provinces[provinceId].fullName}, ` : "";
const province = pack.provinces[provinceId];
const provinceName = isProvince(province) ? `${province.fullName}, ` : "";
tip(provinceName + stateName);
highlightDialogLine("statesEditor", stateId);

View file

@ -8,7 +8,6 @@ import {initLayers, renderLayer, restoreLayers} from "layers";
import {drawScaleBar, Rulers} from "modules/measurers";
// @ts-expect-error js module
import {unfog} from "modules/ui/editors";
// @ts-expect-error js module
import {applyMapSize, randomizeOptions} from "modules/ui/options";
// @ts-expect-error js module
import {applyStyleOnLoad} from "modules/ui/stylePresets";
@ -26,10 +25,11 @@ import {createGrid} from "./grid/grid";
import {createPack} from "./pack/pack";
import {getInputValue, setInputValue} from "utils/nodeUtils";
import {calculateMapCoordinates} from "modules/coordinates";
import { isBurg } from "utils/typeUtils";
const {Zoom, ThreeD} = window;
interface IGenerationOptions {
export interface IGenerationOptions {
seed: string;
graph: IGrid;
}
@ -195,6 +195,7 @@ function focusOn() {
if (burgParam) {
const burg = isNaN(+burgParam) ? pack.burgs.find(burg => burg.name === burgParam) : pack.burgs[+burgParam];
if (!burg) return;
if (!isBurg(burg)) return;
const {x, y} = burg;
Zoom.to(x, y, scale, 1600);
@ -209,8 +210,8 @@ function focusOn() {
// find burg for MFCG and focus on it
function findBurgForMFCG(params: URLSearchParams) {
const {cells, burgs} = pack;
const {cells, burgs: burgsT} = pack;
const burgs = burgsT.filter(isBurg);
if (pack.burgs.length < 2) {
ERROR && console.error("Cannot select a burg for MFCG");
return;
@ -247,13 +248,13 @@ function findBurgForMFCG(params: URLSearchParams) {
if (param === "name") b.name = value;
else if (param === "size") b.population = +value;
else if (param === "seed") b.MFCG = +value;
else if (param === "shantytown") b.shanty = +value;
else if (param === "shantytown") b.shanty = +value > 0 ? 1 : 0;
}
const nameParam = params.get("name");
if (nameParam && nameParam !== "null") b.name = nameParam;
const label = burgLabels.select("[data-id='" + burgId + "']");
const label = burgLabels.select<Element>("[data-id='" + burgId + "']");
if (label.size()) {
label
.text(b.name)

View file

@ -77,7 +77,6 @@ export const culturalTheocracyFormsMap: {[key: number]: {[key in TMonarchyForms]
[NB.Roman]: Catholic,
[NB.Portuguese]: Catholic,
[NB.Ruthenian]: Orthodox,
[NB.Ruthenian]: Orthodox,
[NB.Turkish]: Islamic,
[NB.Nigerian]: Islamic,
[NB.Berber]: Islamic,

View file

@ -35,8 +35,8 @@ export function generateCoreProvinces(states: TStates, burgs: TBurgs, cultures:
const fullName = name + " " + formName;
const color = brighter(getMixedColor(state.color, 0.2), 0.3);
const coa = generateEmblem(nameByBurg, burgEmblem, type, cultures, cultureId, state);
provinces.push({i: provinces.length + 1, name, formName, center, burg, state: state.i, fullName, color, coa});
const province : IProvince = {i: provinces.length + 1, name, formName, center, burg, state: state.i, fullName, color, coa,pole: state.pole};
provinces.push(province);
}
});

View file

@ -54,8 +54,8 @@ export function generateWildProvinces({
const coa = generateEmblem(formName, state, burg, cultureId);
const color = brighter(getMixedColor(state.color, 0.2), 0.3);
wildProvinces.push({i: provinceId, name, formName, center, burg: burgId, state: state.i, fullName, color, coa});
const province : IProvince = {i: provinceId, name, formName, center, burg: burgId, state: state.i, fullName, color, coa, pole: state.pole};
wildProvinces.push(province);
// re-check
noProvinceCellsInState = noProvinceCells.filter(i => cells.state[i] === state.i && !provinceIds[i]);

View file

@ -3,7 +3,6 @@ import {addOnLoadListener} from "./loading";
import {assignLockBehavior} from "./options/lock";
import {addTooptipListers} from "./tooltips";
import {assignSpeakerBehavior} from "./speaker";
// @ts-ignore
import {addResizeListener} from "modules/ui/options";
// @ts-ignore
import {addDragToUpload} from "modules/io/load";

View file

@ -41,7 +41,7 @@ export function lock(id: string) {
}
// unlock option
function unlock(id: string) {
export function unlock(id: string) {
localStorage.removeItem(id);
const $lock = document.getElementById("lock_" + id);
if ($lock) {

View file

@ -23,9 +23,12 @@ declare let options: IOptions;
interface IOptions {
pinNotes: boolean;
showMFCGMap: boolean;
winds: [number, number, number, number, number, number];
winds: number[];
stateLabelsMode: "auto" | "short" | "full";
year: number;
era: string;
eraShort: string;
military: any; //MARKER any
}
declare let populationRate: number;

View file

@ -29,6 +29,7 @@ interface Window {
Markers: any;
COA: any;
Routes: any;
Cloud: any;
}
interface Node {

View file

@ -9,7 +9,7 @@ interface IBurg {
y: number;
population: number;
type: TCultureType;
coa: ICoa | "string";
coa: ICoa | "custom";
capital: Logical; // 1 - capital, 0 - burg
port: number; // port feature id, 0 - not a port
citadel: Logical;

View file

@ -8,7 +8,7 @@ interface IProvince {
state: number;
center: number;
pole: TPoint;
coa: ICoa | string;
coa: ICoa | "custom";
removed?: boolean;
}

View file

@ -11,7 +11,7 @@ interface IState {
formName: string;
fullName: string;
pole: TPoint;
coa: ICoa | string;
coa: ICoa | "custom";
area: number;
cells: number;
burgs: number;

18
src/utils/index.ts Normal file
View file

@ -0,0 +1,18 @@
export * from "./arrayUtils";
export * from "./colorUtils";
export * from "./coordinateUtils";
export * from "./debugUtils";
export * from "./errorUtils";
export * from "./functionUtils";
export * from "./graphUtils";
export * from "./keyboardUtils";
export * from "./languageUtils";
export * from "./lineUtils";
export * from "./linkUtils";
export * from "./nodeUtils";
export * from "./numberUtils";
export * from "./probabilityUtils";
export * from "./shorthands";
export * from "./stringUtils";
export * from "./typeUtils";
export * from "./unitUtils";

View file

@ -1,4 +1,25 @@
import {byId} from "./shorthands";
export type ElementMap = {
a: HTMLAnchorElement;
button: HTMLButtonElement;
div: HTMLDivElement;
img: HTMLImageElement;
input: HTMLInputElement;
output: HTMLOutputElement;
select: HTMLSelectElement;
canvas: HTMLCanvasElement;
// add more types as needed
};
// function definition with overloads to account for different options
export function byId<K extends keyof ElementMap>(id: string): ElementMap[K];
export function byId<K extends keyof ElementMap>(id: string, options?: {throwOnNull: false}): ElementMap[K] | null;
export function byId<K extends keyof ElementMap>(id: string, options = {throwOnNull: true}) {
const element = document.getElementById(id);
if (!element && options.throwOnNull) {
throw new Error(`Element ${id} not found`);
}
return element as ElementMap[K] | null;
}
// get next unused id
export function getNextId(core: string, index = 1) {

View file

@ -1,6 +1,7 @@
import {rn} from "./numberUtils";
import {findCell, findGridCell} from "./graphUtils";
import {getInputNumber, getInputValue} from "./nodeUtils";
import { isBurg } from "./typeUtils";
// ***
// SI
@ -136,7 +137,8 @@ export function getBurgPopulationPoints(burgPopulationValue: number) {
export function getCellPopulation(cellId: number) {
const rural = getRuralPopulation(pack.cells.pop[cellId]);
const burgId = pack.cells.burg[cellId];
const urban = burgId ? getBurgPopulation(pack.burgs[burgId].population) : 0;
const burg = pack.burgs[burgId];
const urban = isBurg(burg) ? getBurgPopulation(burg.population) : 0;
return [rural, urban];
}

View file

@ -15,8 +15,9 @@
"noUnusedParameters": true,
"noImplicitReturns": true,
"skipLibCheck": true,
"types": ["vitest/globals"],
"baseUrl": "src"
"types": ["vitest/globals","jquery","jqueryui"],
"baseUrl": "src",
"allowJs": false,
},
"include": ["src"]
}