Table of Contents

BioOSM

Biologicke zbrane ve vasem okoli
bioosm.jpg
founder: sachy
depends on:
interested: sumie-dh
software license: CC-BY-SA
hardware license: N/A

~~META: status = active &relation firstimage = :project:bioosm:bioosm.jpg ~~

BioOSM je mapa vyskytu mikroorganismu (ras, bakterii, plostenek, …) a do budoucna i dalsich prirodnin (mineralu, …).

K cemu to je

Jak to funguje

Podklad jsou OSM, ktere maji API OpenLayers jez umoznuje pridavat do mapy vlastni body, vrstvy…

Jednotliva pozorovani jsou v databazi Tellico. Udelal jsem script parse_tellico.sh, ktery z .tc databaze (je to vlastne ZIP s XML uvnitr) vyparsuje jednotlive polozky a vygeneruje HTML soubor s mapou a podadresar “det” s HTML strankami s detaily jednotlivych pozorovani. Vygeneruje se taky JSON s vyparsovanymi polozkami, ktery lze z webu projektu stahnout.

Pro nadsence je vygenerovany taky prehled prispevku plainlog.htm serazeny dle data pridani do databaze.

Pokud chcete vedet co je noveho, odebirejte projektovou RSS

Obrazky v plnem rozliseni jsou v podadresari “img”, nahledy v “simg”. Videa jsou nahrana na YT a misto nahledu maji generickou ikonu.

Pozorovani ktera se v mape zobrazi lze filtrovat dle prislusnosti k radu (bakterie, zvirata, rostliny,…) az po prislusnost k jednotlivym druhum.

Tellico sample database

Az se mi ho podari nekam nahrat tak nekde bude. Nebo mozna nejaky webxicht…

Kusy zdrojaku k nezapomenuti

Extrakce polozek z Tellico databaze

  1. ziskani tellico.xml
  2. radkovani dle polozek
  3. pouze verejne (strcit-do-mapy = yep)
  4. preneseni lokality na zacatek radku s informacemi o polozce
  5. seskupeni dle lokality
praseTC=$(unzip -p "$1" tellico.xml | tr -d '\n' | sed -e $'s/<entry id="/\\\n<entry id="/g' -e $'s/<\/entry>/<\/entry>\\\n/g' | grep -Pe '^<entry id="' | grep "<strcit-do-mapy>yep</strcit-do-mapy>" | sed -E 's/(^.*)(<locality>.*<\/locality>)(.*$)/\2\1\3/' | sort)

Prepinani vrstev

Nazvy vrstev musi byt v JS poli kvuli ovladacimu API (skryti/zobrazeni)

var laycon = [vectorLayer,ALL];
...
laycon.push(vrstva);
var controls = {
  selector: new OpenLayers.Control.SelectFeature(laycon,{onSelect: createPopup, onUnselect: destroyPopup})
};
map.addControl(controls['selector']);
controls['selector'].activate();

Prepnuti viditelnych vrstev

function kinchange() {
  kinsel=document.getElementById('kin');
  kinopt=kinsel.options[kinsel.selectedIndex].text;
  for (var i = map.layers.length - 1; i >= 1; i--) {
    map.removeLayer(map.layers[i]);
  }
  map.addLayer(window[kinopt])
}

Nastaveni brmlabu do paticky map

OpenLayers.Layer.Vector('Overlay',{attribution:'<a href="http://brmlab.cz">Brmlab</a>'});

Umisteni copyrightu

OSM maji defaultne copyright nesmyslne odsazeny od spodniho okraje mapy, CSS zmena na nejaky rozumny offset:

.olControlAttribution
{
  bottom:0.5em;
}

parse_tellico.sh

parse_tellico.sh
#!/bin/bash
# Parse Tellico database to BioOSM index.htm
# $1 = tellico .tc file
# $2 = "" terminal stderr (default)
#    = "html" html marked stderr (for web bioosm)
#
# Print result to /jsonrss/*.json
#
# find ./ -type f -name '*.jpg' -newermt "2023-09-03" -exec mogrify -verbose -layers Dispose -resize 1600\>x1600\> -quality 90% {} +
# echo "14.7345 48.7145" | gdallocationinfo -wgs84 ./cesko_big.tiff
# gdal_translate -of GTiff -a_srs WGS84 -a_ullr 11.6863 50.9745 19.9876 48.3729 ./source.tif ./result.tif
# https://data.geus.dk/egdi/#baslay=baseMapGEUS&extent=3953440,2399890,4757540,2763830&layers=igme5000
 
#bnds=new OpenLayers.Bounds(11.6863000,48.3729000 ,19.9876000,50.9745000);
#var geoimg = new OpenLayers.Layer.Image("geo","https://brmlab.s0c4.net/bioosm/eusr5000_600dpi_cesko.png", bnds,bnds.getSize(),{numZoomLevels: 20,isBaseLayer:false});
#map.addLayer(geoimg);
 
 
#
# <iframe width="500" height="500" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="https://www.openstreetmap.org/export/embed.html?bbox=14.978000%2C49.990000%2C15.022000%2C50.010000&amp;layer=mapnik&amp;marker=50.000000%2C15.000000"></iframe>
# // vectorLayer.removeFeatures(atol)
# // map.removeLayer(vectorLayer)
#
#
# Creates:
#   (to stdout) HTML file with the map and static entries
#   ./det/ID.htm details of each and every entry
#   ./bioosm.json JSON of all entries
#   ./bioosm.rss updated RSS feed
#   ./plainlog.htm sorted entries for easy human/alg
#
 
 
 
rm -rfv "./det/*"
mkdir -p "./det"
 
ICON_animalia="animalia.png"
ICON_bacteria="bacteria.png"
ICON_fungi="fungi.png"
ICON_chromista="chromista.png"
ICON_plantae="plantae.svg"
ICON_plostenkoid="plostenkoid.png"
ICON_protista="protista.png"
ICON_biohazard="biohazard.svg"
 
json=""
geojson=""
 
rss=$'<?xml version="1.0" encoding="UTF-8" ?>\n'
rss+=$'<rss version="2.0">\n'
rss+=$'<channel>\n'
rss+=$'<title>Brmlab BioOSM RSS feed</title>\n'
rss+=$'<description>New entries in the BioOSM database</description>\n'
rss+=$'<link>https://bioosm.s0c4.net</link>\n'
rss+=$'<lastBuildDate></lastBuildDate>\n'
rss+=$'<pubDate></pubDate>\n'
rss+=$'<ttl>86400</ttl>\n'
 
errhtml="$2"
 
# paticka (co, rok, odkaz)
function obioosm () {
 r="<div id='obioosm'><p>Welcome to BioOSM! This site is owned and maintained by members of the <a href='https://brmlab.cz' target='_blank'>hackerspace brmlab</a>. See our wiki page for further <a href='https://brmlab.cz/project/bioosm/start' target='_blank'>details</a><br>License: <a href='https://creativecommons.org/licenses/by-nc-nd/4.0/' target='_blank'>CC BY-NC-ND</a>. In case you have any questions, suggestions, please let us know at bioosm<span id='zavinacvmejlu'></span>s0c4.net.</p><p>To cite any material (including images) in your publication, please use following format: <br><i>Plskova, K., Sacha, M., brmlab. BioOSM"
	if [[ "$1" != "" ]]; then
		r+=" - $1"
	fi
	r+=". "
	if [[ "$2" != "" ]]; then
		r+="$2. "
	else
		r+="2023. "
	fi
	if [[ "$3" != "" ]]; then
		r+="$3"
	else
		r+="https://bioosm.s0c4.net"
	fi
	r+="</i></p></div>"
	echo "$r"
}
 
# HTML fajl per project
function genhtml() {
	o=$(obioosm "$1" "" "" | sed -e 's/\//\\\//g') # make "\/" from "/" so sed below is OK
	h=$(cat "./__BIOVZOR__.htm" | sed -e "s/__BIOVZOR_TIT__/$1/g" | sed -e "s/__BIOVZOR_CPRT__/$o/g" | sed -e "s/__BIOVZOR_J__/$1/g")
	echo "$h" > "./jsonrss/$1.htm"
	echo "*** $1 done ***"
}
 
# Return icon by Regnum
function geticon () {
	case "$1" in
		"Animalia")
			echo "$ICON_animalia";;
		"Bacteria")
			echo "$ICON_bacteria";;
		"Fungi")
			echo "$ICON_fungi";;
		"Chromista")
			echo "$ICON_chromista";;
		"Plantae")
			echo "$ICON_plantae";;
		"Protista")
			echo "$ICON_protista";;
		*)
			echo "$ICON_biohazard";;
	esac
}
 
function safehtml () {
	echo "$1" | sed -e 's/#/%23/g' -e "s/'/\&#39;/g" -e 's/"/\&#34;/g' -e 's/</\&lt;/g' -e 's/>/\&gt;/g' -e 's/^[ ]*//g' -e 's/[ ]*$//g'
}
 
