Add static website

This commit is contained in:
Feufochmar 2019-11-05 17:40:09 +01:00
parent a57c915f94
commit fd2ca1de7a
3 changed files with 441 additions and 0 deletions

98
web/gener-communes.css Normal file
View File

@ -0,0 +1,98 @@
body {
margin-left: 15%;
margin-right: 15%;
background-color: hsl(230, 80%, 15%);
color: hsl(230, 10%, 10%);
border-color: hsl(230, 10%, 15%);
}
h1 {
margin: 1px;
padding: 1px;
}
h2 {
margin: 1px;
padding: 1px;
}
h3 {
margin: 1px;
padding: 1px;
}
h4 {
margin: 1px;
padding: 1px;
}
h5 {
margin: 1px;
padding: 1px;
}
h6 {
margin: 1px;
padding: 1px;
}
hr {
border-style: solid;
border-width: thin;
}
header {
background-color: hsla(230, 10%, 90%);
border-style: solid;
border-width: thin;
border-radius: 5px;
margin: 2px;
padding: 5px;
text-align: center;
}
footer {
background-color: hsla(230, 10%, 90%);
border-style: solid;
border-width: thin;
border-radius: 5px;
margin: 2px;
padding: 5px;
text-align: center;
}
article {
background-color: hsla(230, 10%, 90%);
border-style: solid;
border-width: thin;
border-radius: 5px;
margin: 2px;
padding: 10px;
}
p {
margin-left: 7px;
}
#genercommunes-output {
text-align: center;
}
#commune-name {
background-color: white;
font-size: 300%;
font-family: sans-serif;
font-variant: small-caps;
font-weight: bold;
border-style: solid;
border-radius: 30px;
border-color: red;
border-width: 20px;
padding: 10px;
margin: 10px;
display: inline-block;
}

324
web/gener-communes.js Normal file
View File

