From 737a428f5259ed410ebc39f567c65c9107d09a00 Mon Sep 17 00:00:00 2001 From: Roman Godmaire Date: Tue, 14 May 2024 21:39:21 -0400 Subject: [PATCH] Initial commit --- .envrc | 3 + .gitignore | 9 +++ devenv.lock | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++ devenv.nix | 7 +++ devenv.yaml | 15 +++++ go.mod | 3 + index.go | 51 +++++++++++++++++ main.go | 15 +++++ stormlight.go | 124 +++++++++++++++++++++++++++++++++++++++ 9 files changed, 383 insertions(+) create mode 100644 .envrc create mode 100644 .gitignore create mode 100644 devenv.lock create mode 100644 devenv.nix create mode 100644 devenv.yaml create mode 100644 go.mod create mode 100644 index.go create mode 100644 main.go create mode 100644 stormlight.go diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..5bf8fc1 --- /dev/null +++ b/.envrc @@ -0,0 +1,3 @@ +source_url "https://raw.githubusercontent.com/cachix/devenv/95f329d49a8a5289d31e0982652f7058a189bfca/direnvrc" "sha256-d+8cBpDfDBj41inrADaJt+bDWhOktwslgoP5YiGJ1v0=" + +use devenv \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4d058db --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +# Devenv +.devenv* +devenv.local.nix + +# direnv +.direnv + +# pre-commit +.pre-commit-config.yaml diff --git a/devenv.lock b/devenv.lock new file mode 100644 index 0000000..066a1ba --- /dev/null +++ b/devenv.lock @@ -0,0 +1,156 @@ +{ + "nodes": { + "devenv": { + "locked": { + "dir": "src/modules", + "lastModified": 1715593316, + "owner": "cachix", + "repo": "devenv", + "rev": "725c90407ef53cc2a1b53701c6d2d0745cf2484f", + "treeHash": "7ac06cbb236d43b776abbb0a7b8c48c9175d6012", + "type": "github" + }, + "original": { + "dir": "src/modules", + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "treeHash": "2addb7b71a20a25ea74feeaf5c2f6a6b30898ecb", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1710146030, + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "treeHash": "bd263f021e345cb4a39d80c126ab650bebc3c10c", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "treeHash": "ca14199cabdfe1a06a7b1654c76ed49100a689f9", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1713361204, + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6", + "treeHash": "50354b35a3e0277d4a83a0a88fa0b0866b5f392f", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1715542476, + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "44072e24566c5bcc0b7aa9178a0104f4cfffab19", + "treeHash": "3f9021e4c33de6fe59b88ac8c3019fc49136dc2a", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "gitignore": "gitignore", + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1715609711, + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "c182c876690380f8d3b9557c4609472ebfa1b141", + "treeHash": "8ca3c0abe85c95ba7e8eef91a8c6a34f6dde5299", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "devenv": "devenv", + "nixpkgs": "nixpkgs", + "pre-commit-hooks": "pre-commit-hooks" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "treeHash": "cce81f2a0f0743b2eb61bc2eb6c7adbe2f2c6beb", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/devenv.nix b/devenv.nix new file mode 100644 index 0000000..e61dd5c --- /dev/null +++ b/devenv.nix @@ -0,0 +1,7 @@ +{ pkgs, ... }: + +{ + packages = with pkgs; [ git go gopls delve ]; + + scripts.start.exec = "go run main.go"; +} diff --git a/devenv.yaml b/devenv.yaml new file mode 100644 index 0000000..116a2ad --- /dev/null +++ b/devenv.yaml @@ -0,0 +1,15 @@ +# yaml-language-server: $schema=https://devenv.sh/devenv.schema.json +inputs: + nixpkgs: + url: github:cachix/devenv-nixpkgs/rolling + +# If you're using non-OSS software, you can set allowUnfree to true. +# allowUnfree: true + +# If you're willing to use a package that's vulnerable +# permittedInsecurePackages: +# - "openssl-1.1.1w" + +# If you have more than one devenv you can merge them +#imports: +# - ./backend diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..10b76e0 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module stormlight-tracker + +go 1.22.2 diff --git a/index.go b/index.go new file mode 100644 index 0000000..718ffcc --- /dev/null +++ b/index.go @@ -0,0 +1,51 @@ +package main + +import ( + "html/template" + "net/http" + "time" +) + +type IndexPage struct { + BookTitle string + Timestamp string +} + +func index(w http.ResponseWriter, r *http.Request) { + page := template.Must(template.New("index").Parse(indexPage)) + + deadline := time.Date(2024, 12, 1, 0, 0, 0, 0, time.UTC) + timeRemaining := deadline.Sub(time.Now().Round(24 * time.Hour)) + + book, timestamp := getBookWithTimestamp(timeRemaining) + + data := IndexPage{ + BookTitle: book, + Timestamp: timestamp.String(), + } + + page.Execute(w, data) +} + +const indexPage string = ` + + + + + Stormlight Archive Tracker + + + + + +