function getgeo () {
	#g=$(echo "$1 $2" | gdallocationinfo -wgs84 ./geo/eusr5000_600dpi_cesko_8b_geo.tif | grep -v 255 | grep -oPe '[0-9]+$')
	g=$(echo "$1 $2" | gdallocationinfo -wgs84 ./geo/eusr5000_600dpi_cesko_8b_geo.tif | grep -v 255 | grep -oE '[0-9]+$')
	case "$g" in
		"1")
			echo "Fluvial deposits, sediments";;
		"128")
			echo "Weathering residues of different rocks, loess";;
		"130")
			echo "Volcanic rocks";;
		"133")
			echo "Igneous and metamorphic rocks, Palaeozoic sedimentary rocks, loess";;
		"143")
			echo "Loess, igneous and metamorphic rocks";;
		"144")
			echo "Loess, Cretaceous sandstone and marl";;
		"147")
			echo "Igneous, metamorphic and Palaeozoic sedimentary rocks, loess";;
		"148")
			echo "Igneous and metamorphic rocks, loess";;
		"149")
			echo "Igneous and metamorphic rocks, Palaeozoic sedimentary rocks, loess";; # asi fakt stejny jako 133 omg
		"150")
			echo "Igneous and metamorphic rocks, palaeozoic sedimentary rocks";;
		"153")
			echo "Sandy and loamy loess, Tertiary sediments, fluvial deposits";;
		"205")
			echo "Cretaceous and Tertiary flysch, marl, sandstone, limestone";;
		*)
			echo "";;
	esac
}
 
i=1 # GLOBAL increment must persist multiple spagety() calls; incremented to infinity
# Core function generating entries matching selection criteria (ie Kingdom)
# !!! BEZ ODSAZENI !!!
# $1 = list of entries
# $2 = layer name = JSON filename without suffix
# $3 = icon of the points
function spagety () {
 
	if [[ "$errhtml" == "" ]]; then
		>&2 echo "===== $2 ====="
	else
		>&2 echo "<h2>$2</h2>"
	fi
 
	bylo="" # Minula pozice
	sam="" # HTML samostatneho zaznamu
	osam="" # predchozi $sam
	spoj="" # HTML had z popisu stejnych pozic
	ospoj="" # Predchozi $spoj
	ox="" # Old X
	oy="" # Old Y
	datelog="" # Entries sorted by date for plaintext log
	json="var data='{\"version\":\"$(date --rfc-3339=seconds)\",\"fund\":\"$2\",\"arma\":["
	geojson='{"type":"FeatureCollection","version":"BIOOSM_'
	geojson+="$(date --rfc-3339=seconds)"
	geojson+='","features":['
 
	while IFS='' read -r radek || [[ -n "$radek" ]]; do
		if [[ "$radek" = "" ]]; then
			continue;
		fi
 
		entryid=$(echo "$radek" | sed -E 's/^.*<entry id="([0-9]+)">.*$/\1/g;t;d')
		co=$(echo "$radek" | sed -E 's/^.*<title>(.*)<\/title>.*$/\1/g;t;d')
		co=$(safehtml "$co")
		obr=$(echo "$radek" | sed -E 's/^.*<image>(.*)<\/image>.*$/\1/g;t;d' | sed -E 's/^.*\///g')
		kde=$(echo "$radek" | sed -E 's/^.*<locality>(.*)<\/locality>.*$/\1/g;t;d')
		kde=$(safehtml "$kde")
		kdex=$(echo "$kde" | sed -E 's/^[0-9]+\.[0-9]+[, ]*//g;t;d') # keep second part
		kdey=$(echo "$kde" | sed -E 's/[, ]*[0-9]+\.[0-9]+$//g;t;d') # keep first part
		kdy=$(echo "$radek" | sed -E 's/^.*<taken-date>(.*)<\/taken-date>.*$/\1/g;t;d' | sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]{4})/\3-\2-\1/g' | sed -E 's/-([0-9])-/-0\1-/g' | sed -E 's/-([0-9])$/-0\1/g')
		kdy=$(safehtml "$kdy")
		skop_typ=$(echo "$radek" | sed -E 's/^.*<new-field-1>(.*)<\/new-field-1>.*$/\1/g;t;d')
		skop_typ=$(safehtml "$skop_typ")
		skop=$(echo "$radek" | sed -E 's/^.*<microscope>(.*)<\/microscope>.*$/\1/g;t;d')
		skop=$(safehtml "$skop")
		imp=$(echo "$radek" | sed -E 's/^.*<new-field-3>(.*)<\/new-field-3>.*$/\1/g;t;d')
		imp=$(safehtml "$imp")
		reg=$(echo "$radek" | sed -E 's/^.*<new-field-4>(.*)<\/new-field-4>.*$/\1/g;t;d')
		reg=$(safehtml "$reg")
		phy=$(echo "$radek" | sed -E 's/^.*<phylum>(.*)<\/phylum>.*$/\1/g;t;d')
		phy=$(safehtml "$phy")
		cla=$(echo "$radek" | sed -E 's/^.*<class>(.*)<\/class>.*$/\1/g;t;d')
		cla=$(safehtml "$cla")
		ord=$(echo "$radek" | sed -E 's/^.*<order>(.*)<\/order>.*$/\1/g;t;d')
		ord=$(safehtml "$ord")
		fam=$(echo "$radek" | sed -E 's/^.*<family>(.*)<\/family>.*$/\1/g;t;d')
		fam=$(safehtml "$fam")
		gen=$(echo "$radek" | sed -E 's/^.*<genus>(.*)<\/genus>.*$/\1/g;t;d')
		gen=$(safehtml "$gen")
		spe=$(echo "$radek" | sed -E 's/^.*<species>(.*)<\/species>.*$/\1/g;t;d')
		spe=$(safehtml "$spe")
		loc=$(echo "$radek" | sed -E 's/^.*<locality---plaintext>(.*)<\/locality---plaintext>.*$/\1/g;t;d')
		loc=$(safehtml "$loc")
		des=$(echo "$radek" | sed -E 's/^.*<description>(.*)<\/description>.*$/\1/g;t;d')
		des=$(safehtml "$des")
		vid=$(echo "$radek" | sed -E 's/^.*<videolink>(.*)<\/videolink>.*$/\1/g;t;d')
		vid=$(safehtml "$vid")
		bio=$(echo "$radek" | sed -E 's/^.*<biotope>(.*)<\/biotope>.*$/\1/g;t;d')
		bio=$(safehtml "$bio")
		eng=$(echo "$radek" | sed -E 's/^.*<enlargement>(.*)<\/enlargement>.*$/\1/g;t;d')
		eng=$(safehtml "$eng")
		obs=$(echo "$radek" | sed -E 's/^.*<observer>(.*)<\/observer>.*$/\1/g;t;d')
		obs=$(safehtml "$obs")
		lnk=$(echo "$radek" | sed -E 's/^.*<localitylink>(.*)<\/localitylink>.*$/\1/g;t;d')
		lnk=$(safehtml "$lnk")
		har=$(echo "$radek" | sed -E 's/^.*<harvesting-method>(.*)<\/harvesting-method>.*$/\1/g;t;d')
		den=$(echo "$radek" | sed -E 's/^.*<population-density>(.*)<\/population-density>.*$/\1/g;t;d')
		dur=$(echo "$radek" | sed -E 's/^.*<min>(.*)<\/min>.*$/\1/g;t;d')
		lor=$(echo "$radek" | sed -E 's/^.*<locality-reference>(.*)<\/locality-reference>.*$/\1/g;t;d')
		lrl=$(echo "$radek" | sed -E 's/^.*<locality-reference---link>(.*)<\/locality-reference---link>.*$/\1/g;t;d')
		lov=$(echo "$radek" | sed -E 's/^.*<locality---vobrazek>(.*)<\/locality---vobrazek>.*$/\1/g;t;d' | sed -E 's/^.*\///g')
		lov=$(safehtml "$lov")
		cls=$(echo "$radek" | sed -E 's/^.*<cluster>([0-9]*)<\/cluster>.*$/\1/g;t;d')
		mpi=$(echo "$radek" | grep -oe ' <mainpic>yep</mainpic> ')
		elv=$(echo "$kdex $kdey" | gdallocationinfo -wgs84 ./elev/cesko_big.tiff | grep "Value" | grep -oe '[0-9]+$')
		geo=$(getgeo "$kdex" "$kdey")
		gra=$(echo "$radek" | sed -E 's/^.*<grant>(.*)<\/grant>.*$/\1/g;t;d')
		tem=$(echo "$radek" | sed -E 's/^.*<temperature>(.*)<\/temperature>.*$/\1/g;t;d')
		cnd=$(echo "$radek" | sed -E 's/^.*<conductivity>(.*)<\/conductivity>.*$/\1/g;t;d')
		 ph=$(echo "$radek" | sed -E 's/^.*<ph>(.*)<\/ph>.*$/\1/g;t;d')
		kar=$(echo "$radek" | sed -E 's/^.*<karyotype>(.*)<\/karyotype>.*$/\1/g;t;d')
		lid=$(echo "$radek" | sed -E 's/^.*<localityid>(.*)<\/localityid>.*$/\1/g;t;d')
 
