Modul:Benutzer:Kpfiwa/Coltab
Eine Beschreibung der Funktionen findet man vorerst nur im Quelltext Modul:Benutzer:Gadacz/Coltab
--[[ Coltab Version 2a BETA, 2020-05-17
müsste noch gründlich "geputzt" und optimiert werden. Wegen eines
laufenden Löschantrags wird die Entwicklung der deutschen Version abgebrochen!
Ggf. werden irgendwann die Ergänzungen der anderssprachigen Versionen übernommen.
--]]
--[[ siehe https://github.com/telegnom/esp_tools/blob/master/hsv2rgb.lua func hsv2rgb
* Konvertiert einen HSV-Farbwert in RGB. Umrechnungsformel angepasst von https://de.wikipedia.org/wiki/HSV-Farbraum
* Angenommen, h, s und v sind in der Menge [0, 1] und enthalten
* gibt r, g und b [jeweils 0, 255] hexadezimal zurück
* @param Nummer Farbwert h 0 - 359° (hue)
* @param Nummer Sättigung s 0-100 % (saturation)
* @param Nummer Helligkeit v oder l (luminance) 0-100 %
* @return Array: RGB-Darstellung hexadezimal, optional Hintergrund, wenn zu dunkel für Schrift
* Assumes h, s, and v are contained in the set [0, 1] and
* returns r, g, and b in the set [0, 255].
-- ]]
local p = {} -- Übergabearray
local r2g = 120 -- das entspricht rot (0) zu grün (120) siehe [[HSV-Farbraum]]
local b2r = 360-- das entspricht blau (240) zu rot (360)
local tblmax = r2g -- Vorgabe hsv-Höchstwert
local gb = 'G' -- Grünskala oder 'b'lau -> rot
local function tu(a,z) -- wandelt in Versalien und extrahiert erstes Zeichen oder Zeichenanzahl z
return string.sub(string.upper(a), 1, z or 1)
end
--[=[ function tonum separiert einen Zahlenanteil aus einem String wie
'ca. 55,4 °C', 'Temperatur 44.9', '123,7', '≈99%' usw.
Punkt und Komma werden generell als (Dezimal-)Punkt ausgewertet;
beliebige Tausendertrenner erlaubt, der Letzte (Komma oder Punkt) ist der Dezimaltrenner
gibt es nur Tausendertrenner, muß hinten ein Punkt oder komma stehen
Negative Werte werden vorzeichenlos übergeben
Rückgabe: Der Zahlenwert (erg) und er Eingabestring (ein)
--]=]
local function tonum(ein)
local erg, stat = '',0
erg, stat = string.gsub(ein, "(%D*)([%s%-%d,%.%']+)(%D*)", "%1|%2|%3")
if stat > 0 then
nix, erg ,nix = string.match(erg, "(.*)|(.*)|(.*)")
erg=string.gsub(string.reverse(erg), "[%.,]+", "QIX",1)
erg=string.gsub(erg, "[%.,%s%']+", "")
erg=string.reverse(string.gsub(erg, "QIX", "."))*1
end -- if stat
return erg, ein
end
function tu(a,z) -- wandelt in Versalien und extrahiert erstes Zeichen oder Anzahl z
return string.sub(string.upper(a), 1, z or 1)
end
local function emph(was) -- Emphasis, Schriftauszeichnung für den Text gem. Vorlagen-Parameter 'd= ...' (Dekoration)
local css = ''
-- if not was or #was < 1 then return 'NIX' end -- undekorierte Rückgabe
if #was <= 6 then -- was größer ist, wird eine direkt eingegebene css-Anweisung sein
was = tu(was,6)
for e in string.gmatch(was, ".") do -- teilen falls mehrere Parameter
if e == 'F' or e == 'B' then css = css .. " font-weight:bold;"
elseif e == 'K' or e == 'I' then css = css .. " font-style:italic;"
elseif e == 'U' then css = css .. " text-decoration:underline;"
elseif e == 'V' then css = css .. " text-transform:uppercase;"
elseif e == 'C' then css = css .. " font-variant:small-caps;"
elseif e == 'G' then css = css .. " letter-spacing:0.3em;"
end -- if e
end -- for e
else -- if #was
was = string.gsub(was,"['%\"]+",'') -- evtl. Anführungszeichen rasieren
css = string.gsub(was,"[%w]+%s*=%s*",'') -- falls versehentlich mit 'string=' eingeleitet wurde
end -- if #was
return css
end
--[[ function hsv2rgb
übernimmt hsv Werte und wandelt sie in rgb (hex) um.
Sofern der Hintergrund zu dunkel ist:
Schrift weiß ('color:#ffffff;') als 2. Rückgabewert
--]]
local function hsv2rgb(h,s,v)
h = tonumber(h)
-- Lokale
local k, c = 'color:#ffffff;', '' -- Schrift weiß, falls Hintergrund zu dunkel
local wert = h -- vorerst nur Kontrolle
local iR, iG, iB, r, g, b, diff
-- Position im Farbkreis (hue)
if h < 61 then r = 255; g = (425 * h) / 100; b = 0
elseif h >= 61 and h < 121 then r = 255 - ((425 * (h - 60)) / 100); g = 255; b = 0
elseif h >= 121 and h < 181 then r = 0; g = 255; b = (425 * (h-120)) / 100
elseif h >= 181 and h < 241 then r = 0; g = 255 - ((425 * (h-180))/100); b = 255
elseif h >= 241 and h < 301 then r = (425 * (h-240))/100; g = 0; b = 255
elseif h >= 301 and h < 360 then r = 255; g = 0; b = 255 - ((425 * (h-300))/100)
end
-- Farbsättigung
s = 100 - s; diff = ((255 - r) * s) / 100
r = r + diff; diff = ((255 - g) * s) / 100
g = g + diff; diff = ((255 - b) * s) / 100
b = b + diff
-- Helligkeit
r = (r * v) / 100; g = (g * v) / 100; b = (b * v) / 100
-- Rückgabewerte runden
iR= math.floor(r); iG= math.floor(g); iB= math.floor(b)
-- Schriftfarbe festlegen bei dunklem Hintergrund
if iG <=120 then c = k end
-- Ausgabe
--return string.format('#%02x%02x%02x', iR, iG, iB), c, string.format('rgb(%d,%d,%d)',iR, iG, iB)
return string.format('#%02x%02x%02x', iR, iG, iB), c --, string.format('rgb(%d,%d,%d)',iR, iG, iB)
end
--[[ function val2hsv
Setzt eine Zahl (val) <= max in einen größenabhängigen Farbwert um.
Hier wird nur der Farbraum von grün nach rot (vv) verarbeitet
Parameter max ist der Höchstwert des darzustellenden Werteraums. Der mUss in Relation stehen
zum vorhandenen Werteraum, also 0 (rot) bis 120 (grün). Daraus ergibt sich ein Teiler (d) für den Wert
bei max = 50; Teiler 120/max (120/50) = skal (3)
bei max = 700; Teiler 120/max (tblmax) = skal (0.171428571)
Ist der Farbwert > max, wird eine Fehlermeldung ausgegeben
HIER muss drastisch eingegriffen werden, um die Logik einem Minimalwert anzupassen
evtl. auch alternatibe Farbskala bearbeiten rot->>blau für Temperaturen
--]]
local function val2hsvOLD(val, max, min)
local r1,r2, erg, revert, tmpmax, diff
val = tonumber(val)
max, r1 = string.gsub(max,'#', ""); max = tonumber(max)
min, r2 = string.gsub(min,'#', ""); min = tonumber(min)
if max < min then -- Werte austauschen, da falsche Reihenfolge
tmpmax = max; max = min; min = tmpmax
end
diff= math.abs(max - min) -- 'Länge' der Skala
revert = r1 + r2
if val then
--- local tblmax = 120 -- das entspricht grün
-- Ist max negativ, ergibt das einen Farbverlauf von grün nach rot
-- DAS MUSS anders geregelt werden, via # revert
if val > math.abs(max) then return nil end -- Error größer als Tabelle
erg = val * tblmax / max
-- hier ggf auf '#' abfragen statt Negativwert
--if max < 0 then erg = tblmax + erg end -- wird ersetzt durch ... revert
if revert > 0 then erg = tblmax + erg end
end
return erg
end
local function val2hsv(val, max, min, gb)
local r1, r2, erg, diff, err
local revert, ergb = 0,0
if val then
max, r1 = string.gsub(max,'#', "") -- falls '#' enthalten wird Farbskala umgekehrt
min, r2 = string.gsub(min,'#', "")
val = tonumber(val) -- vorsorglich
max = tonumber(max); min = tonumber(min)
if (max < min) then -- wurden versehentlich max/min vertauschr, korrigieren
tmpmax = max
max = min
min = tmpmax
end -- if max<min
diff = math.abs(max - min) -- 'Länge' der Skala
revert = r1 + r2 -- falls '#' auftauchte, > 0
-- nur sinnvol, wenn bei 'b' die Skala gedreht werden muss, sonst ausschaten
if gb == 'B' then
ergb = b2r
if revert == 0 then revert = 1
else revert = 0
end -- if revert
end -- if gb==b
if val then erg = val * tblmax / diff else val = max + 1 end
if (val > max) or (val < min) then -- Error: Wert außerhalb Skala
err = 'Wert außerhalb der Skala'
erg = nil
else
erg = math.abs(math.floor(erg+0.5))
end -- end if val>max
if revert > 0 then
if erg then erg = tblmax - erg end
end -- if revert
if erg then erg = erg + ergb end -- falls 'b', hat ergb +240
-- erg = erg + ergb
else
erg = nil
err = 'kein berechenbarer Wert'
end -- if val
return erg, err
end
--[=[function p.f(frame)
* Übernahme der Werte und Parameter aus Artikel via Vorlage:Coltab als Array
* Auswertung
* * Berechnung des Farbwertes via val2hsv und hsv2rgb
* * Zusammensetzung des Feldinhalts in der Tabelle incl. Formatier- und Färbungsanweisengen.
* Rückgabe des Ergebnisses ala Attay (Lua-Table)
!! Anmerkung: Die Bezeichner für die Parameter werden auf den ersten Buchstaben reduziert.
Klein-Großschreibung ist bedeutungslos, Bezeichner ist beliebig wählbar,
sofern der 1. Buchstabe eindeutig ist
Parameter:
@param 1 oder named-key = 'V'alie oder 'W'ert
Zahlenwert. Er kann Zusätze wie Bezeichner °C $ § ≈ ≠ ± ≤ ≥ ² ³ ½ ⚭ # ‰ € ¢ £ ¥ km³ usw. enthalten,
also jeder beliebige Wert, der durchgereicht und angezeigt, aber nie ausgewertet wird.
Nur der numerische Wert ist für die Färbung entscheidend
@param 2 oder 'M'ax
Der Höchstwert der Skala. Alle Werte müssen niedriger sein,
sonst stimmt der Farbverlauf nicht mehr bzw. Fehlermeldung
Ist m negativ, geht die Farbskala von grün nach rot, sonst rot -> grün
@param 'E'rgänzungen (beliebig), wie z.B. <ref ..., Links, Illustrationen
@param 'S'ortierwert, wenn er vom Wert 1 (V,W) abweicht (generiert data-sort-value)
@param 'O'rientierung sofern von der allg. Vorgabe der Tabelle abweichend
O=L -> linksbündig
O=R -> rechtsbündig
O=Z oder O=C -> zentriert
O=D Ausrichtung auf Dezimalkomma/-Punkt (ggf. Anzahl Nachkommastellen)
@param 'A'ttribut: Ergänzung zur Farbangabe außerhalb 'style=', wie
colspan, rowspan, class.
data-sort-value wird via 'S', class="hintergrundfarbe .. bringt keinen Sinn
@param 'K'ontrast, <100 wird blasser
--]=]
function p.f(frame)
local numval, maximum, kontrast, hell , minimum = 0, 10, 25, 100, 0
local stringval, orient, anhang, sort, erg , class, css, style = '', '', '', '', '', '','', ''
local ft
frame = frame:getParent() -- erst mal die übergebenen Parameter aufrufen
for key, val in pairs(frame.args) do
key = tu(key) -- hier Parameter auf einen Großbuchstaben verkürzen
if key == "1" or key == 'V' or key == 'W' then numval, stringval = tonum(val) -- tonumber, aber Zeichen, wie ~#€$§ ... abfangen. ggf Kleinberechnung
elseif key == "2" or key == 'M' then maximum = val --[[ höchster Wert der Skala
MUSS GEÄNDERT WERDEN, wenn M < 0 erreichen könnte (Negativskala)
ggf. extra Parameter oder Wert z.B 100- bzw. -100-
oder '#' als Kennzeichen (-100#)? Könnte dann auch bei 'N' stehen. --]]
elseif key == "3" or key == 'N' then minimum = val --[[ niedrigster Wert der Skala
der könnte deutlich über 0 liegen für Skalen die sinnvoll weit oben beginnen
wir z.B. hPa (Mittel 1013,25 hPa), ggf Extremwerte 880 - 1100
oder Temperaturskala -50°C bis +50 °C --]]
elseif key == 'E' then anhang = val -- evtl SPACE falls nicht ref
elseif key == 'A' then class = val .. ' ' -- auch rowspan, colspan, ... alles was vor pipe steht
elseif key == 'O' then val = tu(val)
if val == 'L' then orient = 'text-align:left; ' end
if val == 'R' then orient = 'text-align:right;' end
if val == 'C' or val == 'Z' then orient = 'text-align:center; ' end
elseif key == 'S' then
if val == '#' then val = numval end -- nur der Zahlenwert wird sortiert
sort = ' data-sort-value="' .. val .. '" '
elseif key == 'K' then if tonumber(val) ~= kontrast then kontrast = val end
elseif key == 'D' then css = css .. emph(val)
elseif key == 'B' then gb=tu(val) -- 'B' ergibt Rot-blau-Skala
elseif key == 'T' then stringval = val -- Anzeigetext, aber numerische Farbbestimmung bleibt
elseif key == 'I' then val = tu(val) -- inline
if val == 'D' then ft = 'div' else ft = 'span' end
end -- if key ...
end -- for key, val in ..
-- Aufruf der Berechnungen val2hsv hsv2rgb
numval, err = val2hsv(numval, maximum, minimum, gb) -- Farbwert in Relation zur Skala ermitteln
if numval then
hexval, schriftfarbe = hsv2rgb(numval,kontrast,hell) -- Farbwert hsv zu rgb umrechnen
-- jetzt Ausgabetring zusammenbasteln
if ft then -- für Fließtext (param T)
erg = '<' .. ft .. ' style="background:' .. hexval .. '; ' .. schriftfarbe .. css .. '">' .. stringval .. anhang ..'</' .. ft .. '>'
else -- für Tabellenfelder
erg = 'style="background:' .. hexval .. '; ' .. schriftfarbe .. css .. orient .. '" ' .. sort .. class .. '|' .. stringval .. anhang
end
else erg = err -- Fehlermeldung fehlt noch class=error
end
return erg
end
return p