Stormlight Archive Tracker

+

+ You should be reading {{.BookTitle}} and past the {{.Timestamp}} mark by the end of the day. +

+ +` diff --git a/main.go b/main.go new file mode 100644 index 0000000..0d4ed47 --- /dev/null +++ b/main.go @@ -0,0 +1,15 @@ +package main + +import ( + "log/slog" + "net/http" +) + +func main() { + router := http.NewServeMux() + + router.HandleFunc("GET /", index) + + slog.Info("Listening on port 8080") + http.ListenAndServe(":8080", router) +} diff --git a/stormlight.go b/stormlight.go new file mode 100644 index 0000000..7c3ff6f --- /dev/null +++ b/stormlight.go @@ -0,0 +1,124 @@ +package main + +import ( + "log/slog" + "slices" + "time" +) + +type Book struct { + Name string + Length time.Duration +} + +var stormlight []Book = []Book{ + { + Name: "The Way of Kings Part 1", + Length: 26966 * time.Second, + }, + { + Name: "The Way of Kings Part 2", + Length: 25887 * time.Second, + }, + { + Name: "The Way of Kings Part 3", + Length: 27645 * time.Second, + }, + { + Name: "The Way of Kings Part 4", + Length: 26077 * time.Second, + }, + { + Name: "The Way of Kings Part 5", + Length: 27181 * time.Second, + }, + { + Name: "Words of Radiance Part 1", + Length: 27556 * time.Second, + }, + { + Name: "Words of Radiance Part 2", + Length: 27416 * time.Second, + }, + { + Name: "Words of Radiance Part 3", + Length: 26568 * time.Second, + }, + { + Name: "Words of Radiance Part 4", + Length: 26130 * time.Second, + }, + { + Name: "Words of Radiance Part 5", + Length: 27726 * time.Second, + }, + { + Name: "Oathbringer Part 1", + Length: 24407 * time.Second, + }, + { + Name: "Oathbringer Part 2", + Length: 24467 * time.Second, + }, + { + Name: "Oathbringer Part 3", + Length: 24482 * time.Second, + }, + { + Name: "Oathbringer Part 4", + Length: 22930 * time.Second, + }, + { + Name: "Oathbringer Part 5", + Length: 24122 * time.Second, + }, + { + Name: "Oathbringer Part 6", + Length: 25034 * time.Second, + }, + { + Name: "Rhythm of War Part 1", + Length: 25655 * time.Second, + }, + { + Name: "Rhythm of War Part 2", + Length: 24470 * time.Second, + }, + { + Name: "Rhythm of War Part 3", + Length: 23996 * time.Second, + }, + { + Name: "Rhythm of War Part 4", + Length: 27610 * time.Second, + }, + { + Name: "Rhythm of War Part 5", + Length: 28758 * time.Second, + }, + { + Name: "Rhythm of War Part 6", + Length: 29142 * time.Second, + }, +} + +func getBookWithTimestamp(timeRemaining time.Duration) (string, time.Duration) { + timeRemaining = time.Duration(timeRemaining.Hours()/24) * time.Hour + slices.Reverse(stormlight) + + for _, book := range stormlight { + slog.Info("Checking...", "name", book.Name, "length", book.Length, "timeRemaining", timeRemaining) + + if timeRemaining < book.Length { + return book.Name, book.Length - timeRemaining + } + + timeRemaining = timeRemaining - book.Length + } + + if timeRemaining > 0 { + return "The Way of Kings Part 1", 0 + } + + return "YOU SHOULD BE DONE", 0 +}