#		if [[ "$errhtml" == "" ]]; then
#			>&2 echo "$co - $har - $den - $dur - $lor - $lrl - $lov - $elv"
#		else
#			>&2 echo "<span class='nok'>$co - $har - $den - $dur - $lor - $lrl - $lov - $elv</span><br>"
#		fi
#		continue;
 
		detid=$(echo "brmlab$co$obr$kde$kdy" | md5sum | grep -oe '[a-zA-Z0-9]*')
 
		if [[ "$kdex" = "" ]]; then
			if [[ "$errhtml" == "" ]]; then
				>&2 echo -e "\033[31m $lid KDEX '$kde' '$co' \033[0m"
				>&2 echo -e "\033[31m $lid RADEK '$radek' \033[0m"
			else
				>&2 echo "<span class='nok'>$lid KDEX '$kde' '$co'</span><br>"
				>&2 echo "<span class='nok'><pre>$radek</pre></span>"
			fi
		fi
 
		zkurvenetellico=$(echo "$obr" | grep -oe '\.[a-zA-Z]*$')
		odkurvenyobr=$(echo "$obr" | sed -e 's/%23/#/g')
		#if [[ "$zkurvenetellico" = ".jpeg" ]]; then
		if [[ ! -f "./img/$odkurvenyobr" ]]; then
			if [[ "$gen" != "negative" ]]; then
				if [[ "$errhtml" == "" ]]; then
					>&2 echo -e "\033[31m $lid OBR $odkurvenyobr $co\033[0m"
				else
					>&2 echo "<span class='nok'>$lid OBR $odkurvenyobr $co</span>"
				fi
				continue;
			fi
		fi
		obr=$(safehtml "$obr")
 
		if [[ "$spe" = "sp." ]]; then
			wikisp="https://en.wikipedia.org/wiki/$gen"
		else
			wikisp="https://en.wikipedia.org/wiki/$gen $spe"
		fi
 
		povr=""
		povs=""
		pov=""
		if [[ "$phy" = "Platyhelminthes" ]]; then
			povr=$(cat "./povodi_r.json" | ./povodi.py "$kdey" "$kdex")
			#povrf=$(echo "$povr" | grep -oPe '^[^ ]*' | tr 'e' 'E')
			povrf=$(echo "$povr" | sed -e 's/ .*$//g' | tr 'e' 'E')
			povrn=$(echo "$povr" | sed -e 's/^[^ ]* //g')
			povs=$(cat "./povodi_s.json" | ./povodi.py "$kdey" "$kdex")
			#povsf=$(echo "$povs" | grep -oPe '^[^ ]*' | tr 'e' 'E')
			povsf=$(echo "$povs" | sed -e 's/ .*$//g' | tr 'e' 'E')
			povsn=$(echo "$povs" | sed -e 's/^[^ ]* //g')
			if (( $(echo "$povsf < $povrf" | bc -l) )) ; then
				pov="$povsn - $povrn"
			else
				pov="$povrn"
			fi
		fi
 
		if [[ "$cls" = "" ]]; then
			cls=0
		fi
 
		if [[ "$mpi" = "" ]]; then
			mpi=""
		else
			mpi="y"
		fi
 
		Tjson="{"
		Tjson+=" \"title\":\"$co\"," # qualis
		Tjson+=" \"imperium\":\"$imp\","
		Tjson+=" \"regnum\":\"$reg\","
		Tjson+=" \"phylum\":\"$phy\","
		Tjson+=" \"classis\":\"$cla\","
		Tjson+=" \"ordo\":\"$ord\","
		Tjson+=" \"familia\":\"$fam\","
		Tjson+=" \"genus\":\"$gen\","
		Tjson+=" \"specie\":\"$spe\","
		Tjson+=" \"locality\":\"$kde\"," # locus
		Tjson+=" \"x\":\"$kdex\","
		Tjson+=" \"y\":\"$kdey\","
		Tjson+=" \"locplain\":\"$loc\","
		Tjson+=" \"description\":\"$des\"," # depictio
		Tjson+=" \"takendate\":\"$kdy\"," # quando
		Tjson+=" \"obr\":\"$obr\","
		Tjson+=" \"micro\":\"$skop\","
		Tjson+=" \"microtyp\":\"$skop_typ\","
		Tjson+=" \"videolink\":\"$vid\"," # vid
		Tjson+=" \"biotope\":\"$bio\"," # bio
		Tjson+=" \"enlargement\":\"$eng\"," # amp
		Tjson+=" \"observer\":\"$obs\"," # spec
		Tjson+=" \"detid\":\"$detid\","
		Tjson+=" \"harvestingmethod\":\"$har\"," # har
		Tjson+=" \"populationdensity\":\"$den\"," # den
		Tjson+=" \"min\":\"$dur\"," # dur
		Tjson+=" \"localityreference\":\"$lor\"," # lor
		Tjson+=" \"localityreferencelink\":\"$lrl\"," #lrl
		Tjson+=" \"localityvobrazek\":\"$lov\"," # lov
		Tjson+=" \"localitylink\":\"$lnk\"," # lnk
		Tjson+=" \"cluster\":$cls," # cls
		Tjson+=" \"mainpic\":\"$mpi\"," # mpi
		Tjson+=" \"pov\":\"$pov\","
		Tjson+=" \"elv\":\"$elv\","
		Tjson+=" \"geo\":\"$geo\","
		Tjson+=" \"temperature\":\"$tem\"," # tem
		Tjson+=" \"conductivity\":\"$cnd\"," # cnd
		Tjson+=" \"ph\":\"$ph\","
		Tjson+=" \"karyotype\":\"$kar\"" # kar # Last without ','
		Tjson+="}"
 
		json+="$Tjson,"
		geojson+='{"type":"Feature","geometry":{"type":"point","coordinates":['
		geojson+="$kdex,$kdey"
		geojson+=']},"properties":'
		geojson+="$Tjson},"
 
		rss+=$'<item>\n'
		rss+=$'  <title>'"$co"$'</title>\n'
		rss+=$'  <description>'"$des"$'</description>\n'
		rss+=$'  <link>http://brmlab.s0c4.net/bioosm/det/'"$detid"$'.htm</link>\n'
		rss+=$'  <guid isPermaLink="false">'"$detid"$'</guid>\n'
		rss+=$'  <pubDate>'"$kdy"$'</pubDate>\n'
		rss+=$'</item>\n'
 
 
		# Generate detail page
		detid=$(echo "brmlab$co$obr$kde$kdy" | md5sum | grep -oe '[a-zA-Z0-9]*')
		detpg="<html><head>"
		detpg+="<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>"
		detpg+="<link rel='stylesheet' href='../style.css' type='text/css'>"
		detpg+="<title>Brmlab - BioOSM $co $kde</title>"
 
		detpg+="<meta property='og:title' content='BioOSM - $co $kde'>"
		detpg+="<meta property='og:description' content='$obs found $co and took an image and additional notes.'>"
		detpg+="<meta property='og:image' content='https://brmlab.s0c4.net/bioosm/img/$obr'>"
		detpg+="<meta property='og:url' content='https://brmlab.s0c4.net/bioosm/det/$detid.htm'>"
		detpg+="<meta name='twitter:card' content='summary_large_image'>"
		detpg+="<meta name='og:type' content='website'>"
		detpg+="<meta property='og:site_name' content='BioOSM - creatures around us'>"
		detpg+="<meta name='twitter:image:alt' content='Image of $co'>"
 
		detpg+="</head>"
		if [[ "$cls" != "0" ]]; then
			detpg+="<script src='../bioosmdet.js'></script>"
			detpg+="<script>getJSONarma($cls)</script>"
		fi
		detpg+="<body>"
		detpg+="<table class='dettbl'><tr>"
		detpg+="<h1>$co (<a href='$wikisp' target='_blank'>wiki</a>)</h1>"
		detpg+="<td style='width:33%;vertical-align:top'>"
		if [[ "$imp" != "" ]]; then
			detpg+="<b>Domain:</b> <a href='https://en.wikipedia.org/wiki/$imp' target='_blank'>$imp</a><br>"
		fi
		if [[ "$reg" != "" ]]; then
			detpg+="<b>Kingdom:</b> <a href='https://en.wikipedia.org/wiki/$reg' target='_blank'>$reg</a><br>"
		fi
		if [[ "$phy" != "" ]]; then
			detpg+="<b>Phylum:</b> <a href='https://en.wikipedia.org/wiki/$phy' target='_blank'>$phy</a><br>"
		fi
		if [[ "$cla" != "" ]]; then
			detpg+="<b>Class:</b> <a href='https://en.wikipedia.org/wiki/$cla' target='_blank'>$cla</a><br>"
		fi
		if [[ "$ord" != "" ]]; then
			detpg+="<b>Order:</b> <a href='https://en.wikipedia.org/wiki/$ord' target='_blank'>$ord</a><br>"
		fi
		if [[ "$fam" != "" ]]; then
			detpg+="<b>Family:</b> <a href='https://en.wikipedia.org/wiki/$fam' target='_blank'>$fam</a><br>"
		fi
		if [[ "$gen" != "" ]]; then
			detpg+="<b>Genus:</b> <a href='https://en.wikipedia.org/wiki/$gen' target='_blank'>$gen</a><br>"
		fi
		if [[ "$spe" != "" ]]; then
			detpg+="<b>Species:</b> <a href='$wikisp' target='_blank'>$spe</a><br>"
		fi
		if [[ "$kar" != "" ]]; then
			detpg+="<b>Karyotype:</b> $kar<br>"
		fi
		detpg+="<br>"
		if [[ "$kdy" != "" ]]; then
			detpg+="<b>Date:</b> $kdy<br>"
		fi
		if [[ "$lnk" != "" ]]; then
			loc="<a href=\"$lnk\" target=\"_blank\">$loc</a>" # Yes, escaped "
		fi
		detpg+="<b>Place:</b> $kde ($loc)<br>"
		if [[ "$elv" != "" ]]; then
			detpg+="<b>Elevation:</b> $elv m<br>"
		fi
 
		if [[ "$obs" != "" ]]; then
			detpg+="<b>Observer:</b> $obs<br>"
		fi
		if [[ "$bio" != "" ]]; then
			detpg+="<b>Biotope:</b> $bio<br>"
		fi
		if [[ "$pov" != "" ]]; then
			detpg+="<b>River:</b> $pov<br>"
		fi
		if [[ "$geo" != "" ]]; then
			detpg+="<b>Bedrock:</b> $geo<br>"
		fi
		if [[ "$tem" != "" ]]; then
			detpg+="<b>Temperature:</b> $tem °C<br>"
		fi
		if [[ "$cnd" != "" ]]; then
			detpg+="<b>Conductivity:</b> $cnd mSv<br>"
		fi
		if [[ "$ph" != "" ]]; then
			detpg+="<b>pH:</b> $ph<br>"
		fi
		detpg+="<span id='microscopeval'>"
		if [[ "$skop" != "" ]]; then
			detpg+="<b>Microscope:</b> $skop ($skop_typ)<br>"
		fi
		detpg+="</span>"
		detpg+="<span id='ampval'>"
		if [[ "$eng" != "" ]]; then
			detpg+="<b>Amplification:</b> $eng<br>"
		fi
		detpg+="</span>"
		if [[ "$vid" != "" ]]; then
			detpg+="<b>Video:</b> <a href=\"$vid\" target=\"_blank\">$vid</a><br>"
		fi
		if [[ "$har" != "" ]]; then
			detpg+="<b>Collecting method:</b> $har<br>"
		fi
		if [[ "$den" != "" ]]; then
			detpg+="<b>Individuals found:</b> $den<br>"
		fi
		if [[ "$dur" != "" ]]; then
			detpg+="<b>Duration on stage:</b> $dur<br>"
		fi
		if [[ "$lrl" != "" ]]; then
			detpg+="<b>Locality reference:</b> <a href=\"$lrl\" target=\"_blank\">$lor</a><br>"
		elif [[ "$lor" != "" ]]; then
			detpg+="<b>Locality reference:</b> $lor<br>"
		fi
		detpg+="<span id='descval'>"
		if [[ "$des" != "" ]]; then
			detpg+="<b>Description:</b> $des<br>"
		fi
		detpg+="</span>"
		detpg+="<br><b>More on <a href=\"../\">BioOSM map</a></b><br>"
		detpg+="<br>"
 
		lhx=$(echo "$kdex-0.022" | bc)
		lhy=$(echo "$kdey-0.010" | bc)
		pdx=$(echo "$kdex+0.022" | bc)
		pdy=$(echo "$kdey+0.010" | bc)
		detpg+="<iframe id='minimapa' src='https://www.openstreetmap.org/export/embed.html?bbox=$lhx%2C$lhy%2C$pdx%2C$pdy&amp;layer=mapnik&amp;marker=$kdey%2C$kdex'></iframe>"
		detpg+="</td><td style='min-width:66%;vertical-align:top'>"
 
		if [[ "$obr" != "" ]]; then
			detpg+="<div id='maximatura'><a href=\"../img/$obr\"><img src=\"../img/$obr\" alt=\"$co\" class='detimg'></a></div>"
			detpg+="<div id='miniatury'></div>"
		else
			if [[ "$vid" != "" ]]; then
				detyt=$(echo "$vid" | sed -e 's/youtube.com\/watch?v=/youtube.com\/embed\//g')
				detpg+="<iframe class='detvid' src='$detyt' frameborder='0' allow='encrypted-media' allowfullscreen></iframe>"
			else
				if [[ "$gen" == "negative" ]]; then
					detpg+="<img src=\"../negative.png\" alt=\"Negative observation\" class='detimg'>"
				else
					detpg+="<img src=\"../$3\" alt=\"video\" class='detimg'>"
				fi
			fi
		fi
		if [[ "$lov" != "" ]]; then
			detpg+="<img class=\"detimg\" src=\"../lokality/$lov\" alt=\"Locality photo\"><br>"
		fi
 
		detpg+="</td></tr></table>"
		detpg+=$(obioosm "$co" "$quando" "https://brmlab.s0c4.net/bioosm/det/$detid.htm")
		detpg+="</body><script>document.getElementById('zavinacvmejlu').innerHTML='@'</script></html>"
		echo "$detpg" > "./det/$detid.htm"
 
		# Plain log of entries
		datelog+="$kdy $kde <a href='./det/$detid.htm' target='_blank'>$co</a><br>\n"
 
		if [[ "$errhtml" == "" ]]; then
			>&2 echo -e "\033[32m$lid $co $obs\033[0m"
		else
			>&2 echo "<span class='ok'>$lid $co $obs</span>"
		fi
 
		ox="$kdex"
		oy="$kdey"
 
		i=$(($i+1))
 
	done <<< $(echo "$1") # Zere parametr spaget, nikoli $1 scriptu !!!
	echo -e "$json{}]}" | sed -e "s/^var data='//g" > "./jsonrss/$2.json"
#	echo -e "$json{}]}'"
	echo -e "$geojson{}]}" > "./jsonrss/geo_$2.geojson"
 
	rss+=$'</channel>\n'
	rss+=$'</rss>\n'
	echo "$rss" > "./jsonrss/$2.rss"
 
} # KONEC FCE SPAGETY
 
 
 
# Sorted unique Kingdoms (to be passed as selection criteria)
#kingdoms=$(unzip -p "$1" tellico.xml | grep -oe '<new-field-4>.*</new-field-4>' | sed -E 's/( )*<(\/)?new-field-4>( )*//g' | sort | uniq)
kingdoms=$(unzip -p "$1" tellico.xml | sed -E 's/^.*<new-field-4>(.*)<\/new-field-4>.*$/\1/g;t;d' | sort | uniq)
 
#echo '<!DOCTYPE html>'
#echo '<html>'
#echo '<head>'
#echo '	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'
#echo '	<title>brmlab - BioOSM</title>'
#echo '	<link rel="stylesheet" href="./style.css" type="text/css">'
#echo '	<link rel="favicon" href="./'$ICON_biohazard'">'
#echo '	<script src="./OpenLayers.js"></script>'
#echo '</head>'
#echo '<body>'
## Generate select
#echo "<div id='plainlog'><b><a href='./bioosm.rss'>RSS feed</a><br><a href='./plainlog.htm'>Quick news log</a></b></div>"
##echo "<h1 id='title'>BioOSM - arma biologica in tuis vicinia</h1>"
#echo "<h1 id='title'>BioOSM - creatures around us</h1>"
#
#ksel="<select id='reg' onChange='genphy()'>"
#ksel="$ksel<option value='ALL' selected>ALL</option>"
#while IFS='' read -r king || [[ -n "$king" ]]; do
#	ksel="$ksel<option value='"$king"'>$king</option>"
#done <<< $(echo "$kingdoms")
#ksel="$ksel</select>"
#echo "Kingdom: $ksel "
#echo "Phylum: <select id='phy' onChange='gencla()'><option>ALL</option></select> "
#echo "Class: <select id='cla' onChange='genord()'><option>ALL</option></select> "
#echo "Order: <select id='ord' onChange='genfam()'><option>ALL</option></select> "
#echo "Family: <select id='fam' onChange='gengen()'><option>ALL</option></select> "
#echo "Genus: <select id='gen' onChange='genspe()'><option>ALL</option></select>"
#echo "Species: <select id='spe' onChange='armageddon()'><option>ALL</option></select>"
#
#echo "<br><input type='button' value='Platyhelminthes' onClick='plostenkoidy()'>"
#echo "<label><input type='checkbox' id='studchecker' onChange='studdrv()'>Springs</label>"
##echo "<input type='button' value='Bugs' onClick='buggy()'>"
#echo "<form style='display:inline;margin-left:5em'><input type='text' length=10 id='srch'><input type='submit' value='&#x1F50D;' onClick='limit();return false;'></form>"
#echo "<br><br><div id='map' class='smallmap'></div>"
#echo $(obioosm "" "" "")
#echo "</body>"
#
#echo "<script>"
#echo 'document.getElementById("zavinacvmejlu").innerHTML="@";'
#echo 'map = new OpenLayers.Map("map");'
#echo 'map.addLayer(new OpenLayers.Layer.OSM());'
#echo 'epsg4326 =  new OpenLayers.Projection("EPSG:4326"); //WGS 1984 projection'
#echo 'projectTo = map.getProjectionObject(); //The map projection (Spherical Mercator)'
#echo 'var lonLat = new OpenLayers.LonLat(15.478, 49.817).transform(epsg4326, projectTo);'
#echo 'var zoom=8;'
#echo 'map.setCenter (lonLat, zoom);'
#
#echo 'var vectorLayer = new OpenLayers.Layer.Vector("Overlay",{attribution:"<a href=\"http://brmlab.cz\">Brmlab</a>"});'
#
#echo '// Define markers as "features" of the vector layer:'
#
#echo 'var atol = new OpenLayers.Feature.Vector('
#echo '	new OpenLayers.Geometry.Point(14.41876, 50.10554).transform(epsg4326, projectTo),'
#echo '		{description:"Atomovy atol Brmkini"} ,'
#echo '		{externalGraphic: "./biohazard.svg", graphicHeight:8, graphicWidth:8, graphicXOffset:-4, graphicYOffset:-4},'
#echo ');'
#echo 'vectorLayer.addFeatures(atol);'
## Sem prijdou dalsi staticke ficury
#echo "map.addLayer(vectorLayer);"
#
 
 
# Parse Tellico file to get list of entries
granty=$(unzip -p "$1" tellico.xml | grep "<grant>" | sed -E 's/( )*<(\/)?grant>( )*//g' | sed -E 's/_additional$//g' | sort -u | grep -v "^none$")
#praseTC=$(unzip -p "$1" tellico.xml | tr -d '\n' | sed -e $'s/<entry id="/\\\n<entry id="/g' -e $'s/<\/entry>/<\/entry>\\\n/g' | grep -Pe '^<entry id="' | grep "<strcit-do-mapy>yep</strcit-do-mapy>" | sed -E 's/(^.*)(<locality>.*<\/locality>)(.*$)/\2\1\3/' | sort)
#praseTC=$(unzip -p "$1" tellico.xml | tr -d '\n' | sed -e $'s/<entry id="/\\\n<entry id="/g' -e $'s/<\/entry>/<\/entry>\\\n/g' | grep -Pe '^<entry id="' | sed -E 's/(^.*)(<locality>.*<\/locality>)(.*$)/\2\1\3/' | sort)
praseTC=$(unzip -p "$1" tellico.xml | tr -d '\n' | sed -e $'s/<entry id="/\\\n<entry id="/g' -e $'s/<\/entry>/<\/entry>\\\n/g' | grep -E '^<entry id="' | sed -E 's/(^.*)(<locality>.*<\/locality>)(.*$)/\2\1\3/' | sort)
 
 
velkyvepr=$(echo "$praseTC" | grep "<strcit-do-mapy>yep</strcit-do-mapy>")
spagety "$velkyvepr" "bioosm" "$ICON_biohazard"
 
