mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2025-12-18 10:01:23 +01:00
Merge branch 'master' of github.com-personal:Azgaar/Fantasy-Map-Generator into burg-groups
This commit is contained in:
commit
8e13a3a0de
8 changed files with 211 additions and 32 deletions
|
|
@ -330,6 +330,40 @@ async function getMapURL(
|
|||
if (pattern) cloneDefs.appendChild(pattern.cloneNode(true));
|
||||
}
|
||||
|
||||
{
|
||||
// replace external marker icons
|
||||
const externalMarkerImages = cloneEl.querySelectorAll('#markers image[href]:not([href=""])');
|
||||
const imageHrefs = Array.from(externalMarkerImages).map(img => img.getAttribute("href"));
|
||||
|
||||
for (const url of imageHrefs) {
|
||||
await new Promise(resolve => {
|
||||
getBase64(url, base64 => {
|
||||
externalMarkerImages.forEach(img => {
|
||||
if (img.getAttribute("href") === url) img.setAttribute("href", base64);
|
||||
});
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// replace external regiment icons
|
||||
const externalRegimentImages = cloneEl.querySelectorAll('#armies image[href]:not([href=""])');
|
||||
const imageHrefs = Array.from(externalRegimentImages).map(img => img.getAttribute("href"));
|
||||
|
||||
for (const url of imageHrefs) {
|
||||
await new Promise(resolve => {
|
||||
getBase64(url, base64 => {
|
||||
externalRegimentImages.forEach(img => {
|
||||
if (img.getAttribute("href") === url) img.setAttribute("href", base64);
|
||||
});
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!cloneEl.getElementById("fogging-cont")) cloneEl.getElementById("fog")?.remove(); // remove unused fog
|
||||
if (!cloneEl.getElementById("regions")) cloneEl.getElementById("statePaths")?.remove(); // removed unused statePaths
|
||||
if (!cloneEl.getElementById("labels")) cloneEl.getElementById("textPaths")?.remove(); // removed unused textPaths
|
||||
|
|
@ -495,11 +529,10 @@ function saveGeoJsonCells() {
|
|||
function saveGeoJsonRoutes() {
|
||||
const features = pack.routes.map(({i, points, group, name = null}) => {
|
||||
const coordinates = points.map(([x, y]) => getCoordinates(x, y, 4));
|
||||
const id = `route${i}`;
|
||||
return {
|
||||
type: "Feature",
|
||||
geometry: {type: "LineString", coordinates},
|
||||
properties: {id, group, name}
|
||||
properties: {id: i, group, name}
|
||||
};
|
||||
});
|
||||
const json = {type: "FeatureCollection", features};
|
||||
|
|
@ -514,11 +547,10 @@ function saveGeoJsonRivers() {
|
|||
if (!cells || cells.length < 2) return;
|
||||
const meanderedPoints = Rivers.addMeandering(cells, points);
|
||||
const coordinates = meanderedPoints.map(([x, y]) => getCoordinates(x, y, 4));
|
||||
const id = `river${i}`;
|
||||
return {
|
||||
type: "Feature",
|
||||
geometry: {type: "LineString", coordinates},
|
||||
properties: {id, source, mouth, parent, basin, widthFactor, sourceWidth, discharge, name, type}
|
||||
properties: {id: i, source, mouth, parent, basin, widthFactor, sourceWidth, discharge, name, type}
|
||||
};
|
||||
}
|
||||
);
|
||||
|
|
@ -532,9 +564,8 @@ function saveGeoJsonMarkers() {
|
|||
const features = pack.markers.map(marker => {
|
||||
const {i, type, icon, x, y, size, fill, stroke} = marker;
|
||||
const coordinates = getCoordinates(x, y, 4);
|
||||
const id = `marker${i}`;
|
||||
const note = notes.find(note => note.id === id);
|
||||
const properties = {id, type, icon, x, y, ...note, size, fill, stroke};
|
||||
const properties = {id: i, type, icon, x, y, ...note, size, fill, stroke};
|
||||
return {type: "Feature", geometry: {type: "Point", coordinates}, properties};
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,10 @@ const PROVIDERS = {
|
|||
anthropic: {
|
||||
keyLink: "https://console.anthropic.com/account/keys",
|
||||
generate: generateWithAnthropic
|
||||
},
|
||||
ollama: {
|
||||
keyLink: "https://github.com/Azgaar/Fantasy-Map-Generator/wiki/Ollama-text-generation",
|
||||
generate: generateWithOllama
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -18,11 +22,16 @@ const MODELS = {
|
|||
"chatgpt-4o-latest": "openai",
|
||||
"gpt-4o": "openai",
|
||||
"gpt-4-turbo": "openai",
|
||||
"o1-preview": "openai",
|
||||
"o1-mini": "openai",
|
||||
o3: "openai",
|
||||
"o3-mini": "openai",
|
||||
"o3-pro": "openai",
|
||||
"o4-mini": "openai",
|
||||
"claude-opus-4-20250514": "anthropic",
|
||||
"claude-sonnet-4-20250514": "anthropic",
|
||||
"claude-3-5-haiku-latest": "anthropic",
|
||||
"claude-3-5-sonnet-latest": "anthropic",
|
||||
"claude-3-opus-latest": "anthropic"
|
||||
"claude-3-opus-latest": "anthropic",
|
||||
"ollama (local models)": "ollama"
|
||||
};
|
||||
|
||||
const SYSTEM_MESSAGE = "I'm working on my fantasy map.";
|
||||
|
|
@ -76,10 +85,36 @@ async function generateWithAnthropic({key, model, prompt, temperature, onContent
|
|||
await handleStream(response, getContent);
|
||||
}
|
||||
|
||||
async function generateWithOllama({key, model, prompt, temperature, onContent}) {
|
||||
const ollamaModelName = key; // for Ollama, 'key' is the actual model name entered by the user
|
||||
|
||||
const response = await fetch("http://localhost:11434/api/generate", {
|
||||
method: "POST",
|
||||
headers: {"Content-Type": "application/json"},
|
||||
body: JSON.stringify({
|
||||
model: ollamaModelName,
|
||||
prompt,
|
||||
system: SYSTEM_MESSAGE,
|
||||
options: {temperature},
|
||||
stream: true
|
||||
})
|
||||
});
|
||||
|
||||
const getContent = json => {
|
||||
if (json.response) onContent(json.response);
|
||||
};
|
||||
|
||||
await handleStream(response, getContent);
|
||||
}
|
||||
|
||||
async function handleStream(response, getContent) {
|
||||
if (!response.ok) {
|
||||
const json = await response.json();
|
||||
throw new Error(json?.error?.message || "Failed to generate");
|
||||
let errorMessage = `Failed to generate (${response.status} ${response.statusText})`;
|
||||
try {
|
||||
const json = await response.json();
|
||||
errorMessage = json.error?.message || json.error || errorMessage;
|
||||
} catch {}
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
const reader = response.body.getReader();
|
||||
|
|
@ -95,13 +130,14 @@ async function handleStream(response, getContent) {
|
|||
|
||||
for (let i = 0; i < lines.length - 1; i++) {
|
||||
const line = lines[i].trim();
|
||||
if (line.startsWith("data: ") && line !== "data: [DONE]") {
|
||||
try {
|
||||
const json = JSON.parse(line.slice(6));
|
||||
getContent(json);
|
||||
} catch (jsonError) {
|
||||
ERROR && console.error(`Failed to parse JSON:`, jsonError, `Line: ${line}`);
|
||||
}
|
||||
if (!line) continue;
|
||||
if (line === "data: [DONE]") break;
|
||||
|
||||
try {
|
||||
const parsed = line.startsWith("data: ") ? JSON.parse(line.slice(6)) : JSON.parse(line);
|
||||
getContent(parsed);
|
||||
} catch (error) {
|
||||
ERROR && console.error("Failed to parse line:", line, error);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -214,15 +214,15 @@ function overviewMarkers() {
|
|||
|
||||
const body = pack.markers.map(marker => {
|
||||
const {i, type, icon, x, y} = marker;
|
||||
const id = `marker${i}`;
|
||||
const note = notes.find(note => note.id === id);
|
||||
|
||||
const note = notes.find(note => note.id === "marker" + i);
|
||||
const name = note ? quote(note.name) : "Unknown";
|
||||
const legend = note ? quote(note.legend) : "";
|
||||
|
||||
const lat = getLatitude(y, 2);
|
||||
const lon = getLongitude(x, 2);
|
||||
|
||||
return [id, type, icon, name, legend, x, y, lat, lon].join(",");
|
||||
return [i, type, icon, name, legend, x, y, lat, lon].join(",");
|
||||
});
|
||||
|
||||
const data = headers + body.join("\n");
|
||||
|
|
|
|||
|
|
@ -121,11 +121,16 @@ function editUnits() {
|
|||
|
||||
function addRuler() {
|
||||
if (!layerIsOn("toggleRulers")) toggleRulers();
|
||||
|
||||
const width = Math.min(graphWidth, svgWidth);
|
||||
const height = Math.min(graphHeight, svgHeight);
|
||||
const pt = byId("map").createSVGPoint();
|
||||
(pt.x = graphWidth / 2), (pt.y = graphHeight / 4);
|
||||
pt.x = width / 2;
|
||||
pt.y = height / 4;
|
||||
const p = pt.matrixTransform(viewbox.node().getScreenCTM().inverse());
|
||||
const dx = graphWidth / 4 / scale;
|
||||
const dy = (rulers.data.length * 40) % (graphHeight / 2);
|
||||
|
||||
const dx = width / 4 / scale;
|
||||
const dy = (rulers.data.length * 40) % (height / 2);
|
||||
const from = [(p.x - dx) | 0, (p.y + dy) | 0];
|
||||
const to = [(p.x + dx) | 0, (p.y + dy) | 0];
|
||||
rulers.create(Ruler, [from, to]).draw();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue