diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 9 | ||||
-rw-r--r-- | activity.html | 14 | ||||
-rw-r--r-- | activity.lua | 64 | ||||
-rw-r--r-- | generate.lua | 8 | ||||
-rw-r--r-- | spec/activity_spec.lua | 43 |
6 files changed, 125 insertions, 14 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2d19fc7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.html diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..35267f8 --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +all: activity.html + +%.html: generate.lua activity.lua + lua generate.lua >$@ + +clean: + rm -f *.html + +.PHONY: all clean diff --git a/activity.html b/activity.html deleted file mode 100644 index 618a3bb..0000000 --- a/activity.html +++ /dev/null @@ -1,14 +0,0 @@ -<!doctype html> -<html lang="en"> -<meta charset="utf-8"> -<link rel="stylesheet" type="text/css" href="style.css"> -<title>Activity</title> -<table class="activity-chart"> -<tr><td class="activity-chart-label"><td><td data-activity-level="1"><td data-activity-level="1"><td data-activity-level="2"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"> -<tr><td class="activity-chart-label"><span>Mon</span><td><td data-activity-level="0"><td data-activity-level="3"><td data-activity-level="1"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="1"><td data-activity-level="4"><td data-activity-level="4"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"> -<tr><td class="activity-chart-label"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="3"><td data-activity-level="0"><td data-activity-level="1"><td data-activity-level="0"><td data-activity-level="2"><td data-activity-level="1"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"> -<tr><td class="activity-chart-label"><span>Wed</span><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="4"><td data-activity-level="1"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td> -<tr><td class="activity-chart-label"><td data-activity-level="1"><td data-activity-level="2"><td data-activity-level="2"><td data-activity-level="2"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="3"><td data-activity-level="0"><td data-activity-level="2"><td data-activity-level="1"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td> -<tr><td class="activity-chart-label"><span>Fri</span><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="1"><td data-activity-level="2"><td data-activity-level="1"><td data-activity-level="3"><td data-activity-level="0"><td data-activity-level="4"><td data-activity-level="2"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td> -<tr><td class="activity-chart-label"><td data-activity-level="2"><td data-activity-level="1"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td data-activity-level="0"><td> -</table> diff --git a/activity.lua b/activity.lua new file mode 100644 index 0000000..1be6e93 --- /dev/null +++ b/activity.lua @@ -0,0 +1,64 @@ +local activity = {} + + +function activity.days (year) + if year % 4 ~= 0 or year % 100 == 0 and year % 400 ~= 0 then + return 365 + end + return 366 +end + + +function activity.this_year () + return os.date"%Y" +end + + +function activity.first_week_day (year) + year = year or activity.this_year() + return os.date("*t", os.time{year=year, month=1, day=1}).wday +end + + +function activity.generate_table (year) + year = year or activity.this_year() + + local function spot () + return [[<td>]] + end + + local function day (level) + return ([[<td data-activity-level="%d">]]):format(level) + end + + local function cell (exists) + if not exists then + return spot + end + return day + end + + local function row (weekday, first, last) + first = cell(first) + last = cell(last) + local row = ([[<tr><td class="activity-chart-label"><span>%s</span>]]):format(weekday) + row = row .. first(math.random(0, 4)) + for _=1,51 do + row = row .. day(math.random(0, 4)) + end + row = row .. last(math.random(0, 4)) .. "\n" + return row + end + + local rows = "" + local weekdays = {"", "Mon", "", "Wed", "", "Fri", ""} + local start_from = activity.first_week_day(year) + local end_at = (start_from + activity.days(year) - 1) % 7 + for index, weekday in pairs(weekdays) do + rows = rows .. row(weekday, index >= start_from, index <= end_at) + end + return [[<table class="activity-chart">]] .. "\n" .. rows .. "</table>" +end + + +return activity diff --git a/generate.lua b/generate.lua new file mode 100644 index 0000000..2c78d61 --- /dev/null +++ b/generate.lua @@ -0,0 +1,8 @@ +local activity = require "activity" +local year = ... +print([[<!doctype html>]]) +print([[<html lang="en">]]) +print([[<meta charset="utf-8">]]) +print([[<link rel="stylesheet" type="text/css" href="style.css">]]) +print([[<title>Activity</title>]]) +print(activity.generate_table(year)) diff --git a/spec/activity_spec.lua b/spec/activity_spec.lua new file mode 100644 index 0000000..08160fa --- /dev/null +++ b/spec/activity_spec.lua @@ -0,0 +1,43 @@ +local activity = require "activity" + +describe("Days in a year", function() + it("should support regular years", function() + assert.are.equal(365, activity.days(1970)) + assert.are.equal(365, activity.days(2001)) + end) + + it("should support lean years", function() + assert.are.equal(366, activity.days(2004)) + assert.are.equal(366, activity.days(1980)) + end) + + it("should support *00 years", function() + assert.are.equal(366, activity.days(2000)) + assert.are.equal(365, activity.days(2100)) + assert.are.equal(365, activity.days(2200)) + assert.are.equal(365, activity.days(2300)) + assert.are.equal(366, activity.days(2400)) + end) +end) + +describe("This year is", function() + local this_year = os.date "%Y" -- Quite useless test + + it(tostring(this_year), function() + assert.are.equal(this_year, activity.this_year()) + end) +end) + +describe("First week day of", function() + it("2023 is Sunday", function() + assert.are.equal(1, activity.first_week_day(2023)) + end) + + it("2022 is Saturday", function() + assert.are.equal(7, activity.first_week_day(2022)) + end) + + it("2020 is Saturday", function() + assert.are.equal(4, activity.first_week_day(2020)) + end) +end) |