# VSECHNO i non-public - zakomentuj predchozi "spagety" a odkomunetuj tohle + exit
#spagety "$praseTC" "celytraktor" "$ICON_biohazard" # vsechno i non-public
#exit
 
while IFS='' read -r grnt || [[ -n "$grnt" ]]; do
 # 'nope' pokud to ma byt jen na grantstrance ale ne ve velkem bioosm
	#vepr=$(echo "$praseTC" | grep -Pe "<strcit-do-mapy>(yep)|(negative)|(nope)</strcit-do-mapy>" | grep -Pe "<grant>$grnt(_additional)?</grant>")
	vepr=$(echo "$praseTC" | grep -E "<strcit-do-mapy>(yep)|(negative)|(nope)</strcit-do-mapy>" | grep -E "<grant>$grnt(_additional)?</grant>")
	spagety "$vepr" "$grnt" "$ICON_biohazard"
	genhtml "$grnt"
done <<< $(echo "$granty")
 
#if [[ "$errhtml" == "html" ]]; then
	>&2 echo "*** DONE ***"
#fi
 
 
##echo -e "$json{}]}"
#echo '</script>'
#echo '<script src="./bioosm.js"></script>' # Must be after JSON
#echo "</html>"
 
# Create plaintext log
dateloghtm="<html><head>"
dateloghtm+="<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>"
dateloghtm+="<link rel='stylesheet' href='./style.css' type='text/css'>"
dateloghtm+="<title>Brmlab - BioOSM plaintext log</title>"
dateloghtm+="</head><body>"
datelogsort=$(echo -e "$datelog" | sort -r | uniq)
dateloghtm+="$datelogsort"
dateloghtm+="</body></html>"
echo "$dateloghtm" > "./plainlog.htm"

bioosm.js

bioosm.js
window.blob=JSON.parse('{}');
window.arma=null;
//
// MAIN LOAD START HERE
// https://web.archive.org/web/20200502112446/http://dev.openlayers.org/releases/OpenLayers-2.13.1/doc/apidocs/files/OpenLayers-js.html
//
//
function getJSONbioosm()
{
	url="./bioosm.json";
	var request;
	if(window.XMLHttpRequest)
		request=new XMLHttpRequest();
	else
		request=new ActiveXObject("Microsoft.XMLHTTP");
	request.onreadystatechange=function()
	{
		if(request.readyState==4)
		{
			window.blob=JSON.parse(request.responseText);
			window.arma=blob.arma;
			// Display ONLY platyhelminthes if reguired
			pus=document.URL.match(/platyhelminthes=understone/);
			console.log(pus);
			if(pus)
				plostenkoidy();
			else
				// Else initial load
				armageddon()
		}
	}
	request.open("GET","./"+ubermaster+".json",true); // defined in html
	request.send();
}
 
getJSONbioosm();
 
var stud=JSON.parse('{}');
 
var vectorLayerDynamic = new OpenLayers.Layer.Vector('Overlay',{attribution:'<a href="http://brmlab.cz">Brmlab</a>'});
var vectorLayerPonygon = new OpenLayers.Layer.Vector('Overlay',{attribution:'<a href="http://brmlab.cz">Brmlab</a>'});
map.addLayer(vectorLayerPonygon);
map.addLayer(vectorLayerDynamic);
//map.setLayerZIndex(vectorLayerDynamic,999);
//map.raiseLayer(vectorLayerDynamic,map.layers.length);
var studlay = new OpenLayers.Layer.Vector("Overlay",{attribution:"<a href=\"http://brmlab.cz\">Brmlab</a>"}); // studanky
map.addLayer(studlay);
 
var regsel=document.getElementById("reg")
var physel=document.getElementById("phy")
var clasel=document.getElementById("cla")
var ordsel=document.getElementById("ord")
var famsel=document.getElementById("fam")
var gensel=document.getElementById("gen")
var spesel=document.getElementById("spe")
 
var ICON_animalia="animalia.png"
var ICON_bacteria="bacteria.png"
var ICON_fungi="fungi.png"
var ICON_chromista="chromista.png"
var ICON_plantae="plantae.svg"
var ICON_plostenkoid="plostenkoid.png"
var ICON_protista="protista.png"
var ICON_biohazard="biohazard.svg"
var ICON_studanka="studanka.png"
var ICON_negative="negative.png"
 
 
function getJSONstud()
{
	url="./stud.json";
	var request;
	if(window.XMLHttpRequest)
		request=new XMLHttpRequest();
	else
		request=new ActiveXObject("Microsoft.XMLHTTP");
	request.onreadystatechange=function()
	{
		if(request.readyState==4)
		{
			stud=JSON.parse(request.responseText);
			studdraw(stud);
		}
	}
	request.open("GET",url,true);
	request.send();
}
 
function studdraw(sj)
{
	studlay.destroyFeatures();
	sjs=stud.std;
	s=[];
 
	for(i=0;i<sjs.length;i++)
	{
		s[i] = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(sjs[i].lon,sjs[i].lat).transform(epsg4326,projectTo),{'description':"<table class=\"hadtbl\">"+sjs[i].name+"</table>"},{'externalGraphic':ICON_studanka,'graphicHeight':24,'graphicWidth':24,'graphicXOffset':-12,'graphicYOffset':-12});
		studlay.addFeatures(s[i]);
	}
}
 
function studdrv()
{
	box=document.getElementById("studchecker");
	if(box.checked)
		getJSONstud();
	else
		studlay.destroyFeatures();
}
 