@ -0,0 +1,324 @@
// Gener-Communes Web
// Browser-based gerenator for gener-communes outputs
// Main object
var genercommunes = {}
// Discrete distribution
// The distribution object defines a discrete distribution
genercommunes.Distribution = function () {
this.total = 0 // Total number of elements in the distribution
this.items = new Map() // Map of item -> number of elements
}
// Add 'occur' number of 'elem' elements into the distribution
genercommunes.Distribution.prototype.addTo = function (elem, occur) {
this.total += occur
if (this.items.has(elem)) {
this.items.set(elem, occur + this.items.get(elem))
} else {
this.items.set(elem, occur)
}
}
// Pick a random element from the distribution
genercommunes.Distribution.prototype.generate = function () {
var idx = Math.floor(Math.random() * this.total)
var acc = 0
var pick = undefined
for (var [elem, occur] of this.items)
{
acc += occur
pick = elem
if (acc > idx) {
break
}
}
return pick
}
// Parse a distribution from the serialized model
genercommunes.Distribution.parse = function (dist) {
var ret = new genercommunes.Distribution()
for (var elem of dist) {
ret.addTo(elem.value, elem.count)
}
return ret
}
// Chain generator
// This generator makes an array of elements from a table of current chain -> next element
genercommunes.ChainGenerator = function (order) {
this.order = order
this.nextItems = new Map()
}
// Populate the table of next elements of a given sequence from a description
genercommunes.ChainGenerator.prototype.addSequence = function (sequence, distribution) {
this.nextItems.set(sequence.toString(), distribution) // note: toString() when setting and getting to be able to compare the arrays
}
// Generate an array of elements
genercommunes.ChainGenerator.prototype.generate = function () {
var next = function (cg, current, output) {
var nextElem = cg.nextItems.get(current.toString()).generate()
if (nextElem === false) {
return output
} else {
current.shift()
current.push(nextElem)
output.push(nextElem)
return next(cg, current, output)
}
}
var current = new Array()
for (var i = 0; i < this.order; ++i) {
current.push(false)
}
return next(this, current, new Array())
}
// Parse a Chain generator from the serialized model
genercommunes.ChainGenerator.parse = function (gen) {
var ret = new genercommunes.ChainGenerator(gen.order)
for (var next of gen.next) {
ret.addSequence(next.sequence, genercommunes.Distribution.parse(next.distribution))
}
return ret
}
// Departement
// Build from a serialized model
genercommunes.Departement = function (dep) {
this.id = dep.id
this.name = dep.name
// Distributions
this.patterns = genercommunes.Distribution.parse(dep['patterns'])
this.wordMasculine = genercommunes.Distribution.parse(dep['word-masculine'])
this.wordFeminine = genercommunes.Distribution.parse(dep['word-feminine'])
this.wordPlural = genercommunes.Distribution.parse(dep['word-plural'])
this.wordMasculinePlural = genercommunes.Distribution.parse(dep['word-masculine-plural'])
this.wordFemininePlural = genercommunes.Distribution.parse(dep['word-feminine-plural'])
this.personNameMasculine = genercommunes.Distribution.parse(dep['person-name-masculine'])
this.personNameFeminine = genercommunes.Distribution.parse(dep['person-name-feminine'])
// Chain generators
this.localityName = genercommunes.ChainGenerator.parse(dep['locality-name'])
this.areaName = genercommunes.ChainGenerator.parse(dep['area-name'])
this.riverName = genercommunes.ChainGenerator.parse(dep['river-name'])
}
// Format a generated word from a chain generator into a string
genercommunes.formatWord = function (listChar) {
var text = ''
for (var char of listChar) {
text += char
}
return text
}
// Replace the patterns
// returns the input with all the pattern strings replaced by generated values
// Recursive on arrays
genercommunes.Departement.prototype.replacePatterns = function (pat) {
if (Array.isArray(pat)) {
return pat.map(x => this.replacePatterns(x))
} else {
switch (pat) {
case '$WordMasculine$':
return this.wordMasculine.generate()
case '$WordFeminine$':
return this.wordFeminine.generate()
case '$WordPlural$':
return this.wordPlural.generate()
case '$WordMasculinePlural$':
return this.wordMasculinePlural.generate()
case '$WordFemininePlural$':
return this.wordFemininePlural.generate()
case '$PersonNameMasculine$':
return this.personNameMasculine.generate()
case '$PersonNameFeminine$':
return this.personNameFeminine.generate()
case '$LocalityName$':
return genercommunes.formatWord(this.localityName.generate())
case '$AreaName$':
return genercommunes.formatWord(this.areaName.generate())
case '$RiverName$':
return genercommunes.formatWord(this.riverName.generate())
default:
return pat
}
}
}
// Check if a string starts with a vowel
genercommunes.isStartingWithVowel = function (str) {
var nfd = str.normalize('NFD'); // Normalize to remove the accents on the first character
return ['A', 'E', 'I', 'O', 'U', 'Y'].includes(nfd.charAt(0)) // Note: the generated words start with an uppercase.
}
// Transform an array tree of the patterns to a string
genercommunes.Departement.prototype.treeToString = function (tree) {
if (Array.isArray(tree)) {
switch (tree[0]) {
case 'el':
case 'sans':
case 'la':
case 'les':
case 'las':
case 'los':
case 'Saint':
case 'San':
case 'Sainte':
case 'Santa':
return tree[0] + '-' + this.treeToString(tree[1])
case 'le':
// elision possible
var follow = this.treeToString(tree[1])
if (genercommunes.isStartingWithVowel(follow)) {
return "l'" + follow
} else {
return 'le-' + follow
}
case 'Santo':
// elision possible
var follow = this.treeToString(tree[1])
if (genercommunes.isStartingWithVowel(follow)) {
return "Sant'" + follow
} else {
return 'Santo-' + follow
}
case 'et':
case 'sous':
case 'lès':
case 'lez':
case 'près':
case 'à':
case 'en':
case 'di':
case 'sur':
return this.treeToString(tree[1]) + '-' + tree[0] + '-' + this.treeToString(tree[2])
case 'de':
// elision possible
var follow = this.treeToString(tree[2])
if (genercommunes.isStartingWithVowel(follow)) {
return this.treeToString(tree[1]) + "-d'" + follow
} else {
return this.treeToString(tree[1]) + "-de-" + follow
}
default:
var str = ''
var first = true
for (var elem of tree) {
if (!first) {
str += '-'
}
first = false
str += this.treeToString(elem)
}
return str
}
} else {
return tree
}
}
// Apply elision rules
genercommunes.applyElisions = function (str) {
var ret = str
// in the middle of the string
ret = ret.replace(/-à-les-/gu, '-aux-')
ret = ret.replace(/-de-los-/gu, '-dels-')
ret = ret.replace(/-de-el-/gu, '-del-')
ret = ret.replace(/-de-les-/gu, '-des-')
ret = ret.replace(/-de-le-/gu, '-du-')
ret = ret.replace(/-à-le-/gu, '-au-')
// at the beginning of the string
ret = ret.replace(/^la-/u, 'La ')
ret = ret.replace(/^le-/u, 'Le ')
ret = ret.replace(/^les-/u, 'Les ')
ret = ret.replace(/^l'/u, "L'")
ret = ret.replace(/^los-/u, 'Los ')
//
return ret
}
// Generate a new name
genercommunes.Departement.prototype.generateName = function () {
// Pattern to use
var nameArray = this.replacePatterns(this.patterns.generate())
// Transform the tree to a string
var nameStr = this.treeToString(nameArray)
// Remove elisions & return
return genercommunes.applyElisions(nameStr)
}
// Region
// Build from a serialized model
genercommunes.Region = function (region) {
this.id = region.id
this.name = region.name
// Each region contains a map of departements
this.departements = new Map()
for (var departement of region.departements) {
this.departements.set(departement.id, new genercommunes.Departement(departement))
}
// Add a pseudo-departement, for combining at region-level
// TODO
}
// Model of the genercommunes generator
genercommunes.model = {}
// Generate a name
genercommunes.generateName = function () {
var selector = document.getElementById('generator-selector')
var generatorId = selector.options[selector.selectedIndex].value
var splitId = generatorId.split(' ')
var regId = splitId[0]
var depId = splitId[1]
var departement = genercommunes.model.regions.get(regId).departements.get(depId)
document.getElementById('commune-name').innerHTML = departement.generateName()
}
// Draw the genercommunes div
genercommunes.drawDiv = function (model) {
var contents = '<div id="genercommunes-output">'
contents += '<label for="generator-selector">Choisissez un département</label><br/>'
contents += '<select id="generator-selector">'
for (var [regId, reg] of model.regions) {
contents += '<optgroup label="' + reg.name + '">'
for (var [depId, dep] of reg.departements) {
contents += '<option value="' + regId + " " + depId + '">' + dep.name + '</option>'
}
contents += '</optgroup>'
}
contents += '</select>'
contents += '<button onClick="genercommunes.generateName()">Générer</button>'
contents += '<br/>'
contents += '<span id="commune-name"> </span><br/></div>'
document.getElementById('genercommunes').innerHTML = contents
}
// Load the model
genercommunes.loadModel = function (model) {
// Parse the raw model
// Regions
genercommunes.model.regions = new Map()
for (var region of model) {
genercommunes.model.regions.set(region.id, new genercommunes.Region(region))
}
// Add a pseudo-region with a pseudo-departement combining all regions
// TODO
// Draw the genercommunes <div>
genercommunes.drawDiv(genercommunes.model)
// Generate a first name
genercommunes.generateName()
}
// Loading function for Gener-Communes
genercommunes.load = function (jsonFile) {
fetch(jsonFile)
.then(function(response) {
return response.json()
})
.then(genercommunes.loadModel)
}
// Export info
//module.exports = genercommunes

19
web/index.html Normal file
View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<title>Un Village en France</title>
<meta charset="UTF-8" />
<link href="gener-communes.css" rel="stylesheet" type="text/css" media="all" />
<script src="gener-communes.js"></script>
</head>
<body>
<header>
<h1>Un Village en France</h1>
</header>
<article>
<div id="genercommunes"></div>
</article>
<footer>Un générateur de nom de commune française, par Feufochmar.</footer>
</body>
<script>genercommunes.load('gener-communes.json')</script>
</html>