From ccb75570dae7101d82bdc5c852298012a746ca3e Mon Sep 17 00:00:00 2001
From: Ilia Pushkin <85931237+Kerravitarr@users.noreply.github.com>
Date: Thu, 3 Feb 2022 10:21:50 +0300
Subject: [PATCH 1/7] Graph of temperature changes for the year in the burg
(#733)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Option for exporting grid cell (#731)
* Added Save Option for Api-like json export.
Will be updated and set to a scheme
* Save Option for Api-like added
* Moved UI of json export to export dialog.
Moved json export to another file named export-json.js
* Added Seperated json export selections
- all JSON : exports all json data.
- minimal JSON : exports json data without cells data.
- cells JSON : exports json data only with pack.cells data.
* More Stable Cell Export...
* Grid cells export option.
* Graph of temperature changes for the year in the burg
I'm bad at writing in English. Please excuse me for this.
It seems illogical to me the parameter of the average temperature for the year in the burg.
Therefore, I found a database of meteorological measurements at https://ru.climate-data.org/
And I analyzed it. With the help of a neural network. I approximately established the dependence of Dy[X] and Dd[X], Md[X] = f(t,p,l).
Dy[X] - how much the temperature in winter differs from the temperature in summer
Md[X] - how much the temperature during the day differs from the temperature at night, on average per year
Dd[X] - how much the temperature difference between day and night is not constant in winter and summer
t - average temperature for the year
p - average rainfall for the year
l - latitude
Now, for each city, you can plot the temperature change. Based on t,p and l.
ATTENTION!!!
The characteristics of the planet and its orbit coincide with those of the earth!
Further, I will use the Russian language, if you want to know my reasoning, please use the Google Translate capabilities.
Я изменил свою первоначальную идею и доработал её. Что касается качества и используемых функций - жду критики. JavaScript - не знакомый мне язык и я не уверен, что выполнил всё верно.
Что касается самой идеи - её реализация пока далека от совершенства. Я понял, что если установить в настройках мира температуру на экваторе ниже, чем на Земле, то графики получаются слишком далекими от реальности. Эта ошибка связана с тем, что Dy[X] зависит от широты, а не среднегодовой температуры. К сожалению добиться хорошей сходимости удалось только расширением нейросети - ещё больше магических чисел.
Теперь, на основе прошлой выборки из 899 городов, попущенных через нейросеть миллион раз среднеквадратичная ошибка стала 3%.
Входными данными для сети являются широта и влажность, а средняя температура иcпользуется только как ориентир при построении графиков.
* Add legnd in graph
* Editing Coefficients
The coefficients have been changed so that the sign of the latitude does not affect the result
Co-authored-by: Efruz Yıldırır <30903352+yldrefruz@users.noreply.github.com>
---
index.html | 5 +-
modules/export-json.js | 35 ++++-
modules/ui/burg-editor.js | 6 +
modules/ui/temperature-graph.js | 220 ++++++++++++++++++++++++++++++++
4 files changed, 259 insertions(+), 7 deletions(-)
create mode 100644 modules/ui/temperature-graph.js
diff --git a/index.html b/index.html
index b8bcb074..14c5f5ea 100644
--- a/index.html
+++ b/index.html
@@ -2085,6 +2085,7 @@
+
@@ -3611,7 +3612,8 @@
full
minimal
- cells
+ pack cells
+ grid cells
Export in JSON format can be used as an API replacement.
@@ -4425,6 +4427,7 @@
+
diff --git a/modules/export-json.js b/modules/export-json.js
index b4c62916..28d87a09 100644
--- a/modules/export-json.js
+++ b/modules/export-json.js
@@ -5,7 +5,8 @@ function exportToJson(type) {
const typeMap = {
Full: getFullDataJson,
Minimal: getMinimalDataJson,
- Cells: getCellsDataJson
+ PackCells: getPackCellsDataJson,
+ GridCells: getGridCellsDataJson,
};
const mapData = typeMap[type]();
@@ -64,7 +65,7 @@ function getSettings() {
return settings;
}
-function getCellsData() {
+function getPackCellsData() {
const cellConverted = {
i: Array.from(pack.cells.i),
v: pack.cells.v,
@@ -91,7 +92,6 @@ function getCellsData() {
religion: Array.from(pack.cells.religion),
province: Array.from(pack.cells.province)
};
-
const cellObjArr = [];
{
cellConverted.i.forEach(value => {
@@ -140,12 +140,24 @@ function getCellsData() {
return cellsData;
}
+//data only containing graphical appearance
+function getGridCellsData(){
+ const gridData = {
+ spacing: grid.spacing,
+ cellsY: grid.cellsY,
+ cellsX: grid.cellsX,
+ points: grid.points,
+ boundary: grid.boundary
+ }
+ return gridData
+}
+
function getFullDataJson() {
TIME && console.time("getFullDataJson");
const info = getMapInfo();
const settings = getSettings();
- const cells = getCellsData();
+ const cells = getPackCellsData();
const exportData = {info, settings, coords: mapCoordinates, cells, biomes: biomesData, notes, nameBases};
TIME && console.timeEnd("getFullDataJson");
@@ -174,13 +186,24 @@ function getMinimalDataJson() {
return JSON.stringify(exportData);
}
-function getCellsDataJson() {
+function getPackCellsDataJson() {
TIME && console.time("getCellsDataJson");
const info = getMapInfo();
- const cells = getCellsData();
+ const cells = getPackCellsData();
const exportData = {info, cells};
TIME && console.timeEnd("getCellsDataJson");
return JSON.stringify(exportData);
}
+
+function getGridCellsDataJson() {
+ TIME && console.time("getGridCellsDataJson");
+
+ const info = getMapInfo();
+ const gridCells = getGridCellsData()
+ const exportData = {info,gridCells};
+
+ TIME && console.log("getGridCellsDataJson");
+ return JSON.stringify(exportData);
+}
\ No newline at end of file
diff --git a/modules/ui/burg-editor.js b/modules/ui/burg-editor.js
index 1a2bef17..fff6c4ee 100644
--- a/modules/ui/burg-editor.js
+++ b/modules/ui/burg-editor.js
@@ -52,6 +52,7 @@ function editBurg(id) {
document.getElementById("burglLegend").addEventListener("click", editBurgLegend);
document.getElementById("burgLock").addEventListener("click", toggleBurgLockButton);
document.getElementById("burgRemove").addEventListener("click", removeSelectedBurg);
+ document.getElementById("burgTemperatureGraph").addEventListener("click", showTemperatureGraphs);
function updateBurgValues() {
const id = +elSelected.attr("data-id");
@@ -542,6 +543,11 @@ function editBurg(id) {
const name = elSelected.text();
editNotes("burg" + id, name);
}
+ function showTemperatureGraphs() {
+ const id = elSelected.attr("data-id");
+ showTGForBurg(id);
+ }
+
function removeSelectedBurg() {
const id = +elSelected.attr("data-id");
diff --git a/modules/ui/temperature-graph.js b/modules/ui/temperature-graph.js
new file mode 100644
index 00000000..f4a236fa
--- /dev/null
+++ b/modules/ui/temperature-graph.js
@@ -0,0 +1,220 @@
+"use strict";
+
+function showTGForBurg(id) {
+ const b = pack.burgs[id];
+ const lat = mapCoordinates.latN - (b.y / graphHeight) * mapCoordinates.latT;
+ const temperature = grid.cells.temp[pack.cells.g[b.cell]];
+ const prec = grid.cells.prec[pack.cells.g[b.cell]];
+
+ const weights = [
+ [//Layer0
+ //IN0 IN1
+ [10.782752257744338, 2.7100404240962126],
+ [-2.8226802110591462, 51.62920138583541],
+ [-6.6250956268643835, 4.427939197315455],
+ [-59.64690518541339, 41.89084162654791],
+ [-1.3302059550553835, -3.6964487738450913],
+ [-2.5844898544535497, 0.09879268612455298],
+ [-5.58528252533573, -0.23426224364501905],
+ [26.94531337690372, 20.898158905988907],
+ [3.816397481634785, -0.19045424064580757],
+ [-4.835697931609101, -10.748232783636434]
+ ],
+ [//Layer1
+ [-2.478952081870123, 0.6405800134306895, -7.136785640930911, -0.2186529024764509, 3.6568435212735424, 31.446026153530838, -19.91005187482281, 0.2543395274783306, -7.036924569659988, -0.7721371621651565],
+ [-197.10583739743538, 6.889921141533474, 0.5058941504631129, 7.7667203434606416, -53.74180550086929, -15.717331715167001, -61.32068414155791, -2.259728220978728, 35.84049189540032, 94.6157364730977],
+ [-5.312011591880851, -0.09923148954215096, -1.7132477487917586, -22.55559652066422, 0.4806107280554336, -26.5583974109492, 2.0558257347014863, 25.815645234787432, -18.569029876991156, -2.6792003366730035],
+ [20.706518520569514, 18.344297403881875, 99.52244671131733, -58.53124969563653, -60.74384321042212, -80.57540534651835, 7.884792406540866, -144.33871131678563, 80.134199744324, 20.50745285622448],
+ [-52.88299538575159, -15.782505343805528, 16.63316001054924, 88.09475330556671, -17.619552086641818, -19.943999528182427, -120.46286026828177, 19.354752020806302, 43.49422099308949, 28.733924806541363],
+ [-2.4621368711159897, -1.2074759925679757, -1.5133898639835084, 2.173715352424188, -5.988707597991683, 3.0234147182203843, 3.3284199340000797, -1.8805161326360575, 5.151910934121654, -1.2540553911612116]
+ ],
+ [//Layer2
+ [-0.3357437479474717, 0.01430651794222215, -0.7927524256670906, 0.2121636229648523, 1.0587803023358318, -3.759288325505095],
+ [-1.1988028704442968, 1.3768997508052783, -3.8480086358278816, 0.5289387340947143, 0.5769459339961177, -1.2528318145750772],
+ [1.0074966649240946, 1.155301164699459, -2.974254371052421, 0.47408176553219467, 0.5939042688615264, -0.7631976947131744]
+ ]
+ ];
+ //From (-∞,∞) to ~[-1,1]
+ const In1 = [(Math.abs(lat) - 26.950680212887473)/48.378128506956,(prec - 12.229929140832644)/29.94402033696607];
+
+ let lastIn = In1;
+ let lstOut = [];
+ for (let levelN = 0; levelN < weights.length ; levelN++) {
+ let layerN = weights[levelN];
+ for (let i = 0; i < layerN.length ; i++) {
+ lstOut[i] = 0;
+ for (let j = 0; j < layerN[i].length ; j++)
+ lstOut[i] = lstOut[i] + lastIn[j]*layerN[i][j] ;
+ //Sigmoid
+ lstOut[i] = 1/(1+Math.exp(-lstOut[i]));
+ }
+ lastIn = lstOut.slice(0);
+ }
+
+ //From [0,1] to [min,max]
+ //Standard deviation for average temperature for the year
+ const yearSig = lstOut[0]*62.9466411977018+0.28613807855649165;
+ //Standard deviation for the difference between the minimum and maximum temperatures for the year
+ const yearDelTmpSig = (lstOut[1]*13.541688670361175+0.1414213562373084) > yearSig ? yearSig : (lstOut[1]*13.541688670361175+0.1414213562373084);
+ //Expected value for the difference between the minimum and maximum temperatures for the year
+ const yearDelTmpMu = lstOut[2]*15.266666666666667+0.6416666666666663;
+
+ //Temperature change shape
+ //const formTmp = -Math.cos(data*2*Math.PI) / 2;
+ const delT = yearDelTmpMu/2+0.5*yearDelTmpSig/2;
+ const minT = temperature - ((yearSig+delT) > 15 ? (yearSig+delT) : 15);
+ const maxT = temperature + (temperature - minT);
+
+ const chartWidth = window.innerWidth/2,
+ chartHeight = 300; // height of our land/sea profile, excluding the biomes data below
+ const xOffset = 80,
+ yOffset = 10; // this is our drawing starting point from top-left (y = 0) of SVG
+
+ const xscale = d3.scaleLinear().domain([0,360]).range([0, chartWidth]);
+ const xscale_inv = d3.scaleLinear().domain([0, chartWidth]).range([0,360]);
+ const yscale = d3.scaleLinear().domain([minT, maxT]).range([chartHeight, 0]);
+ const yscale_inv = d3.scaleLinear().domain([chartHeight, 0]).range([minT, maxT]);
+
+ const dataAverTmp = [];
+ const dataMinTmp = [];
+ const dataMaxTmp = [];
+ for (let i = 0; i < 360 ; i++) {
+ let formTmp = Math.cos(i/360*2*Math.PI) / 2;
+ if(lat > 0) formTmp = -formTmp;
+ const averT = formTmp * yearSig + temperature;
+ const delT = yearDelTmpMu/2+formTmp*yearDelTmpSig/2;
+ dataAverTmp.push({x:xscale(i) + xOffset,y:yscale(averT) + yOffset});
+ dataMinTmp.push({x:xscale(i) + xOffset,y:yscale(averT-delT) + yOffset});
+ dataMaxTmp.push({x:xscale(i) + xOffset,y:yscale(averT+delT) + yOffset});
+ }
+
+ document.getElementById("epControls").style.visibility = "hidden";
+
+ $("#elevationProfile").dialog({
+ title: "Seasonal temperature schedule",
+ resizable: false,
+ width: window.width,
+ close: closeTGForBurg,
+ position: {my: "left top", at: "left+20 bottom-500", of: window, collision: "fit"}
+ });
+
+ draw();
+
+ function draw() {
+
+ document.getElementById("elevationGraph").innerHTML = "";
+ const legendSize = 60;
+ const chart = d3
+ .select("#elevationGraph")
+ .append("svg")
+ .attr("width", chartWidth + 120)
+ .attr("height", chartHeight + yOffset + legendSize)
+ .attr("id", "elevationSVG")
+ .attr("class", "epbackground");
+ // arrow-head definition
+ chart.append("defs").append("marker").attr("id", "arrowhead").attr("orient", "auto").attr("markerWidth", "2").attr("markerHeight", "4").attr("refX", "0.1").attr("refY", "2");
+
+ let Gen = d3.line().curve(d3.curveBasis).x((p) => p.x).y((p) => p.y);
+
+ //print graphs
+ chart.append("g").append("path").attr("d", Gen(dataAverTmp))
+ .attr("fill", "none").attr("stroke", "orange").on("mousemove", printVal).style("stroke-width", "2");
+ chart.append("g").append("path").attr("d", Gen(dataMinTmp))
+ .attr("fill", "none").attr("stroke", "blue").on("mousemove", printVal).style("stroke-width", "2");
+ chart.append("g").append("path").attr("d", Gen(dataMaxTmp))
+ .attr("fill", "none").attr("stroke", "red").on("mousemove", printVal).style("stroke-width", "2");
+
+ //print legend
+ chart.append("circle").attr("cx",chartWidth*1/4).attr("cy",chartHeight + yOffset + legendSize*0.8).attr("r", 4).style("fill", "red")
+ chart.append("text").attr("x", chartWidth*1/4+20).attr("y", chartHeight + yOffset + legendSize*0.8)
+ .text("Day temperature").style("font-size", "10px").attr("alignment-baseline","middle")
+ chart.append("circle").attr("cx",chartWidth*2/4).attr("cy",chartHeight + yOffset + legendSize*0.8).attr("r", 4).style("fill", "orange")
+ chart.append("text").attr("x", chartWidth*2/4+20).attr("y", chartHeight + yOffset + legendSize*0.8)
+ .text("Average daily temperature").style("font-size", "10px").attr("alignment-baseline","middle")
+ chart.append("circle").attr("cx",chartWidth*3/4).attr("cy",chartHeight + yOffset + legendSize*0.8).attr("r", 4).style("fill", "blue")
+ chart.append("text").attr("x", chartWidth*3/4+20).attr("y", chartHeight + yOffset + legendSize*0.8)
+ .text("Night temperature").style("font-size", "10px").attr("alignment-baseline","middle")
+
+
+
+ //print title
+ let timerId = setTimeout(() => chart.attr("data-tip", "Seasonal temperature schedule"), 1000);
+
+ const months = ["January","February","March","April","May","June","July","August","September","October","November","December"];
+ //Val under line
+ function printVal(){
+ let m = d3.mouse(this);
+ let tmp = convertTemperature(yscale_inv(m[1]-yOffset).toFixed(1));
+ let month = months[parseInt(xscale_inv(m[0]-xOffset)/360*12)];
+ chart.attr("data-tip", tmp + " in " + month);
+ clearTimeout(timerId);
+ timerId = setTimeout(() => chart.attr("data-tip", "Seasonal temperature schedule"), 1000);
+ }
+
+ const xAxis = d3
+ .axisBottom(xscale)
+ .ticks(10)
+ .tickFormat(function (d) {
+ return months[parseInt(d/360*12)];
+ });
+ const yAxis = d3
+ .axisLeft(yscale)
+ .ticks(5)
+ .tickFormat(function (d) {
+ return convertTemperature(d);
+ });
+
+ const xGrid = d3.axisBottom(xscale).ticks(10).tickSize(-chartHeight).tickFormat("");
+ const yGrid = d3.axisLeft(yscale).ticks(5).tickSize(-chartWidth).tickFormat("");
+
+ chart
+ .append("g")
+ .attr("id", "epxaxis")
+ .attr("transform", "translate(" + xOffset + "," + parseInt(chartHeight + +yOffset + 20) + ")")
+ .call(xAxis)
+ .selectAll("text")
+ .style("text-anchor", "center")
+ .attr("transform", function (d) {
+ return "rotate(0)"; // used to rotate labels, - anti-clockwise, + clockwise
+ });
+
+ chart
+ .append("g")
+ .attr("id", "epyaxis")
+ .attr("transform", "translate(" + parseInt(+xOffset - 10) + "," + parseInt(+yOffset) + ")")
+ .call(yAxis);
+
+ // add the X gridlines
+ chart
+ .append("g")
+ .attr("id", "epxgrid")
+ .attr("class", "epgrid")
+ .attr("stroke-dasharray", "4 1")
+ .attr("transform", "translate(" + xOffset + "," + parseInt(chartHeight + +yOffset) + ")")
+ .call(xGrid);
+
+ if(minT < 0 && maxT > 0){
+ //add zero lv
+ chart.append("g").append("line")
+ .attr("x1", xscale(0) + xOffset)
+ .attr("y1", yscale(0) + yOffset)
+ .attr("x2", xscale(360) + xOffset)
+ .attr("y2", yscale(0) + yOffset)
+ .attr("stroke", "black");
+ }
+
+ // add the Y gridlines
+ chart
+ .append("g")
+ .attr("id", "epygrid")
+ .attr("class", "epgrid")
+ .attr("stroke-dasharray", "4 1")
+ .attr("transform", "translate(" + xOffset + "," + yOffset + ")")
+ .call(yGrid);
+ }
+ function closeTGForBurg() {
+ document.getElementById("epControls").style.visibility = "visible";
+ document.getElementById("elevationGraph").innerHTML = "";
+ modules.elevation = false;
+ }
+}
\ No newline at end of file
From 5f0be0401e336cedf924c23ecc46e19a72e9b787 Mon Sep 17 00:00:00 2001
From: Azgaar
Date: Fri, 4 Feb 2022 00:13:10 +0300
Subject: [PATCH 2/7] burg temperature graph - corrections
---
index.html | 100 ++++-----
modules/ui/burg-editor.js | 10 +-
modules/ui/temperature-graph.js | 352 ++++++++++++++++++--------------
3 files changed, 253 insertions(+), 209 deletions(-)
diff --git a/index.html b/index.html
index 14c5f5ea..6dc479f1 100644
--- a/index.html
+++ b/index.html
@@ -1799,7 +1799,7 @@
Curve:
Linear
- Basis spline
+ Basis spline
Bundle
Cubic Catmull-Rom
Monotone X
@@ -1990,61 +1990,62 @@
-
-
+
+
-
+
-
-
Type:
-
- Generic
- River
- Lake
- Naval
- Nomadic
- Hunting
- Highland
-
-
+
+
Type:
+
+ Generic
+ River
+ Lake
+ Naval
+ Nomadic
+ Hunting
+ Highland
+
+
-
+
-
+
-
-
Features:
-
-
-
-
-
-
-
-
+
+
Features:
+
+
+
+
+
+
+
+
-
-
Temperature:
-
, like in
-
-
+
+
Temperature:
+
, like in
+
+
+
-
-
Elevation:
-
above sea level
-
+
+
Elevation:
+
above sea level
+
@@ -2085,7 +2086,6 @@
-
diff --git a/modules/ui/burg-editor.js b/modules/ui/burg-editor.js
index fff6c4ee..8ec8b61a 100644
--- a/modules/ui/burg-editor.js
+++ b/modules/ui/burg-editor.js
@@ -52,7 +52,7 @@ function editBurg(id) {
document.getElementById("burglLegend").addEventListener("click", editBurgLegend);
document.getElementById("burgLock").addEventListener("click", toggleBurgLockButton);
document.getElementById("burgRemove").addEventListener("click", removeSelectedBurg);
- document.getElementById("burgTemperatureGraph").addEventListener("click", showTemperatureGraphs);
+ document.getElementById("burgTemperatureGraph").addEventListener("click", showTemperatureGraph);
function updateBurgValues() {
const id = +elSelected.attr("data-id");
@@ -543,11 +543,11 @@ function editBurg(id) {
const name = elSelected.text();
editNotes("burg" + id, name);
}
- function showTemperatureGraphs() {
- const id = elSelected.attr("data-id");
- showTGForBurg(id);
- }
+ function showTemperatureGraph() {
+ const id = elSelected.attr("data-id");
+ showBurgTemperatureGraph(id);
+ }
function removeSelectedBurg() {
const id = +elSelected.attr("data-id");
diff --git a/modules/ui/temperature-graph.js b/modules/ui/temperature-graph.js
index f4a236fa..aa107be6 100644
--- a/modules/ui/temperature-graph.js
+++ b/modules/ui/temperature-graph.js
@@ -1,161 +1,208 @@
"use strict";
-function showTGForBurg(id) {
- const b = pack.burgs[id];
- const lat = mapCoordinates.latN - (b.y / graphHeight) * mapCoordinates.latT;
- const temperature = grid.cells.temp[pack.cells.g[b.cell]];
- const prec = grid.cells.prec[pack.cells.g[b.cell]];
-
- const weights = [
- [//Layer0
- //IN0 IN1
- [10.782752257744338, 2.7100404240962126],
- [-2.8226802110591462, 51.62920138583541],
- [-6.6250956268643835, 4.427939197315455],
- [-59.64690518541339, 41.89084162654791],
- [-1.3302059550553835, -3.6964487738450913],
- [-2.5844898544535497, 0.09879268612455298],
- [-5.58528252533573, -0.23426224364501905],
- [26.94531337690372, 20.898158905988907],
- [3.816397481634785, -0.19045424064580757],
- [-4.835697931609101, -10.748232783636434]
- ],
- [//Layer1
- [-2.478952081870123, 0.6405800134306895, -7.136785640930911, -0.2186529024764509, 3.6568435212735424, 31.446026153530838, -19.91005187482281, 0.2543395274783306, -7.036924569659988, -0.7721371621651565],
- [-197.10583739743538, 6.889921141533474, 0.5058941504631129, 7.7667203434606416, -53.74180550086929, -15.717331715167001, -61.32068414155791, -2.259728220978728, 35.84049189540032, 94.6157364730977],
- [-5.312011591880851, -0.09923148954215096, -1.7132477487917586, -22.55559652066422, 0.4806107280554336, -26.5583974109492, 2.0558257347014863, 25.815645234787432, -18.569029876991156, -2.6792003366730035],
- [20.706518520569514, 18.344297403881875, 99.52244671131733, -58.53124969563653, -60.74384321042212, -80.57540534651835, 7.884792406540866, -144.33871131678563, 80.134199744324, 20.50745285622448],
- [-52.88299538575159, -15.782505343805528, 16.63316001054924, 88.09475330556671, -17.619552086641818, -19.943999528182427, -120.46286026828177, 19.354752020806302, 43.49422099308949, 28.733924806541363],
- [-2.4621368711159897, -1.2074759925679757, -1.5133898639835084, 2.173715352424188, -5.988707597991683, 3.0234147182203843, 3.3284199340000797, -1.8805161326360575, 5.151910934121654, -1.2540553911612116]
- ],
- [//Layer2
- [-0.3357437479474717, 0.01430651794222215, -0.7927524256670906, 0.2121636229648523, 1.0587803023358318, -3.759288325505095],
- [-1.1988028704442968, 1.3768997508052783, -3.8480086358278816, 0.5289387340947143, 0.5769459339961177, -1.2528318145750772],
- [1.0074966649240946, 1.155301164699459, -2.974254371052421, 0.47408176553219467, 0.5939042688615264, -0.7631976947131744]
- ]
- ];
- //From (-∞,∞) to ~[-1,1]
- const In1 = [(Math.abs(lat) - 26.950680212887473)/48.378128506956,(prec - 12.229929140832644)/29.94402033696607];
-
- let lastIn = In1;
- let lstOut = [];
- for (let levelN = 0; levelN < weights.length ; levelN++) {
- let layerN = weights[levelN];
- for (let i = 0; i < layerN.length ; i++) {
- lstOut[i] = 0;
- for (let j = 0; j < layerN[i].length ; j++)
- lstOut[i] = lstOut[i] + lastIn[j]*layerN[i][j] ;
- //Sigmoid
- lstOut[i] = 1/(1+Math.exp(-lstOut[i]));
- }
- lastIn = lstOut.slice(0);
- }
-
- //From [0,1] to [min,max]
- //Standard deviation for average temperature for the year
- const yearSig = lstOut[0]*62.9466411977018+0.28613807855649165;
- //Standard deviation for the difference between the minimum and maximum temperatures for the year
- const yearDelTmpSig = (lstOut[1]*13.541688670361175+0.1414213562373084) > yearSig ? yearSig : (lstOut[1]*13.541688670361175+0.1414213562373084);
- //Expected value for the difference between the minimum and maximum temperatures for the year
- const yearDelTmpMu = lstOut[2]*15.266666666666667+0.6416666666666663;
-
- //Temperature change shape
- //const formTmp = -Math.cos(data*2*Math.PI) / 2;
- const delT = yearDelTmpMu/2+0.5*yearDelTmpSig/2;
- const minT = temperature - ((yearSig+delT) > 15 ? (yearSig+delT) : 15);
- const maxT = temperature + (temperature - minT);
+function showBurgTemperatureGraph(id) {
+ const b = pack.burgs[id];
+ const lat = mapCoordinates.latN - (b.y / graphHeight) * mapCoordinates.latT;
+ const temperature = grid.cells.temp[pack.cells.g[b.cell]];
+ const prec = grid.cells.prec[pack.cells.g[b.cell]];
- const chartWidth = window.innerWidth/2,
- chartHeight = 300; // height of our land/sea profile, excluding the biomes data below
- const xOffset = 80,
- yOffset = 10; // this is our drawing starting point from top-left (y = 0) of SVG
-
- const xscale = d3.scaleLinear().domain([0,360]).range([0, chartWidth]);
- const xscale_inv = d3.scaleLinear().domain([0, chartWidth]).range([0,360]);
- const yscale = d3.scaleLinear().domain([minT, maxT]).range([chartHeight, 0]);
- const yscale_inv = d3.scaleLinear().domain([chartHeight, 0]).range([minT, maxT]);
-
- const dataAverTmp = [];
- const dataMinTmp = [];
- const dataMaxTmp = [];
- for (let i = 0; i < 360 ; i++) {
- let formTmp = Math.cos(i/360*2*Math.PI) / 2;
- if(lat > 0) formTmp = -formTmp;
- const averT = formTmp * yearSig + temperature;
- const delT = yearDelTmpMu/2+formTmp*yearDelTmpSig/2;
- dataAverTmp.push({x:xscale(i) + xOffset,y:yscale(averT) + yOffset});
- dataMinTmp.push({x:xscale(i) + xOffset,y:yscale(averT-delT) + yOffset});
- dataMaxTmp.push({x:xscale(i) + xOffset,y:yscale(averT+delT) + yOffset});
- }
-
- document.getElementById("epControls").style.visibility = "hidden";
+ // prettier-ignore
+ const weights = [
+ [// Layer0
+ [10.782752257744338, 2.7100404240962126],
+ [-2.8226802110591462, 51.62920138583541],
+ [-6.6250956268643835, 4.427939197315455],
+ [-59.64690518541339, 41.89084162654791],
+ [-1.3302059550553835, -3.6964487738450913],
+ [-2.5844898544535497, 0.09879268612455298],
+ [-5.58528252533573, -0.23426224364501905],
+ [26.94531337690372, 20.898158905988907],
+ [3.816397481634785, -0.19045424064580757],
+ [-4.835697931609101, -10.748232783636434]
+ ],
+ [// Layer1
+ [-2.478952081870123, 0.6405800134306895, -7.136785640930911, -0.2186529024764509, 3.6568435212735424, 31.446026153530838, -19.91005187482281, 0.2543395274783306, -7.036924569659988, -0.7721371621651565],
+ [-197.10583739743538, 6.889921141533474, 0.5058941504631129, 7.7667203434606416, -53.74180550086929, -15.717331715167001, -61.32068414155791, -2.259728220978728, 35.84049189540032, 94.6157364730977],
+ [-5.312011591880851, -0.09923148954215096, -1.7132477487917586, -22.55559652066422, 0.4806107280554336, -26.5583974109492, 2.0558257347014863, 25.815645234787432, -18.569029876991156, -2.6792003366730035],
+ [20.706518520569514, 18.344297403881875, 99.52244671131733, -58.53124969563653, -60.74384321042212, -80.57540534651835, 7.884792406540866, -144.33871131678563, 80.134199744324, 20.50745285622448],
+ [-52.88299538575159, -15.782505343805528, 16.63316001054924, 88.09475330556671, -17.619552086641818, -19.943999528182427, -120.46286026828177, 19.354752020806302, 43.49422099308949, 28.733924806541363],
+ [-2.4621368711159897, -1.2074759925679757, -1.5133898639835084, 2.173715352424188, -5.988707597991683, 3.0234147182203843, 3.3284199340000797, -1.8805161326360575, 5.151910934121654, -1.2540553911612116]
+ ],
+ [// Layer2
+ [-0.3357437479474717, 0.01430651794222215, -0.7927524256670906, 0.2121636229648523, 1.0587803023358318, -3.759288325505095],
+ [-1.1988028704442968, 1.3768997508052783, -3.8480086358278816, 0.5289387340947143, 0.5769459339961177, -1.2528318145750772],
+ [1.0074966649240946, 1.155301164699459, -2.974254371052421, 0.47408176553219467, 0.5939042688615264, -0.7631976947131744]
+ ]
+ ];
+ // From (-∞,∞) to ~[-1,1]
+ const In1 = [(Math.abs(lat) - 26.950680212887473) / 48.378128506956, (prec - 12.229929140832644) / 29.94402033696607];
- $("#elevationProfile").dialog({
- title: "Seasonal temperature schedule",
- resizable: false,
- width: window.width,
- close: closeTGForBurg,
- position: {my: "left top", at: "left+20 bottom-500", of: window, collision: "fit"}
- });
+ let lastIn = In1;
+ let lstOut = [];
- draw();
+ for (let levelN = 0; levelN < weights.length; levelN++) {
+ const layerN = weights[levelN];
+ for (let i = 0; i < layerN.length; i++) {
+ lstOut[i] = 0;
+ for (let j = 0; j < layerN[i].length; j++) {
+ lstOut[i] = lstOut[i] + lastIn[j] * layerN[i][j];
+ }
+ // sigmoid
+ lstOut[i] = 1 / (1 + Math.exp(-lstOut[i]));
+ }
+ lastIn = lstOut.slice(0);
+ }
- function draw() {
+ // Standard deviation for average temperature for the year from [0,1] to [min,max]
+ const yearSig = lstOut[0] * 62.9466411977018 + 0.28613807855649165;
+ // Standard deviation for the difference between the minimum and maximum temperatures for the year
+ const yearDelTmpSig = lstOut[1] * 13.541688670361175 + 0.1414213562373084 > yearSig ? yearSig : lstOut[1] * 13.541688670361175 + 0.1414213562373084;
+ // Expected value for the difference between the minimum and maximum temperatures for the year
+ const yearDelTmpMu = lstOut[2] * 15.266666666666667 + 0.6416666666666663;
- document.getElementById("elevationGraph").innerHTML = "";
- const legendSize = 60;
+ // Temperature change shape
+ const delT = yearDelTmpMu / 2 + (0.5 * yearDelTmpSig) / 2;
+ const minT = temperature - (yearSig + delT > 15 ? yearSig + delT : 15);
+ const maxT = temperature + (temperature - minT);
+
+ // height of land/sea profile, excluding the biomes data below
+ const chartWidth = window.innerWidth / 2;
+ const chartHeight = 300;
+
+ // drawing starting point from top-left (y = 0) of SVG
+ const xOffset = 80;
+ const yOffset = 10;
+
+ const xscale = d3.scaleLinear().domain([0, 360]).range([0, chartWidth]);
+ const xscale_inv = d3.scaleLinear().domain([0, chartWidth]).range([0, 360]);
+ const yscale = d3.scaleLinear().domain([minT, maxT]).range([chartHeight, 0]);
+ const yscale_inv = d3.scaleLinear().domain([chartHeight, 0]).range([minT, maxT]);
+
+ const dataAverTmp = [];
+ const dataMinTmp = [];
+ const dataMaxTmp = [];
+
+ for (let i = 0; i < 360; i++) {
+ let formTmp = Math.cos((i / 360) * 2 * Math.PI) / 2;
+ if (lat > 0) formTmp = -formTmp;
+ const averT = formTmp * yearSig + temperature;
+ const delT = yearDelTmpMu / 2 + (formTmp * yearDelTmpSig) / 2;
+ dataAverTmp.push({x: xscale(i) + xOffset, y: yscale(averT) + yOffset});
+ dataMinTmp.push({x: xscale(i) + xOffset, y: yscale(averT - delT) + yOffset});
+ dataMaxTmp.push({x: xscale(i) + xOffset, y: yscale(averT + delT) + yOffset});
+ }
+
+ drawGraph();
+ $("#alert").dialog({title: "Anual temperature in " + b.name, position: {my: "center", at: "center", of: "svg"}});
+
+ function drawGraph() {
+ alertMessage.innerHTML = "";
+
+ const legendSize = 60;
const chart = d3
- .select("#elevationGraph")
+ .select("#alertMessage")
.append("svg")
.attr("width", chartWidth + 120)
.attr("height", chartHeight + yOffset + legendSize)
.attr("id", "elevationSVG")
.attr("class", "epbackground");
+
// arrow-head definition
- chart.append("defs").append("marker").attr("id", "arrowhead").attr("orient", "auto").attr("markerWidth", "2").attr("markerHeight", "4").attr("refX", "0.1").attr("refY", "2");
+ chart
+ .append("defs")
+ .append("marker")
+ .attr("id", "arrowhead")
+ .attr("orient", "auto")
+ .attr("markerWidth", "2")
+ .attr("markerHeight", "4")
+ .attr("refX", "0.1")
+ .attr("refY", "2");
- let Gen = d3.line().curve(d3.curveBasis).x((p) => p.x).y((p) => p.y);
+ let Gen = d3
+ .line()
+ .curve(d3.curveBasis)
+ .x(p => p.x)
+ .y(p => p.y);
+
+ //print graphs
+ chart
+ .append("g")
+ .append("path")
+ .attr("d", Gen(dataAverTmp))
+ .attr("fill", "none")
+ .attr("stroke", "orange")
+ .on("mousemove", printVal)
+ .style("stroke-width", "2");
+ chart
+ .append("g")
+ .append("path")
+ .attr("d", Gen(dataMinTmp))
+ .attr("fill", "none")
+ .attr("stroke", "blue")
+ .on("mousemove", printVal)
+ .style("stroke-width", "2");
+ chart.append("g").append("path").attr("d", Gen(dataMaxTmp)).attr("fill", "none").attr("stroke", "red").on("mousemove", printVal).style("stroke-width", "2");
+
+ //print legend
+ chart
+ .append("circle")
+ .attr("cx", (chartWidth * 1) / 4)
+ .attr("cy", chartHeight + yOffset + legendSize * 0.8)
+ .attr("r", 4)
+ .style("fill", "red");
+ chart
+ .append("text")
+ .attr("x", (chartWidth * 1) / 4 + 20)
+ .attr("y", chartHeight + yOffset + legendSize * 0.8)
+ .text("Day temperature")
+ .style("font-size", "10px")
+ .attr("alignment-baseline", "middle");
+ chart
+ .append("circle")
+ .attr("cx", (chartWidth * 2) / 4)
+ .attr("cy", chartHeight + yOffset + legendSize * 0.8)
+ .attr("r", 4)
+ .style("fill", "orange");
+ chart
+ .append("text")
+ .attr("x", (chartWidth * 2) / 4 + 20)
+ .attr("y", chartHeight + yOffset + legendSize * 0.8)
+ .text("Average daily temperature")
+ .style("font-size", "10px")
+ .attr("alignment-baseline", "middle");
+ chart
+ .append("circle")
+ .attr("cx", (chartWidth * 3) / 4)
+ .attr("cy", chartHeight + yOffset + legendSize * 0.8)
+ .attr("r", 4)
+ .style("fill", "blue");
+ chart
+ .append("text")
+ .attr("x", (chartWidth * 3) / 4 + 20)
+ .attr("y", chartHeight + yOffset + legendSize * 0.8)
+ .text("Night temperature")
+ .style("font-size", "10px")
+ .attr("alignment-baseline", "middle");
+
+ //print title
+ let timerId = setTimeout(() => chart.attr("data-tip", "Seasonal temperature schedule"), 1000);
+
+ const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
+ //Val under line
+ function printVal() {
+ let m = d3.mouse(this);
+ let tmp = convertTemperature(yscale_inv(m[1] - yOffset).toFixed(1));
+ let month = months[parseInt((xscale_inv(m[0] - xOffset) / 360) * 12)];
+ chart.attr("data-tip", tmp + " in " + month);
+ clearTimeout(timerId);
+ timerId = setTimeout(() => chart.attr("data-tip", "Seasonal temperature schedule"), 1000);
+ }
- //print graphs
- chart.append("g").append("path").attr("d", Gen(dataAverTmp))
- .attr("fill", "none").attr("stroke", "orange").on("mousemove", printVal).style("stroke-width", "2");
- chart.append("g").append("path").attr("d", Gen(dataMinTmp))
- .attr("fill", "none").attr("stroke", "blue").on("mousemove", printVal).style("stroke-width", "2");
- chart.append("g").append("path").attr("d", Gen(dataMaxTmp))
- .attr("fill", "none").attr("stroke", "red").on("mousemove", printVal).style("stroke-width", "2");
-
- //print legend
- chart.append("circle").attr("cx",chartWidth*1/4).attr("cy",chartHeight + yOffset + legendSize*0.8).attr("r", 4).style("fill", "red")
- chart.append("text").attr("x", chartWidth*1/4+20).attr("y", chartHeight + yOffset + legendSize*0.8)
- .text("Day temperature").style("font-size", "10px").attr("alignment-baseline","middle")
- chart.append("circle").attr("cx",chartWidth*2/4).attr("cy",chartHeight + yOffset + legendSize*0.8).attr("r", 4).style("fill", "orange")
- chart.append("text").attr("x", chartWidth*2/4+20).attr("y", chartHeight + yOffset + legendSize*0.8)
- .text("Average daily temperature").style("font-size", "10px").attr("alignment-baseline","middle")
- chart.append("circle").attr("cx",chartWidth*3/4).attr("cy",chartHeight + yOffset + legendSize*0.8).attr("r", 4).style("fill", "blue")
- chart.append("text").attr("x", chartWidth*3/4+20).attr("y", chartHeight + yOffset + legendSize*0.8)
- .text("Night temperature").style("font-size", "10px").attr("alignment-baseline","middle")
-
-
-
- //print title
- let timerId = setTimeout(() => chart.attr("data-tip", "Seasonal temperature schedule"), 1000);
-
- const months = ["January","February","March","April","May","June","July","August","September","October","November","December"];
- //Val under line
- function printVal(){
- let m = d3.mouse(this);
- let tmp = convertTemperature(yscale_inv(m[1]-yOffset).toFixed(1));
- let month = months[parseInt(xscale_inv(m[0]-xOffset)/360*12)];
- chart.attr("data-tip", tmp + " in " + month);
- clearTimeout(timerId);
- timerId = setTimeout(() => chart.attr("data-tip", "Seasonal temperature schedule"), 1000);
- }
-
const xAxis = d3
.axisBottom(xscale)
.ticks(10)
.tickFormat(function (d) {
- return months[parseInt(d/360*12)];
+ return months[parseInt((d / 360) * 12)];
});
const yAxis = d3
.axisLeft(yscale)
@@ -192,16 +239,18 @@ function showTGForBurg(id) {
.attr("stroke-dasharray", "4 1")
.attr("transform", "translate(" + xOffset + "," + parseInt(chartHeight + +yOffset) + ")")
.call(xGrid);
-
- if(minT < 0 && maxT > 0){
- //add zero lv
- chart.append("g").append("line")
- .attr("x1", xscale(0) + xOffset)
- .attr("y1", yscale(0) + yOffset)
- .attr("x2", xscale(360) + xOffset)
- .attr("y2", yscale(0) + yOffset)
- .attr("stroke", "black");
- }
+
+ if (minT < 0 && maxT > 0) {
+ //add zero lv
+ chart
+ .append("g")
+ .append("line")
+ .attr("x1", xscale(0) + xOffset)
+ .attr("y1", yscale(0) + yOffset)
+ .attr("x2", xscale(360) + xOffset)
+ .attr("y2", yscale(0) + yOffset)
+ .attr("stroke", "black");
+ }
// add the Y gridlines
chart
@@ -212,9 +261,4 @@ function showTGForBurg(id) {
.attr("transform", "translate(" + xOffset + "," + yOffset + ")")
.call(yGrid);
}
- function closeTGForBurg() {
- document.getElementById("epControls").style.visibility = "visible";
- document.getElementById("elevationGraph").innerHTML = "";
- modules.elevation = false;
- }
-}
\ No newline at end of file
+}
From 6beb262e91f76877246f0417c0ff1ac633897b00 Mon Sep 17 00:00:00 2001
From: Azgaar
Date: Fri, 4 Feb 2022 01:33:11 +0300
Subject: [PATCH 3/7] burg temperature graph - clean up
---
modules/ui/temperature-graph.js | 182 +++++++++-----------------------
utils/unitUtils.js | 4 +-
2 files changed, 49 insertions(+), 137 deletions(-)
diff --git a/modules/ui/temperature-graph.js b/modules/ui/temperature-graph.js
index aa107be6..507ea027 100644
--- a/modules/ui/temperature-graph.js
+++ b/modules/ui/temperature-graph.js
@@ -98,147 +98,68 @@ function showBurgTemperatureGraph(id) {
function drawGraph() {
alertMessage.innerHTML = "";
+ const makeCurve = d3
+ .line()
+ .curve(d3.curveBasis)
+ .x(p => p.x)
+ .y(p => p.y);
+ const getCurve = data => round(makeCurve(data), 2);
+
const legendSize = 60;
const chart = d3
.select("#alertMessage")
.append("svg")
.attr("width", chartWidth + 120)
- .attr("height", chartHeight + yOffset + legendSize)
- .attr("id", "elevationSVG")
- .attr("class", "epbackground");
+ .attr("height", chartHeight + yOffset + legendSize);
- // arrow-head definition
- chart
- .append("defs")
- .append("marker")
- .attr("id", "arrowhead")
- .attr("orient", "auto")
- .attr("markerWidth", "2")
- .attr("markerHeight", "4")
- .attr("refX", "0.1")
- .attr("refY", "2");
+ const curves = chart.append("g").attr("fill", "none").style("stroke-width", 2.5);
+ curves.append("path").attr("d", getCurve(dataAverTmp)).attr("stroke", "orange").on("mousemove", printVal);
+ curves.append("path").attr("d", getCurve(dataMinTmp)).attr("stroke", "blue").on("mousemove", printVal);
+ curves.append("path").attr("d", getCurve(dataMaxTmp)).attr("stroke", "red").on("mousemove", printVal);
- let Gen = d3
- .line()
- .curve(d3.curveBasis)
- .x(p => p.x)
- .y(p => p.y);
-
- //print graphs
- chart
- .append("g")
- .append("path")
- .attr("d", Gen(dataAverTmp))
- .attr("fill", "none")
- .attr("stroke", "orange")
- .on("mousemove", printVal)
- .style("stroke-width", "2");
- chart
- .append("g")
- .append("path")
- .attr("d", Gen(dataMinTmp))
- .attr("fill", "none")
- .attr("stroke", "blue")
- .on("mousemove", printVal)
- .style("stroke-width", "2");
- chart.append("g").append("path").attr("d", Gen(dataMaxTmp)).attr("fill", "none").attr("stroke", "red").on("mousemove", printVal).style("stroke-width", "2");
-
- //print legend
- chart
- .append("circle")
- .attr("cx", (chartWidth * 1) / 4)
- .attr("cy", chartHeight + yOffset + legendSize * 0.8)
- .attr("r", 4)
- .style("fill", "red");
- chart
- .append("text")
- .attr("x", (chartWidth * 1) / 4 + 20)
- .attr("y", chartHeight + yOffset + legendSize * 0.8)
- .text("Day temperature")
- .style("font-size", "10px")
- .attr("alignment-baseline", "middle");
- chart
- .append("circle")
- .attr("cx", (chartWidth * 2) / 4)
- .attr("cy", chartHeight + yOffset + legendSize * 0.8)
- .attr("r", 4)
- .style("fill", "orange");
- chart
- .append("text")
- .attr("x", (chartWidth * 2) / 4 + 20)
- .attr("y", chartHeight + yOffset + legendSize * 0.8)
- .text("Average daily temperature")
- .style("font-size", "10px")
- .attr("alignment-baseline", "middle");
- chart
- .append("circle")
- .attr("cx", (chartWidth * 3) / 4)
- .attr("cy", chartHeight + yOffset + legendSize * 0.8)
- .attr("r", 4)
- .style("fill", "blue");
- chart
- .append("text")
- .attr("x", (chartWidth * 3) / 4 + 20)
- .attr("y", chartHeight + yOffset + legendSize * 0.8)
- .text("Night temperature")
- .style("font-size", "10px")
- .attr("alignment-baseline", "middle");
-
- //print title
- let timerId = setTimeout(() => chart.attr("data-tip", "Seasonal temperature schedule"), 1000);
+ const legend = chart.append("g");
+ const legendY = chartHeight + yOffset + legendSize * 0.9;
+ const legendX = n => (chartWidth * n) / 4;
+ const legendTextPadding = 10;
+ const legendTextX = n => legendX(n) + legendTextPadding;
+ legend.append("circle").attr("cx", legendX(1)).attr("cy", legendY).attr("r", 4).style("fill", "red");
+ legend.append("text").attr("x", legendTextX(1)).attr("y", legendY).attr("alignment-baseline", "central").text("Day temperature");
+ legend.append("circle").attr("cx", legendX(2)).attr("cy", legendY).attr("r", 4).style("fill", "orange");
+ legend.append("text").attr("x", legendTextX(2)).attr("y", legendY).attr("alignment-baseline", "central").text("Mean daily temperature");
+ legend.append("circle").attr("cx", legendX(3)).attr("cy", legendY).attr("r", 4).style("fill", "blue");
+ legend.append("text").attr("x", legendTextX(3)).attr("y", legendY).attr("alignment-baseline", "central").text("Night temperature");
const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
- //Val under line
+
function printVal() {
- let m = d3.mouse(this);
- let tmp = convertTemperature(yscale_inv(m[1] - yOffset).toFixed(1));
- let month = months[parseInt((xscale_inv(m[0] - xOffset) / 360) * 12)];
- chart.attr("data-tip", tmp + " in " + month);
- clearTimeout(timerId);
- timerId = setTimeout(() => chart.attr("data-tip", "Seasonal temperature schedule"), 1000);
+ const [x, y] = d3.mouse(this);
+ const tmp = convertTemperature(yscale_inv(y - yOffset));
+ const month = months[parseInt((xscale_inv(x - xOffset) / 360) * 12)];
+ chart.attr("data-tip", `${month} temperature: ${tmp}`);
}
- const xAxis = d3
- .axisBottom(xscale)
- .ticks(10)
- .tickFormat(function (d) {
- return months[parseInt((d / 360) * 12)];
- });
- const yAxis = d3
- .axisLeft(yscale)
- .ticks(5)
- .tickFormat(function (d) {
- return convertTemperature(d);
- });
+ const xGrid = d3.axisBottom(xscale).ticks(10).tickSize(-chartHeight);
+ const yGrid = d3.axisLeft(yscale).ticks(5).tickSize(-chartWidth);
- const xGrid = d3.axisBottom(xscale).ticks(10).tickSize(-chartHeight).tickFormat("");
- const yGrid = d3.axisLeft(yscale).ticks(5).tickSize(-chartWidth).tickFormat("");
-
- chart
+ const grid = chart.append("g").attr("class", "epgrid").attr("stroke-dasharray", "4 1");
+ grid
.append("g")
- .attr("id", "epxaxis")
- .attr("transform", "translate(" + xOffset + "," + parseInt(chartHeight + +yOffset + 20) + ")")
- .call(xAxis)
- .selectAll("text")
- .style("text-anchor", "center")
- .attr("transform", function (d) {
- return "rotate(0)"; // used to rotate labels, - anti-clockwise, + clockwise
- });
-
- chart
- .append("g")
- .attr("id", "epyaxis")
- .attr("transform", "translate(" + parseInt(+xOffset - 10) + "," + parseInt(+yOffset) + ")")
- .call(yAxis);
-
- // add the X gridlines
- chart
- .append("g")
- .attr("id", "epxgrid")
- .attr("class", "epgrid")
- .attr("stroke-dasharray", "4 1")
- .attr("transform", "translate(" + xOffset + "," + parseInt(chartHeight + +yOffset) + ")")
+ .attr("transform", `translate(${xOffset}, ${chartHeight + yOffset})`)
.call(xGrid);
+ grid.append("g").attr("transform", `translate(${xOffset}, ${yOffset})`).call(yGrid);
+ grid.selectAll("text").remove();
+
+ const formatX = d => months[parseInt((d / 360) * 12)];
+ const xAxis = d3.axisBottom(xscale).ticks(10).tickFormat(formatX);
+
+ const formatY = d => convertTemperature(d);
+ const yAxis = d3.axisLeft(yscale).ticks(5).tickFormat(formatY);
+
+ chart
+ .append("g")
+ .attr("transform", `translate(${xOffset}, ${chartHeight + yOffset})`)
+ .call(xAxis);
+ chart.append("g").attr("transform", `translate(${xOffset}, ${yOffset})`).call(yAxis);
if (minT < 0 && maxT > 0) {
//add zero lv
@@ -251,14 +172,5 @@ function showBurgTemperatureGraph(id) {
.attr("y2", yscale(0) + yOffset)
.attr("stroke", "black");
}
-
- // add the Y gridlines
- chart
- .append("g")
- .attr("id", "epygrid")
- .attr("class", "epgrid")
- .attr("stroke-dasharray", "4 1")
- .attr("transform", "translate(" + xOffset + "," + yOffset + ")")
- .call(yGrid);
}
}
diff --git a/utils/unitUtils.js b/utils/unitUtils.js
index 609b5eb9..141fa432 100644
--- a/utils/unitUtils.js
+++ b/utils/unitUtils.js
@@ -5,7 +5,7 @@
function convertTemperature(temp) {
switch (temperatureScale.value) {
case "°C":
- return temp + "°C";
+ return rn(temp) + "°C";
case "°F":
return rn((temp * 9) / 5 + 32) + "°F";
case "K":
@@ -21,7 +21,7 @@ function convertTemperature(temp) {
case "°Rø":
return rn((temp * 21) / 40 + 7.5) + "°Rø";
default:
- return temp + "°C";
+ return rn(temp) + "°C";
}
}
From d99c24e0dec76107fc08d4459908b3d68d0ca7e1 Mon Sep 17 00:00:00 2001
From: Azgaar
Date: Fri, 4 Feb 2022 01:40:41 +0300
Subject: [PATCH 4/7] burg temperature graph - clean up
---
index.css | 2 +-
modules/ui/temperature-graph.js | 24 ++++++++++++------------
2 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/index.css b/index.css
index 9946d1b2..17913cb4 100644
--- a/index.css
+++ b/index.css
@@ -2310,7 +2310,7 @@ svg.button {
.epgrid line {
stroke: lightgrey;
- stroke-opacity: 0.7;
+ stroke-opacity: 0.5;
shape-rendering: crispEdges;
}
diff --git a/modules/ui/temperature-graph.js b/modules/ui/temperature-graph.js
index 507ea027..c8d51770 100644
--- a/modules/ui/temperature-graph.js
+++ b/modules/ui/temperature-graph.js
@@ -149,6 +149,18 @@ function showBurgTemperatureGraph(id) {
grid.append("g").attr("transform", `translate(${xOffset}, ${yOffset})`).call(yGrid);
grid.selectAll("text").remove();
+ //add zero degree line
+ if (minT < 0 && maxT > 0) {
+ chart
+ .append("g")
+ .append("line")
+ .attr("x1", xscale(0) + xOffset)
+ .attr("y1", yscale(0) + yOffset)
+ .attr("x2", xscale(360) + xOffset)
+ .attr("y2", yscale(0) + yOffset)
+ .attr("stroke", "gray");
+ }
+
const formatX = d => months[parseInt((d / 360) * 12)];
const xAxis = d3.axisBottom(xscale).ticks(10).tickFormat(formatX);
@@ -160,17 +172,5 @@ function showBurgTemperatureGraph(id) {
.attr("transform", `translate(${xOffset}, ${chartHeight + yOffset})`)
.call(xAxis);
chart.append("g").attr("transform", `translate(${xOffset}, ${yOffset})`).call(yAxis);
-
- if (minT < 0 && maxT > 0) {
- //add zero lv
- chart
- .append("g")
- .append("line")
- .attr("x1", xscale(0) + xOffset)
- .attr("y1", yscale(0) + yOffset)
- .attr("x2", xscale(360) + xOffset)
- .attr("y2", yscale(0) + yOffset)
- .attr("stroke", "black");
- }
}
}
From 6abed0cdf44624a9c633d3c113094002f06af09f Mon Sep 17 00:00:00 2001
From: Azgaar
Date: Sat, 5 Feb 2022 16:54:59 +0300
Subject: [PATCH 5/7] burg temperature graph - UI and data corrections
---
modules/ui/temperature-graph.js | 141 ++++++++++++++------------------
1 file changed, 63 insertions(+), 78 deletions(-)
diff --git a/modules/ui/temperature-graph.js b/modules/ui/temperature-graph.js
index c8d51770..59a8ac9c 100644
--- a/modules/ui/temperature-graph.js
+++ b/modules/ui/temperature-graph.js
@@ -3,24 +3,16 @@
function showBurgTemperatureGraph(id) {
const b = pack.burgs[id];
const lat = mapCoordinates.latN - (b.y / graphHeight) * mapCoordinates.latT;
- const temperature = grid.cells.temp[pack.cells.g[b.cell]];
+ const burgTemp = grid.cells.temp[pack.cells.g[b.cell]];
const prec = grid.cells.prec[pack.cells.g[b.cell]];
// prettier-ignore
const weights = [
- [// Layer0
- [10.782752257744338, 2.7100404240962126],
- [-2.8226802110591462, 51.62920138583541],
- [-6.6250956268643835, 4.427939197315455],
- [-59.64690518541339, 41.89084162654791],
- [-1.3302059550553835, -3.6964487738450913],
- [-2.5844898544535497, 0.09879268612455298],
- [-5.58528252533573, -0.23426224364501905],
- [26.94531337690372, 20.898158905988907],
- [3.816397481634785, -0.19045424064580757],
- [-4.835697931609101, -10.748232783636434]
+ [
+ [10.782752257744338, 2.7100404240962126], [-2.8226802110591462, 51.62920138583541], [-6.6250956268643835, 4.427939197315455], [-59.64690518541339, 41.89084162654791], [-1.3302059550553835, -3.6964487738450913],
+ [-2.5844898544535497, 0.09879268612455298], [-5.58528252533573, -0.23426224364501905], [26.94531337690372, 20.898158905988907], [3.816397481634785, -0.19045424064580757], [-4.835697931609101, -10.748232783636434]
],
- [// Layer1
+ [
[-2.478952081870123, 0.6405800134306895, -7.136785640930911, -0.2186529024764509, 3.6568435212735424, 31.446026153530838, -19.91005187482281, 0.2543395274783306, -7.036924569659988, -0.7721371621651565],
[-197.10583739743538, 6.889921141533474, 0.5058941504631129, 7.7667203434606416, -53.74180550086929, -15.717331715167001, -61.32068414155791, -2.259728220978728, 35.84049189540032, 94.6157364730977],
[-5.312011591880851, -0.09923148954215096, -1.7132477487917586, -22.55559652066422, 0.4806107280554336, -26.5583974109492, 2.0558257347014863, 25.815645234787432, -18.569029876991156, -2.6792003366730035],
@@ -28,13 +20,13 @@ function showBurgTemperatureGraph(id) {
[-52.88299538575159, -15.782505343805528, 16.63316001054924, 88.09475330556671, -17.619552086641818, -19.943999528182427, -120.46286026828177, 19.354752020806302, 43.49422099308949, 28.733924806541363],
[-2.4621368711159897, -1.2074759925679757, -1.5133898639835084, 2.173715352424188, -5.988707597991683, 3.0234147182203843, 3.3284199340000797, -1.8805161326360575, 5.151910934121654, -1.2540553911612116]
],
- [// Layer2
+ [
[-0.3357437479474717, 0.01430651794222215, -0.7927524256670906, 0.2121636229648523, 1.0587803023358318, -3.759288325505095],
[-1.1988028704442968, 1.3768997508052783, -3.8480086358278816, 0.5289387340947143, 0.5769459339961177, -1.2528318145750772],
[1.0074966649240946, 1.155301164699459, -2.974254371052421, 0.47408176553219467, 0.5939042688615264, -0.7631976947131744]
]
];
- // From (-∞,∞) to ~[-1,1]
+ // From (-∞, ∞) to ~[-1, 1]
const In1 = [(Math.abs(lat) - 26.950680212887473) / 48.378128506956, (prec - 12.229929140832644) / 29.94402033696607];
let lastIn = In1;
@@ -53,7 +45,7 @@ function showBurgTemperatureGraph(id) {
lastIn = lstOut.slice(0);
}
- // Standard deviation for average temperature for the year from [0,1] to [min,max]
+ // Standard deviation for average temperature for the year from [0, 1] to [min, max]
const yearSig = lstOut[0] * 62.9466411977018 + 0.28613807855649165;
// Standard deviation for the difference between the minimum and maximum temperatures for the year
const yearDelTmpSig = lstOut[1] * 13.541688670361175 + 0.1414213562373084 > yearSig ? yearSig : lstOut[1] * 13.541688670361175 + 0.1414213562373084;
@@ -62,48 +54,48 @@ function showBurgTemperatureGraph(id) {
// Temperature change shape
const delT = yearDelTmpMu / 2 + (0.5 * yearDelTmpSig) / 2;
- const minT = temperature - (yearSig + delT > 15 ? yearSig + delT : 15);
- const maxT = temperature + (temperature - minT);
+ const minT = burgTemp - Math.max(yearSig + delT, 15);
+ const maxT = burgTemp + (burgTemp - minT);
- // height of land/sea profile, excluding the biomes data below
- const chartWidth = window.innerWidth / 2;
+ const chartWidth = Math.max(window.innerWidth / 2, 580);
const chartHeight = 300;
// drawing starting point from top-left (y = 0) of SVG
- const xOffset = 80;
+ const xOffset = 60;
const yOffset = 10;
- const xscale = d3.scaleLinear().domain([0, 360]).range([0, chartWidth]);
- const xscale_inv = d3.scaleLinear().domain([0, chartWidth]).range([0, 360]);
+ const year = new Date().getFullYear(); // use current year
+ const startDate = new Date(year, 0, 1);
+ const endDate = new Date(year, 11, 31);
+ const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
+
+ const xscale = d3.scaleTime().domain([startDate, endDate]).range([0, chartWidth]);
const yscale = d3.scaleLinear().domain([minT, maxT]).range([chartHeight, 0]);
- const yscale_inv = d3.scaleLinear().domain([chartHeight, 0]).range([minT, maxT]);
- const dataAverTmp = [];
- const dataMinTmp = [];
- const dataMaxTmp = [];
+ const tempMean = [];
+ const tempMin = [];
+ const tempMax = [];
- for (let i = 0; i < 360; i++) {
- let formTmp = Math.cos((i / 360) * 2 * Math.PI) / 2;
+ months.forEach((month, index) => {
+ const rate = index / 11;
+ let formTmp = Math.cos(rate * 2 * Math.PI) / 2;
if (lat > 0) formTmp = -formTmp;
- const averT = formTmp * yearSig + temperature;
- const delT = yearDelTmpMu / 2 + (formTmp * yearDelTmpSig) / 2;
- dataAverTmp.push({x: xscale(i) + xOffset, y: yscale(averT) + yOffset});
- dataMinTmp.push({x: xscale(i) + xOffset, y: yscale(averT - delT) + yOffset});
- dataMaxTmp.push({x: xscale(i) + xOffset, y: yscale(averT + delT) + yOffset});
- }
+
+ const x = rate * chartWidth + xOffset;
+ const tempAverage = formTmp * yearSig + burgTemp;
+ const tempDelta = yearDelTmpMu / 2 + (formTmp * yearDelTmpSig) / 2;
+
+ tempMean.push([x, yscale(tempAverage) + yOffset]);
+ tempMin.push([x, yscale(tempAverage - tempDelta) + yOffset]);
+ tempMax.push([x, yscale(tempAverage + tempDelta) + yOffset]);
+ });
drawGraph();
- $("#alert").dialog({title: "Anual temperature in " + b.name, position: {my: "center", at: "center", of: "svg"}});
+ $("#alert").dialog({title: "Annual temperature in " + b.name, position: {my: "center", at: "center", of: "svg"}});
function drawGraph() {
alertMessage.innerHTML = "";
-
- const makeCurve = d3
- .line()
- .curve(d3.curveBasis)
- .x(p => p.x)
- .y(p => p.y);
- const getCurve = data => round(makeCurve(data), 2);
+ const getCurve = data => round(d3.line().curve(d3.curveBasis)(data), 2);
const legendSize = 60;
const chart = d3
@@ -112,65 +104,58 @@ function showBurgTemperatureGraph(id) {
.attr("width", chartWidth + 120)
.attr("height", chartHeight + yOffset + legendSize);
- const curves = chart.append("g").attr("fill", "none").style("stroke-width", 2.5);
- curves.append("path").attr("d", getCurve(dataAverTmp)).attr("stroke", "orange").on("mousemove", printVal);
- curves.append("path").attr("d", getCurve(dataMinTmp)).attr("stroke", "blue").on("mousemove", printVal);
- curves.append("path").attr("d", getCurve(dataMaxTmp)).attr("stroke", "red").on("mousemove", printVal);
-
const legend = chart.append("g");
- const legendY = chartHeight + yOffset + legendSize * 0.9;
+ const legendY = chartHeight + yOffset + legendSize * 0.8;
const legendX = n => (chartWidth * n) / 4;
- const legendTextPadding = 10;
- const legendTextX = n => legendX(n) + legendTextPadding;
+ const legendTextX = n => legendX(n) + 10;
legend.append("circle").attr("cx", legendX(1)).attr("cy", legendY).attr("r", 4).style("fill", "red");
legend.append("text").attr("x", legendTextX(1)).attr("y", legendY).attr("alignment-baseline", "central").text("Day temperature");
legend.append("circle").attr("cx", legendX(2)).attr("cy", legendY).attr("r", 4).style("fill", "orange");
- legend.append("text").attr("x", legendTextX(2)).attr("y", legendY).attr("alignment-baseline", "central").text("Mean daily temperature");
+ legend.append("text").attr("x", legendTextX(2)).attr("y", legendY).attr("alignment-baseline", "central").text("Mean temperature");
legend.append("circle").attr("cx", legendX(3)).attr("cy", legendY).attr("r", 4).style("fill", "blue");
legend.append("text").attr("x", legendTextX(3)).attr("y", legendY).attr("alignment-baseline", "central").text("Night temperature");
- const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
-
- function printVal() {
- const [x, y] = d3.mouse(this);
- const tmp = convertTemperature(yscale_inv(y - yOffset));
- const month = months[parseInt((xscale_inv(x - xOffset) / 360) * 12)];
- chart.attr("data-tip", `${month} temperature: ${tmp}`);
- }
-
- const xGrid = d3.axisBottom(xscale).ticks(10).tickSize(-chartHeight);
+ const xGrid = d3.axisBottom(xscale).ticks().tickSize(-chartHeight);
const yGrid = d3.axisLeft(yscale).ticks(5).tickSize(-chartWidth);
const grid = chart.append("g").attr("class", "epgrid").attr("stroke-dasharray", "4 1");
- grid
- .append("g")
- .attr("transform", `translate(${xOffset}, ${chartHeight + yOffset})`)
- .call(xGrid);
+ grid.append("g").attr("transform", `translate(${xOffset}, ${chartHeight + yOffset})`).call(xGrid); // prettier-ignore
grid.append("g").attr("transform", `translate(${xOffset}, ${yOffset})`).call(yGrid);
grid.selectAll("text").remove();
- //add zero degree line
+ // add zero degree line
if (minT < 0 && maxT > 0) {
- chart
- .append("g")
+ grid
.append("line")
- .attr("x1", xscale(0) + xOffset)
+ .attr("x1", xOffset)
.attr("y1", yscale(0) + yOffset)
- .attr("x2", xscale(360) + xOffset)
+ .attr("x2", chartWidth + xOffset)
.attr("y2", yscale(0) + yOffset)
.attr("stroke", "gray");
}
- const formatX = d => months[parseInt((d / 360) * 12)];
- const xAxis = d3.axisBottom(xscale).ticks(10).tickFormat(formatX);
+ const xAxis = d3.axisBottom(xscale).ticks().tickFormat(d3.timeFormat("%B"));
+ const yAxis = d3.axisLeft(yscale).ticks(5).tickFormat(convertTemperature);
- const formatY = d => convertTemperature(d);
- const yAxis = d3.axisLeft(yscale).ticks(5).tickFormat(formatY);
-
- chart
+ const axis = chart.append("g");
+ axis
.append("g")
.attr("transform", `translate(${xOffset}, ${chartHeight + yOffset})`)
.call(xAxis);
- chart.append("g").attr("transform", `translate(${xOffset}, ${yOffset})`).call(yAxis);
+ axis.append("g").attr("transform", `translate(${xOffset}, ${yOffset})`).call(yAxis);
+ axis.select("path.domain").attr("d", `M0.5,0.5 H${chartWidth + 0.5}`);
+
+ const curves = chart.append("g").attr("fill", "none").style("stroke-width", 2.5);
+ curves.append("path").attr("d", getCurve(tempMean)).attr("data-type", "daily").attr("stroke", "orange").on("mousemove", printVal);
+ curves.append("path").attr("d", getCurve(tempMin)).attr("data-type", "night").attr("stroke", "blue").on("mousemove", printVal);
+ curves.append("path").attr("d", getCurve(tempMax)).attr("data-type", "day").attr("stroke", "red").on("mousemove", printVal);
+
+ function printVal() {
+ const [x, y] = d3.mouse(this);
+ const type = this.getAttribute("data-type");
+ const temp = convertTemperature(yscale.invert(y - yOffset));
+ const month = months[rn(((x - xOffset) / chartWidth) * 12)] || months[0];
+ tip(`Average ${type} temperature in ${month}: ${temp}`);
+ }
}
}
From f65bc63ab3b8a3014ac223f59eb6be7751458c71 Mon Sep 17 00:00:00 2001
From: Azgaar
Date: Sat, 5 Feb 2022 17:08:48 +0300
Subject: [PATCH 6/7] pump version to 1.72
---
index.html | 2 +-
main.js | 16 ++++++++--------
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/index.html b/index.html
index 6dc479f1..7e0bafb3 100644
--- a/index.html
+++ b/index.html
@@ -226,7 +226,7 @@
Azgaar's
Fantasy Map Generator
-
v. 1.71
+
v. 1.72
LOADING . . .
diff --git a/main.js b/main.js
index e3cd39f7..0dc57216 100644
--- a/main.js
+++ b/main.js
@@ -2,7 +2,7 @@
// https://github.com/Azgaar/Fantasy-Map-Generator
"use strict";
-const version = "1.71"; // generator version
+const version = "1.72"; // generator version
document.title += " v" + version;
// Switches to disable/enable logging features
@@ -411,20 +411,20 @@ function showWelcomeMessage() {
alertMessage.innerHTML = `The Fantasy Map Generator is updated up to version ${version} .
This version is compatible with ${changelog}, loaded .map files will be auto-updated.
- Main changes:
- Ability to limit military units by biome, state, culture and religion
+ Latest changes:
+ Burg temperature graph
+ 4 new textures
+ Province capture logic rework
+ Button to release all provinces
+ Limit military units by biome, state, culture and religion
New marker types
New markers editor
Markers overview screen
Markers regeneration menu
- Burg editor update
- Editable theme color
- Add font dialog
- Save to Dropbox
Join our ${discord} and ${reddit} to ask questions, share maps, discuss the Generator and Worlbuilding, report bugs and propose new features.
- Thanks for all supporters on Patreon ! `;
+ Thanks for all supporters on ${patreon}! `;
$("#alert").dialog({
resizable: false,
From 65409a9d977e97b5eb380bfd9a0aea2092cc753f Mon Sep 17 00:00:00 2001
From: Azgaar
Date: Sat, 5 Feb 2022 17:13:54 +0300
Subject: [PATCH 7/7] set width to auto
---
modules/ui/temperature-graph.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/ui/temperature-graph.js b/modules/ui/temperature-graph.js
index 59a8ac9c..0b3ea567 100644
--- a/modules/ui/temperature-graph.js
+++ b/modules/ui/temperature-graph.js
@@ -91,7 +91,7 @@ function showBurgTemperatureGraph(id) {
});
drawGraph();
- $("#alert").dialog({title: "Annual temperature in " + b.name, position: {my: "center", at: "center", of: "svg"}});
+ $("#alert").dialog({title: "Annual temperature in " + b.name, width: "auto", position: {my: "center", at: "center", of: "svg"}});
function drawGraph() {
alertMessage.innerHTML = "";