// Return icon by Regnum
function geticon (a,i)
{
	if(a[i].genus=="negative")
		return ICON_negative;
 
	var p=true;
	var r=""
	if(document.getElementById("reg").value!="ALL")
	{
		r=document.getElementById("reg").value
		p=false;
	}
	else
	{
		r=a[i].regnum
		for(var e=i;e>=0 && a[e].locality==a[i].locality;e--)
		{
			if(a[e].phylum!="Platyhelminthes")
				p=false;
			if(a[e].regnum!=a[i].regnum)
			{
				r="ALL";
				break;
			}
		}
	}
 
 
	switch (r)
	{
		case "Animalia":
		{
			if(p)
				return ICON_plostenkoid;
			return ICON_animalia;
		}
		case "Bacteria":
			return ICON_bacteria;
		case "Fungi":
			return ICON_fungi;
		case "Chromista":
			return ICON_chromista;
		case "Plantae":
			return ICON_plantae;
		case "Protista":
			return ICON_protista;
		default:
			return ICON_biohazard
	}
}
 
function genphy() {
	physel.innerHTML="<option>ALL</option>"
	clasel.innerHTML="<option>ALL</option>"
	ordsel.innerHTML="<option>ALL</option>"
	famsel.innerHTML="<option>ALL</option>"
	gensel.innerHTML="<option>ALL</option>"
	spesel.innerHTML="<option>ALL</option>"
 
	var phyarr=[]
	for (var i=0;i<window.arma.length-1;i++)
	{
		if(regsel.value==window.arma[i].regnum && window.arma[i].phynum!="")
			phyarr.push(window.arma[i].phylum)
	}
	phyarr.sort()
	for (var i=0;i<phyarr.length;i++)
	{
		if(i==0)
		{
			physel.innerHTML+="<option>"+phyarr[0]+"</option>"
			continue
		}
		if(phyarr[i]!=phyarr[i-1])
			physel.innerHTML+="<option>"+phyarr[i]+"</option>"
	}
	armageddon() // Populate the map with monsters...
}
 
function gencla() {
	clasel.innerHTML="<option>ALL</option>"
	ordsel.innerHTML="<option>ALL</option>"
	famsel.innerHTML="<option>ALL</option>"
	gensel.innerHTML="<option>ALL</option>"
	spesel.innerHTML="<option>ALL</option>"
 
	var claarr=[]
	for (var i=0;i<window.arma.length-1;i++)
	{
		if(physel.value==window.arma[i].phylum && window.arma.classis!="")
			claarr.push(window.arma[i].classis)
	}
	claarr.sort()
	for (var i=0;i<claarr.length;i++)
	{
		if(i==0)
		{
			clasel.innerHTML+="<option>"+claarr[0]+"</option>"
			continue
		}
		if(claarr[i]!=claarr[i-1])
			clasel.innerHTML+="<option>"+claarr[i]+"</option>"
	}
	armageddon() // Populate the map with monsters...
}
 
function genord() {
	ordsel.innerHTML="<option>ALL</option>"
	famsel.innerHTML="<option>ALL</option>"
	gensel.innerHTML="<option>ALL</option>"
	spesel.innerHTML="<option>ALL</option>"
	var ordarr=[]
	for (var i=0;i<window.arma.length-1;i++)
	{
		if(clasel.value==window.arma[i].classis && window.arma[i].ordo!="")
			ordarr.push(window.arma[i].ordo)
	}
	ordarr.sort()
	for (var i=0;i<ordarr.length;i++)
	{
		if(i==0)
		{
			ordsel.innerHTML+="<option>"+ordarr[0]+"</option>"
			continue
		}
		if(ordarr[i]!=ordarr[i-1])
			ordsel.innerHTML+="<option>"+ordarr[i]+"</option>"
	}
	armageddon() // Populate the map with monsters...
}
 
function genfam() {
	famsel.innerHTML="<option>ALL</option>"
	gensel.innerHTML="<option>ALL</option>"
	spesel.innerHTML="<option>ALL</option>"
	var famarr=[]
	for (var i=0;i<window.arma.length-1;i++)
	{
		if(ordsel.value==window.arma[i].ordo && window.arma[i].familia!="")
			famarr.push(window.arma[i].familia)
	}
	famarr.sort()
	for (var i=0;i<famarr.length;i++)
	{
		if(i==0)
		{
			famsel.innerHTML+="<option>"+famarr[0]+"</option>"
			continue
		}
		if(famarr[i]!=famarr[i-1])
			famsel.innerHTML+="<option>"+famarr[i]+"</option>"
	}
	armageddon() // Populate the map with monsters...
}
 
function gengen() {
	gensel.innerHTML="<option>ALL</option>"
	spesel.innerHTML="<option>ALL</option>"
	var genarr=[]
	for (var i=0;i<window.arma.length-1;i++)
	{
		if(famsel.value==window.arma[i].familia && window.arma[i].genus!="")
			genarr.push(window.arma[i].genus)
	}
	genarr.sort()
	for (var i=0;i<genarr.length;i++)
	{
		if(i==0)
		{
			gensel.innerHTML+="<option>"+genarr[0]+"</option>"
			continue
		}
		if(genarr[i]!=genarr[i-1])
			gensel.innerHTML+="<option>"+genarr[i]+"</option>"
	}
	//genspe() // ...and here we go
	armageddon() // Populate the map with monsters...
}
 
function genspe()
{
	spesel.innerHTML="<option>ALL</option>"
	var spearr=[]
	for (var i=0;i<window.arma.length-1;i++)
	{
		if(gensel.value==window.arma[i].genus && window.arma[i].specie!="")
			spearr.push(window.arma[i].specie)
	}
	spearr.sort()
	for (var i=0;i<spearr.length;i++)
	{
		if(i==0)
		{
			spesel.innerHTML+="<option>"+spearr[0]+"</option>"
			continue
		}
		if(spearr[i]!=spearr[i-1])
			spesel.innerHTML+="<option>"+spearr[i]+"</option>"
	}
	armageddon() // Populate the map with monsters...
}
 
function armageddon()
{
	console.log("a "+window.arma.length);
	var speval=document.getElementById("spe").value
	var genval=document.getElementById("gen").value
	var famval=document.getElementById("fam").value
	var ordval=document.getElementById("ord").value
	var claval=document.getElementById("cla").value
	var phyval=document.getElementById("phy").value
	var regval=document.getElementById("reg").value
	var a=[]
 
	if(speval!="ALL")
	{
		for(var i=0;i<window.arma.length-1;i++)
			if(window.arma[i].specie==speval && window.arma[i].genus==genval) // Check genus because of unknown "sp."
				a.push(window.arma[i])
	}
	else if(genval!="ALL")
	{
		for(var i=0;i<window.arma.length-1;i++)
			if(window.arma[i].genus==genval)
				a.push(window.arma[i])
	}
	else if(famval!="ALL")
	{
		for(var i=0;i<window.arma.length-1;i++)
			if(window.arma[i].familia==famval)
				a.push(window.arma[i])
	}
	else if(ordval!="ALL")
	{
		for(var i=0;i<window.arma.length-1;i++)
			if(window.arma[i].ordo==ordval)
				a.push(window.arma[i])
	}
	else if(claval!="ALL")
	{
		for(var i=0;i<window.arma.length-1;i++)
			if(window.arma[i].classis==claval)
				a.push(window.arma[i])
	}
	else if(phyval!="ALL")
	{
		for(var i=0;i<window.arma.length-1;i++)
			if(window.arma[i].phylum==phyval)
				a.push(window.arma[i])
	}
	else if(regval!="ALL")
	{
		for(var i=0;i<window.arma.length-1;i++)
			if(window.arma[i].regnum==regval)
				a.push(window.arma[i])
	}
	else // Regnum: ALL
	{
		for(var i=0;i<window.arma.length-1;i++)
			a.push(window.arma[i])
	}
 
	icongeddon(a)
}
 
function buggy()
{
	var p=[]
	for(var i=0;i<window.arma.length-1;i++)
	{
		if(window.arma[i].regnum==""||
	     window.arma[i].phylum==""||
	     window.arma[i].classis==""||
	     window.arma[i].ordo==""||
	     window.arma[i].familia==""||
	     window.arma[i].genus=="")
		  p.push(window.arma[i])
	}
	icongeddon(p)
}
 
function plostenkoidy()
{
	var p=[]
	for(var i=0;i<window.arma.length-1;i++)
	{
		if(window.arma[i].phylum=="Platyhelminthes")
			p.push(window.arma[i])
	}
	icongeddon(p)
}
 
