
| Current Path : /bin/ |
Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 |
| Current File : //bin/diadia |
#!/usr/bin/env texlua
--
-- diadia [options]
--
-- loads and processes a diadia data file
--
-- License: LPPL
--
local version = "v1.0 (2015/05/15)"
local infile = ""
local outfile = ""
local mode = "*"
local startdate = ""
local enddate = ""
local columns = ""
local data = {}
function pversion()
print("diadia.lua " .. version)
print("(C) Josef Kleber 2015 License: LPPL")
os.exit(0)
end
function phelp()
print([[
diadia.lua [options]
allows you to
- cut a chunk out of the data file
e.g.: -i in.dat -o out.dat -s YYYY-MM-DD -e YYYY-MM-DD
- compose a new data file based on given columns of an
existing data file
e.g.: -i in.dat -o out.dat -c 1,2
- create a new data file with date and value (1st and
2nd column of existing file) and added value average
columns of the last 7, 14, 30, 60 and 90 days
e.g.: -i in.dat -o out.dat [-s YYYY-MM-DD -e YYYY-MM-DD]
Options:
-m specify the mode (cut|compose|average)
-i specify the input file
-o specify the output file
-c specify the columns for compose mode
-s specify the start date (YYYY-MM-DD) in
cut and average mode
-e specify the end date
-v prints version information
-h prints help information
]])
pversion()
end
function check_date(date)
if string.find(date, "(%d%d%d%d)-(%d%d)-(%d%d)") == nil
then
io.stderr:write ("Error 21: wrong date format (YYYY-MM-DD)\n")
os.exit(11)
end
end
function parse_date(date)
return string.match(date, "(%d%d%d%d)%-(%d%d)%-(%d%d)")
end
function parse_dateinline(line)
return string.match(line, "(%d%d%d%d%-%d%d%-%d%d)")
end
function daystring(unixtime)
return os.date("%Y-%m-%d", unixtime)
end
function unixtime(year,month,day)
return os.time{year=year, month=month, day=day}
end
function round(number)
return math.floor(number+0.5)
end
function ptd(value)
local val = tostring(value)
local slen = string.len(val)
if slen == 3
then
return val
else
return val .. " "
end
end
function calc_avg(data,date,days)
local sum = 0
local wdays = 0
local wday
local endday = unixtime(parse_date(date))
local startday = endday - 60*60*24*(days-1)
while startday <= endday
do
wday = daystring(startday)
if data[wday] ~= nil
then
sum = sum + data[wday]
wdays = wdays + 1
end
startday = startday + 60*60*24
end
if wdays == 0
then
return "nan"
else
return tostring(round(sum/wdays))
end
end
function read_data(file)
local data = {}
local date
local startdate
local enddate
local dat
local firstline = true
for line in io.lines(file)
do
if string.match(line, "date")
then
else
date, dat = string.match(line, "(%d%d%d%d%-%d%d%-%d%d)%s+(%S+)")
if firstline == true
then
startdate = date
firstline = false
end
if dat ~= "nan" and dat ~= "{}" and dat ~= ""
then
data[date] = dat
end
end
end
enddate = date
return data,startdate,enddate
end
function write_avg_file(data,file,startdate,enddate)
local sdate
local edate
local wday
sdate = unixtime(parse_date(startdate))
edate = unixtime(parse_date(enddate))
outfile = assert(io.open(file, "w"))
outfile:write("date value avg07 avg14 avg30 avg60 avg90")
while sdate <= edate+7200
do
wday = daystring(sdate)
if data[wday] ~= nil
then
outfile:write("\n" .. wday .. " "
.. ptd(data[wday]) .. " "
.. ptd(calc_avg(data,wday,7)) .. " "
.. ptd(calc_avg(data,wday,14)) .. " "
.. ptd(calc_avg(data,wday,30)) .. " "
.. ptd(calc_avg(data,wday,60)) .. " "
.. ptd(calc_avg(data,wday,90)))
end
sdate = sdate + 60*60*24
end
outfile:close()
end
do
local newarg = {}
local i, limit = 1, #arg
while (i <= limit) do
if arg[i] == "-i" then
infile = arg[i+1]
i = i + 1
elseif arg[i] == "-o" then
outfile = arg[i+1]
i = i + 1
elseif arg[i] == "-s" then
startdate = arg[i+1]
i = i + 1
elseif arg[i] == "-e" then
enddate = arg[i+1]
i = i + 1
elseif arg[i] == "-c" then
columns = arg[i+1]
i = i + 1
elseif arg[i] == "-m" then
mode = arg[i+1]
i = i + 1
elseif arg[i] == "-v" then
pversion()
elseif arg[i] == "-h" then
phelp()
else
newarg[#newarg+1] = arg[i]
end
i = i + 1
end
arg = newarg
end
if mode == "average"
then
local startd
local endd
print("set mode to " .. mode)
print("reading data file " .. infile)
data,startd,endd = read_data(infile)
if startdate ~= ""
then
startd = startdate
end
if enddate ~= ""
then
endd = enddate
end
print("writing data file " .. outfile)
write_avg_file(data,outfile,startd,endd)
os.exit(0)
end
if mode == "compose"
then
local row = 0
local column = 0
local ofile
local cols
print("set mode to " .. mode)
print("reading data file " .. infile)
for line in io.lines(infile)
do
row = row + 1
data[row] = {}
column = 0
for value in string.gmatch(line, "%S+")
do
column = column + 1
data[row][column] = value
end
end
cols = assert(load("return table.concat({"..columns:gsub("%d+","(...)[%0]").."},' ')"))
ofile = assert(io.open(outfile, "w"))
print("writing data file " .. outfile)
for irow = 1,row
do
if irow == row
then
ofile:write(cols(data[irow]))
else
ofile:write(cols(data[irow]).."\n")
end
end
ofile:close()
os.exit(0)
end
if mode == "cut"
then
local ofile
local date
local sdate
local edate
local cdate
check_date(startdate)
check_date(enddate)
sdate = unixtime(parse_date(startdate))
edate = unixtime(parse_date(enddate))
print("set mode to " .. mode)
print("reading data file " .. infile)
print("writing data file " .. outfile)
ofile = assert(io.open(outfile, "w"))
for line in io.lines(infile)
do
if string.match(line, "date")
then
ofile:write(line)
else
date = parse_dateinline(line)
cdate = unixtime(parse_date(date))
if cdate >= sdate and cdate <= edate
then
ofile:write("\n" .. line)
end
end
end
ofile:close()
os.exit(0)
end
if mode == "*"
then
io.stderr:write ("Error 11: no mode specified!")
os.exit(11)
else
io.stderr:write ("Error 12: invalid mode " .. mode)
os.exit(12)
end