function icongeddon(a)
{
	//alert(a.length) // #thingies to show in the map'
	while(map.popups.length)
		map.removePopup(map.popups[0])
	vectorLayerDynamic.destroyFeatures()
 
	var bylo="" // Minula pozice
	var sam="" // HTML samostatneho zaznamu
	var osam="" // predchozi $sam
	var spoj="" // HTML had z popisu stejnych pozic
	var ospoj="" // Predchozi spoj
	var ox="" // Old X
	var oy="" // Old Y
	var datelog="" // Entries sorted by date for plaintext log
	var i=0 // Iterator over a[] (needed after FOR)
	var n=[] // New points in the layer
	var muchicons=0 // How much Regnum's?
	var samicon=ICON_biohazard // Icon
	var spojicon=ICON_biohazard // Icon
 
	for(;i<a.length;i++) // -1 fix for last empty entry
	{
		if(a[i].cluster!=0&&a[i].mainpic!="y") // show only in gallery, without icon in map
			continue;
 
		// Pokracujem v hadovi
		if(a[i].locality == bylo)
		{
			sam="";
			spoj+="<tr><td>"
			spoj+='<a href="./det/'+a[i].detid+'.htm" target="_blank">'
			if(a[i].obr != "")
				spoj+='<img src="./simg/'+a[i].obr+'" class="hadimg"></a></td>'
			else
				spoj+='<img src=./"'+ICON_biohazard+'" class="hadimg"></a></td>'
			spoj+="<td>"+a[i].title+"<br>"+a[i].takendate+"</td>"
			spoj+="</tr>"
			ox=a[i].x
			oy=a[i].y
			continue;
		}
 
		switch(a[i].specie)
		{
			case "sp.":
			{
				wikisp="https://en.wikipedia.org/wiki/"+a[i].genus
				break;
			}
			case "negative":
			case "":
			{
				wikisp="https://en.wikipedia.org/wiki/Null_result"
				break;
			}
			default:
			{
				wikisp="https://en.wikipedia.org/wiki/"+a[i].genus+" "+a[i].specie
				break;
			}
		}
 
 
		// Bud prvni zaznam, nebo zmena pozice
 
		// Predchozi pozice jen 1 zaznam?
		if(sam != "")
		{
			samicon=geticon(a,i-1)
			n[i] = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(ox,oy).transform(epsg4326,projectTo),{'description':sam},{'externalGraphic':samicon,'graphicHeight':24,'graphicWidth':24,'graphicXOffset':-12,'graphicYOffset':-12});
			vectorLayerDynamic.addFeatures(n[i]);
			spoj=""
			sam=""
		} // ELSE vytvori prazdny radek
		// Predchozi pozice vic zaznamu?
		if(spoj!="")
		{
			spojicon=geticon(a,i-1)
			n[i] = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(ox,oy).transform(epsg4326,projectTo),{'description':"<table class=\"hadtbl\">"+spoj+"</table>"},{'externalGraphic':spojicon,'graphicHeight':24,'graphicWidth':24,'graphicXOffset':-12,'graphicYOffset':-12});
			vectorLayerDynamic.addFeatures(n[i]);
			spoj=""
			sam=""
		}
 
		bylo=a[i].locality
		spoj='<tr><td><a href="./det/'+a[i].detid+'.htm" target="_blank">'
		if(a[i].obr != "")
			spoj+='<img src="./simg/'+a[i].obr+'" class="hadimg"></a></td>'
		else
			spoj+='<img src="./'+geticon(a,i)+'" class="hadimg"</a></td>'
		spoj+='<td>'+a[i].title+'<br>'+a[i].takendate+'</td>'
		spoj+="</tr>"
 
		sam='<a href="./det/'+a[i].detid+'.htm" target="_blank"><img src="'+(a[i].genus=='negative'?ICON_negative:'./simg/'+a[i].obr)+'" alt="'+a[i].title+'" class="buttimg"></a>'
		sam+='<br><span class="butttext">'
		sam+='<a href="'+wikisp+'" target="_blank">'+(a[i].title=="negative"?"Negative observation":a[i].title)+'</a><br>'
		if(a[i].imperium != "")
			sam+='<b>Domain:</b> <a href="https://en.wikipedia.org/wiki/'+a[i].imperium+'" target="_blank">'+a[i].imperium+'</a><br>'
		if(a[i].regnum != "")
    	sam+='<b>Kingdom:</b> <a href="https://en.wikipedia.org/wiki/'+a[i].regnum+'" target="_blank">'+a[i].regnum+'</a><br>'
		if(a[i].phylum != "")
			sam+='<b>Phylum:</b> <a href="https://en.wikipedia.org/wiki/'+a[i].phylum+'" target="_blank">'+a[i].phylum+'</a><br>'
		if(a[i].classis != "")
			sam+='<b>Class:</b> <a href="https://en.wikipedia.org/wiki/'+a[i].classis+'" target="_blank">'+a[i].classis+'</a><br>'
		if(a[i].ordo != "")
			sam+='<b>Order:</b> <a href="https://en.wikipedia.org/wiki/'+a[i].ordo+'" target="_blank">'+a[i].ordo+'</a><br>'
		if(a[i].familia != "")
			sam+='<b>Family:</b> <a href="https://en.wikipedia.org/wiki/'+a[i].familia+'" target="_blank">'+a[i].familia+'</a><br>'
		if(a[i].genus != "" && a[i].genus!="negative")
			sam+='<b>Genus:</b> <a href="https://en.wikipedia.org/wiki/'+a[i].genus+'" target="_blank">'+a[i].genus+'</a><br>'
		if(a[i].specie != "")
			sam+='<b>Species:</b> <a href="'+wikisp+'" target="_blank">'+a[i].specie+'</a><br>'
		if(a[i].biotope != "")
			sam+="<b>Biotope:</b> "+a[i].biotope+"<br>"
		if(a[i].pov != "")
			sam+="<b>River:</b> "+a[i].pov+"<br>"
		if(a[i].temperature != "")
			sam+="<b>Temperature:</b> "+a[i].temperature+" °C<br>"
		if(a[i].pov != "")
			sam+="<b>Conductivity:</b> "+a[i].conductivity+" mSv<br>"
		if(a[i].pov != "")
			sam+="<b>pH:</b> "+a[i].ph+"<br>"
 
 
 
		if(a[i].takendate != "")
			sam+="<b>Date:</b> "+a[i].takendate+"<br>"
		sam+="<b>Location:</b> "+a[i].locality+" ("+a[i].locplain+")<br>"
		if(a[i].observer != "")
 			sam+="<b>Spectator:</b> "+a[i].observer+"<br>"
		if(a[i].micro != "")
			sam+="<b>Microscope:</b> "+a[i].micro+" ("+a[i].microtyp+")<br>"
		if(a[i].enlargement != "")
			sam+="<b>Amplification:</b> "+a[i].enlargement+"<br>"
		/* if [[ "$des" != "" ]]; then
		#   sam="$sam<b>Depictio:</b> $des<br>"
		# fi */
		//if(a[i].videolink != "")
		//	sam+='<b>Video:</b> <a href="'+a[i].videolink+'" target="_blank">'+a[i].videolink+'</a><br>'
		sam+="</span>"
 
		ox=a[i].x
		oy=a[i].y
	} // Konec prochazeni a[]
 
	// Do not forget to print last line when FOR ends!
	samicon=geticon(a,i-1)
	if(sam == "")
		sam='<table style="hadtbl">'+spoj+'</table>'
 
	n[i]=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(a[i-1].x,a[i-1].y).transform(epsg4326,projectTo),{description:"'"+sam+"'"},{externalGraphic:samicon,graphicHeight:24,graphicWidth:24,graphicXOffset:-12,graphicYOffset:-12});
	vectorLayerDynamic.addFeatures(n[i]);
 
} // Konec armageddonu
 
//var laycon = [vectorLayer,vectorLayerPonygon,vectorLayerDynamic,studlay];
var laycon = [vectorLayer,vectorLayerDynamic,studlay];
 
var controls = {selector: new OpenLayers.Control.SelectFeature(laycon, { onSelect: createPopup, onUnselect: destroyPopup })};
map.addControl(controls['selector']);
controls['selector'].activate();
 
function createPopup(feature)
{
	feature.popup = new OpenLayers.Popup.FramedCloud('pop',
		feature.geometry.getBounds().getCenterLonLat(),
		null,
		'<div class="markerContent">'+feature.attributes.description+'</div>',
		null,
		false, // Close button?
		function() { controls['selector'].unselectAll(); }
	);
	//feature.popup.closeOnMove = true;
	map.addPopup(feature.popup);
}
 
function destroyPopup(feature) {
	feature.popup.destroy();
	feature.popup = null;
}
 
 
// Vyhledavani
function limit()
{
	srch=document.getElementById("srch").value.toLowerCase();
	var p=[]
	for(var i=0;i<window.arma.length-1;i++)
	{
		if(window.arma[i].title.toLowerCase().indexOf(srch)>=0||
		   window.arma[i].imperium.toLowerCase().indexOf(srch)>=0||
		   window.arma[i].regnum.toLowerCase().indexOf(srch)>=0||
		   window.arma[i].phylum.toLowerCase().indexOf(srch)>=0||
		   window.arma[i].classis.toLowerCase().indexOf(srch)>=0||
		   window.arma[i].ordo.toLowerCase().indexOf(srch)>=0||
		   window.arma[i].familia.toLowerCase().indexOf(srch)>=0||
		   //window.arma[i].genus.toLowerCase().indexOf(srch)>=0|| // v "qualis"
		   //window.arma[i].observerie.toLowerCase().indexOf(srch)>=0||
		   window.arma[i].locplain.toLowerCase().indexOf(srch)>=0||
		   window.arma[i].description.toLowerCase().indexOf(srch)>=0||
		   window.arma[i].takendate.toLowerCase().indexOf(srch)>=0||
		   window.arma[i].micro.toLowerCase().indexOf(srch)>=0||
		   window.arma[i].microtyp.toLowerCase().indexOf(srch)>=0||
		   window.arma[i].biotope.toLowerCase().indexOf(srch)>=0||
		   window.arma[i].pov.toLowerCase().indexOf(srch)>=0)
		  p.push(arma[i])
	}
	icongeddon(p)
}
 
 
// ====== GEOJSON ======
 
var metageo=JSON.parse("{}");
var geje=[];
var gejbarva="";
 
function placegeo(coor,gejbarva)
{
	var geja=new Array;
	epsg4326 =  new OpenLayers.Projection("EPSG:4326"); //WGS 1984 projection
	projectTo = map.getProjectionObject();
 
	for(i=0;i<coor.length;i++)
	{
		geja.push(new OpenLayers.Geometry.Point(coor[i][0],coor[i][1]).transform(epsg4326, projectTo))
	}
/* "default" namespaces work for Layers, not Features
	var lajna=new OpenLayers.StyleMap({
	    "default": new OpenLayers.Style({
        //strokeColor: "#FF0000",
        strokeColor: gejbarva,
        strokeOpacity: 1,
        strokeWidth: 5,
        pointRadius: 6,
	    }),
	    "select": new OpenLayers.Style({
	      //strokeColor: "#0000FF",
	      strokeColor: gejbarva,
	      strokeOpacity: 1,
	      strokeWidth: 5,
	      pointRadius: 6,
	    })
	}); */
	var lajna={ // Feature without the namespaces
        strokeColor: gejbarva,
        strokeOpacity: 1,
        strokeWidth: 5,
        pointRadius: 6,
	};
 
	gejs=new OpenLayers.Geometry.LineString(geja);
	vectorLayerPonygon.addFeatures([new OpenLayers.Feature.Vector(gejs,{},lajna)]);
}
 
function getsld(url,s,g)
{
	var request;
	if(window.XMLHttpRequest)
		request=new XMLHttpRequest();
	else
		request=new ActiveXObject("Microsoft.XMLHTTP");
	request.overrideMimeType("text/plain");
	request.onreadystatechange=function()
	{
		if(request.readyState==4)
		{
			tmpc=request.responseText;
			tmpc=tmpc.match(/SvgParameter name="stroke">#[0-9a-fA-F]*<\/se:SvgParameter/)[0].match(/#[0-9a-fA-F]*/)[0];
			getgeo(url,g,tmpc);
			//console.log(tmpc);
		}
	}
	request.open("GET",url+s,true);
	request.send();
}
 
 
function getgeo(url,g,c)
{
	var request;
	if(window.XMLHttpRequest)
		request=new XMLHttpRequest();
	else
		request=new ActiveXObject("Microsoft.XMLHTTP");
	request.overrideMimeType("application/geo+json");
	request.onreadystatechange=function()
	{
		if(request.readyState==4)
		{
			tmpg=JSON.parse(request.responseText);
			for(var e=0;e<tmpg.features.length;e++)
			{
				if(typeof tmpg.features[e].properties === 'undefined') // || tmpg.features[e].properties.osm_type!="way")
					continue;
 
				for(var i=0;i<tmpg.features[e].geometry.coordinates.length;i++)
				{
					for(var j=0;j<tmpg.features[e].geometry.coordinates[i].length;j++)
					{
						if(tmpg.features[e].geometry.coordinates[i][j].length<2)
							continue;
						//console.log(tmpg.features[e].properties.osm_type+" "+tmpg.features[e].geometry.coordinates[i][j].length);
						placegeo(tmpg.features[e].geometry.coordinates[i][j],c);
					}
				}
			}
		}
	}
	request.open("GET",url+g,true);
	request.send();
}
 
// ENTRY POINT
// parametr je ./ adresar ve kterem je metadata.json S LOMITKEM NA KONCI
function drawgeojson(url)
{
	var request;
	if(window.XMLHttpRequest)
		request=new XMLHttpRequest();
	else
		request=new ActiveXObject("Microsoft.XMLHTTP");
	request.onreadystatechange=function()
	{
		if(request.readyState==4)
		{
			window.metageo=JSON.parse(request.responseText);
			for(var i=0;i<metageo.layers.length;i++)
			{
				//console.log(metageo.layers[i].geojson);
				getsld(url,metageo.layers[i].sld,metageo.layers[i].geojson)
			}
		}
	}
	request.open("GET",url+"metadata.json",true);
	request.send();
}

Springs

To be able to better plan routes for collecting planarians, the knowledge of locations of springs seems to be important. So BioOSM can show them! Below is a script to get the locations from OSM XMLs obtainable from http://osm.kyblsoft.cz/archiv/.

studanky.sh
#!/bin/bash
# generate BioOSM compatible "springs"
# Usage: studanky.sh osmdump.xml
# 
# Download OSM file to be passed as $1
# wget "http://osm.kyblsoft.cz/archiv/czech_republic-2019-11-03.osm.gz"
# gzip -kd ./czech_republic-2019-11-03.osm.gz
#
# Pozor ^^ sezere spoustu rameti
#
 
osm=$(cat "$1" | sed -e 's/<node/\'$'\a<node/g' -e 's/<\/node>/<\/node\'$'\a/g' -e 's/<way/\'$'\a<way/g' -e 's/<\/way>/<\/way>\'$'\a/g' -e 's/<relation/\'$'\a<relation/g' -e 's/<\/relation>/<\/relation>\'$'\a/g' | tr -d '\n' | tr '\a' '\n' | grep 'v="spring"' | grep 'k="natural"')
 
json='{"version":"'$(date --rfc-3339=seconds)'","std":['
 
while IFS='' read -r spr || [[ -n "$spr" ]]; do
	n=$(echo "$spr" | grep -oPe 'k="name" v="[^"]*"' | sed -e 's/k="name" v="//g' -e 's/"$//g')
	lat=$(echo "$spr" | grep -oPe ' lat="[^"]*"' | sed -e 's/ lat="//g' -e 's/"$//g')
	lon=$(echo "$spr" | grep -oPe ' lon="[^"]*"' | sed -e 's/ lon="//g' -e 's/"$//g')
 
	if [ "$lat" = "" ] || [ "$lon" = "" ]; then
		continue; # <way> a tak
	fi
	if [[ "$n" = "" ]]; then
		n="inkognito"
		>&2 echo -e "\033[34m $lat $lon \033[0m";
	fi
 
	json+="{"
	json+=" \"name\":\"$n\","
	json+=" \"lon\":\"$lon\","
	json+=" \"lat\":\"$lat\""
	json+="},"
 
	>&2 echo -e "\033[32m $n $lat $lon\033[0m"
 
done <<< $(echo "$osm")
 
echo "$json{}]}"

LocalityID

ajdy.sh
#!/bin/bash
 
T=$(mktemp)
unzip -p "$1" tellico.xml | tr -d '\n' | sed -e $'s/<entry id="/\\\n<entry id="/g' -e $'s/<\/entry>/<\/entry>\\\n/g' > "$T"
 
 
hf=$(cat "$T" | grep -Pe '^<entry id="' | grep '<hasflatworms>yep</hasflatworms>')
# nejvyssi dosazene ID
mid=$(cat "$T" | grep -Pe '^<entry id="' | grep -oe ' <localityid>.*</localityid> ' | grep -oPe '[0-9]+' | sort | tail -n 1)
mid=$(($mid+1))
 
 
function ll()
{
	while IFS='' read -r r || [[ -n "$r" ]]; do
		t=$(echo "$r" | grep -oe ' <taken-date>.*</taken-date> ' | sed -E 's/( )*<(\/)?taken-date>( )*//g' | sed -E 's/([0-9]+)\.([0-9]+)\.([0-9]{4})/\3-\2-\1/g' | sed -E 's/-([0-9])-/-0\1-/g' | sed -E 's/-([0-9])$/-0\1/g')
		l=$(echo "$r" | grep -oe '<locality>.*</locality>' | grep -oPe '[0-9]+\.[0-9]+[, ]*[0-9]+\.[0-9]+')
		 echo "$t@$l"
	done <<< $(echo "$1")
}
 
srt=$(ll "$hf" | sort -u)
 
uid=$mid
while IFS='' read -r r || [[ -n "$r" ]]; do
	l=$(echo "$r" | grep -oPe '@.*$' | tr -d '@')
	lid=$(cat "$T" | grep  " <locality>$l</locality> " | grep -oe ' <localityid>.*</localityid> ' | grep -oPe '[0-9]+')
	if [[ "$lid" = "" ]]; then
 
		sedexp="s/( <locality>$l<\/locality> .*<hasflatworms>yep<\/hasflatworms> )/ \\1 <localityid>$uid<\/localityid> /g"
		#echo "$sedexp"
		sed -E "$sedexp" -i "$T"
		uid=$(($uid+1))
	fi
done <<< $(echo "$srt")
 
D=$(mktemp -d)
cp -f "$T" "$D/tellico.xml"
zip -j "./micro_new.tc" "$D/tellico.xml"
 
rm -rfv "$T"
rm -rfv "$D"