made to suck less, including:
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
* `make` works again, exporting correct database file path for local dev * better formatting of durations * refactored duration math to misc functions * now tracks and displays score * displays short-lifetime fp wipeouts in red
This commit is contained in:
parent
fe1c4df4f1
commit
0d9ed8874f
2
.gitignore
vendored
2
.gitignore
vendored
@ -13,4 +13,4 @@
|
|||||||
*.out
|
*.out
|
||||||
|
|
||||||
server
|
server
|
||||||
storage.db
|
storage.sqlite
|
||||||
|
3
Makefile
3
Makefile
@ -1,3 +1,6 @@
|
|||||||
|
# for development, db in cwd
|
||||||
|
export DATABASE_PATH := ./storage.sqlite
|
||||||
|
|
||||||
VERSION := $(shell git rev-parse --short HEAD)
|
VERSION := $(shell git rev-parse --short HEAD)
|
||||||
BUILDTIME := $(shell date -u '+%Y-%m-%dT%H:%M:%SZ')
|
BUILDTIME := $(shell date -u '+%Y-%m-%dT%H:%M:%SZ')
|
||||||
BUILDTIMEFILENAME := $(shell date -u '+%Y%m%d-%H%M%SZ')
|
BUILDTIMEFILENAME := $(shell date -u '+%Y%m%d-%H%M%SZ')
|
||||||
|
1
go.mod
1
go.mod
@ -6,6 +6,7 @@ require (
|
|||||||
github.com/UnnoTed/fileb0x v1.1.4 // indirect
|
github.com/UnnoTed/fileb0x v1.1.4 // indirect
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
|
||||||
github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4
|
github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4
|
||||||
|
github.com/hako/durafmt v0.0.0-20191009132224-3f39dc1ed9f4
|
||||||
github.com/jinzhu/gorm v1.9.12
|
github.com/jinzhu/gorm v1.9.12
|
||||||
github.com/k0kubun/pp v3.0.1+incompatible
|
github.com/k0kubun/pp v3.0.1+incompatible
|
||||||
github.com/labstack/echo v3.3.10+incompatible
|
github.com/labstack/echo v3.3.10+incompatible
|
||||||
|
2
go.sum
2
go.sum
@ -20,6 +20,8 @@ github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclK
|
|||||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/hako/durafmt v0.0.0-20191009132224-3f39dc1ed9f4 h1:60gBOooTSmNtrqNaRvrDbi8VAne0REaek2agjnITKSw=
|
||||||
|
github.com/hako/durafmt v0.0.0-20191009132224-3f39dc1ed9f4/go.mod h1:5Scbynm8dF1XAPwIwkGPqzkM/shndPm79Jd1003hTjE=
|
||||||
github.com/jinzhu/gorm v1.9.12 h1:Drgk1clyWT9t9ERbzHza6Mj/8FY/CqMyVzOiHviMo6Q=
|
github.com/jinzhu/gorm v1.9.12 h1:Drgk1clyWT9t9ERbzHza6Mj/8FY/CqMyVzOiHviMo6Q=
|
||||||
github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs=
|
github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs=
|
||||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||||
|
2
hn/db.go
2
hn/db.go
@ -17,6 +17,7 @@ type HNFrontPage struct {
|
|||||||
HighestRank uint // frontpage index
|
HighestRank uint // frontpage index
|
||||||
Rank uint // frontpage index
|
Rank uint // frontpage index
|
||||||
Title string // submission title
|
Title string // submission title
|
||||||
|
Score uint // updoots
|
||||||
URL string // duh
|
URL string // duh
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,6 +28,7 @@ type HNStoryRank struct {
|
|||||||
Title string // submission title
|
Title string // submission title
|
||||||
URL string // duh
|
URL string // duh
|
||||||
Rank uint // frontpage index
|
Rank uint // frontpage index
|
||||||
|
Score uint // updoots
|
||||||
FetchedAt time.Time // identical within fetchid
|
FetchedAt time.Time // identical within fetchid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +88,7 @@ func (f *Fetcher) StoreFrontPage() error {
|
|||||||
Rank: uint(i + 1),
|
Rank: uint(i + 1),
|
||||||
URL: item.URL,
|
URL: item.URL,
|
||||||
Title: item.Title,
|
Title: item.Title,
|
||||||
|
Score: item.Score,
|
||||||
FetchedAt: t,
|
FetchedAt: t,
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
@ -109,6 +110,7 @@ func (f *Fetcher) StoreFrontPage() error {
|
|||||||
HighestRank: uint(i + 1),
|
HighestRank: uint(i + 1),
|
||||||
Rank: uint(i + 1),
|
Rank: uint(i + 1),
|
||||||
Title: item.Title,
|
Title: item.Title,
|
||||||
|
Score: uint(item.Score),
|
||||||
URL: item.URL,
|
URL: item.URL,
|
||||||
}
|
}
|
||||||
f.db.Create(&r)
|
f.db.Create(&r)
|
||||||
@ -116,6 +118,7 @@ func (f *Fetcher) StoreFrontPage() error {
|
|||||||
Uint("hnid", uint(id)).
|
Uint("hnid", uint(id)).
|
||||||
Uint("rank", uint(i+1)).
|
Uint("rank", uint(i+1)).
|
||||||
Str("title", item.Title).
|
Str("title", item.Title).
|
||||||
|
Int("score", item.Score).
|
||||||
Str("url", item.URL).
|
Str("url", item.URL).
|
||||||
Msg("HN new story on frontpage")
|
Msg("HN new story on frontpage")
|
||||||
} else {
|
} else {
|
||||||
@ -129,10 +132,12 @@ func (f *Fetcher) StoreFrontPage() error {
|
|||||||
Uint("hnid", uint(id)).
|
Uint("hnid", uint(id)).
|
||||||
Uint("oldrank", old.Rank).
|
Uint("oldrank", old.Rank).
|
||||||
Uint("newrank", uint(i+1)).
|
Uint("newrank", uint(i+1)).
|
||||||
|
Int("score", item.Score).
|
||||||
Str("title", item.Title).
|
Str("title", item.Title).
|
||||||
Str("url", item.URL).
|
Str("url", item.URL).
|
||||||
Msg("HN story rank changed, recording new rank")
|
Msg("HN story rank changed, recording new rank")
|
||||||
old.Rank = uint(i + 1)
|
old.Rank = uint(i + 1)
|
||||||
|
old.Score = uint(item.Score)
|
||||||
needSave = true
|
needSave = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,6 +150,12 @@ func (f *Fetcher) StoreFrontPage() error {
|
|||||||
old.HighestRank = uint(i + 1)
|
old.HighestRank = uint(i + 1)
|
||||||
needSave = true
|
needSave = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if old.Score != uint(item.Score) {
|
||||||
|
old.Score = uint(item.Score)
|
||||||
|
needSave = true
|
||||||
|
}
|
||||||
|
|
||||||
if needSave {
|
if needSave {
|
||||||
f.db.Save(&old)
|
f.db.Save(&old)
|
||||||
}
|
}
|
||||||
|
@ -24,33 +24,41 @@ func (r *RequestHandlerSet) indexHandler(c echo.Context) error {
|
|||||||
r.db.Where("disappeared is not ?", SQLITE_NULL_DATETIME).Order("disappeared desc").Find(&fpi)
|
r.db.Where("disappeared is not ?", SQLITE_NULL_DATETIME).Order("disappeared desc").Find(&fpi)
|
||||||
|
|
||||||
type fprow struct {
|
type fprow struct {
|
||||||
Duration string
|
Duration string
|
||||||
URL string
|
DurationSecs uint
|
||||||
Title string
|
URL string
|
||||||
HighestRank uint
|
Title string
|
||||||
HNID uint
|
HighestRank uint
|
||||||
TimeGone string
|
HNID uint
|
||||||
|
Score uint
|
||||||
|
TimeGone string
|
||||||
|
TimeGoneSecs uint
|
||||||
}
|
}
|
||||||
var fprows []fprow
|
var fprows []fprow
|
||||||
|
|
||||||
for _, item := range fpi {
|
for _, item := range fpi {
|
||||||
fprows = append(fprows, fprow{
|
fprows = append(fprows, fprow{
|
||||||
Duration: item.Disappeared.Round(time.Minute).Sub(item.Appeared.Round(time.Minute)).String(),
|
Duration: timeDiffHuman(item.Disappeared, item.Appeared),
|
||||||
URL: item.URL,
|
DurationSecs: timeDiffAbsSeconds(item.Disappeared, item.Appeared),
|
||||||
HNID: item.HNID,
|
URL: item.URL,
|
||||||
Title: item.Title,
|
HNID: item.HNID,
|
||||||
HighestRank: item.HighestRank,
|
Score: item.Score,
|
||||||
TimeGone: time.Now().Round(time.Minute).Sub(item.Disappeared.Round(time.Minute)).String(),
|
Title: item.Title,
|
||||||
|
HighestRank: item.HighestRank,
|
||||||
|
TimeGone: timeDiffHuman(time.Now(), item.Disappeared),
|
||||||
|
TimeGoneSecs: timeDiffAbsSeconds(time.Now(), item.Disappeared),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type rowtwo struct {
|
type rowtwo struct {
|
||||||
Duration string
|
Duration string
|
||||||
URL string
|
DurationSecs uint
|
||||||
Title string
|
URL string
|
||||||
HighestRank uint
|
Title string
|
||||||
HNID uint
|
Score uint
|
||||||
Rank uint
|
HighestRank uint
|
||||||
|
HNID uint
|
||||||
|
Rank uint
|
||||||
}
|
}
|
||||||
var currentfp []rowtwo
|
var currentfp []rowtwo
|
||||||
|
|
||||||
@ -59,12 +67,14 @@ func (r *RequestHandlerSet) indexHandler(c echo.Context) error {
|
|||||||
|
|
||||||
for _, item := range cur {
|
for _, item := range cur {
|
||||||
currentfp = append(currentfp, rowtwo{
|
currentfp = append(currentfp, rowtwo{
|
||||||
Duration: time.Now().Round(time.Minute).Sub(item.Appeared.Round(time.Minute)).String(),
|
Duration: timeDiffHuman(time.Now(), item.Appeared),
|
||||||
URL: item.URL,
|
DurationSecs: timeDiffAbsSeconds(time.Now(), item.Appeared),
|
||||||
HNID: item.HNID,
|
URL: item.URL,
|
||||||
Title: item.Title,
|
HNID: item.HNID,
|
||||||
HighestRank: item.HighestRank,
|
Score: item.Score,
|
||||||
Rank: item.Rank,
|
Title: item.Title,
|
||||||
|
HighestRank: item.HighestRank,
|
||||||
|
Rank: item.Rank,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
hn/misc.go
Normal file
20
hn/misc.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package hn
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hako/durafmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func timeDiffHuman(first time.Time, second time.Time) string {
|
||||||
|
if first.Before(second) {
|
||||||
|
return durafmt.ParseShort(second.Sub(first)).String()
|
||||||
|
} else {
|
||||||
|
return durafmt.ParseShort(first.Sub(second)).String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func timeDiffAbsSeconds(first time.Time, second time.Time) uint {
|
||||||
|
return uint(math.Abs(first.Sub(second).Truncate(time.Second).Seconds()))
|
||||||
|
}
|
@ -11,7 +11,8 @@
|
|||||||
<th scope="col">Hang Time</th>
|
<th scope="col">Hang Time</th>
|
||||||
<th scope="col">Title</th>
|
<th scope="col">Title</th>
|
||||||
<th scope="col">Highest Rank</th>
|
<th scope="col">Highest Rank</th>
|
||||||
<th scope="col">Time Since Wipeout</th>
|
<th scope="col">Time Since <a
|
||||||
|
href="https://www.youtube.com/watch?v=p13yZAjhU0M">Wipeout</a></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -21,8 +22,13 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td scope="row">{{exit.Duration}}</th>
|
{% if exit.DurationSecs < 1800 %}
|
||||||
<td><a href="{{exit.URL}}">{{exit.Title}}</a> <small>(<a
|
<td scope="row" class="text-danger">{{exit.Duration}}</th>
|
||||||
|
{% else %}
|
||||||
|
<td scope="row">{{exit.Duration}}</th>
|
||||||
|
{% endif %}
|
||||||
|
<td><a href="{{exit.URL}}">{{exit.Title}}</a> <small>({{exit.Score}}
|
||||||
|
points, <a
|
||||||
href="https://news.ycombinator.com/item?id={{exit.HNID}}">comments</a>)</small></td>
|
href="https://news.ycombinator.com/item?id={{exit.HNID}}">comments</a>)</small></td>
|
||||||
<td>{{exit.HighestRank}}</td>
|
<td>{{exit.HighestRank}}</td>
|
||||||
<td>{{exit.TimeGone}}</td>
|
<td>{{exit.TimeGone}}</td>
|
||||||
@ -47,7 +53,7 @@
|
|||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td scope="row">{{i.Duration}}</th>
|
<td scope="row">{{i.Duration}}</th>
|
||||||
<td><a href="{{i.URL}}">{{i.Title}}</a> <small>(<a
|
<td><a href="{{i.URL}}">{{i.Title}}</a> <small>({{i.Score}} points, <a
|
||||||
href="https://news.ycombinator.com/item?id={{i.HNID}}">comments</a>)</small></td>
|
href="https://news.ycombinator.com/item?id={{i.HNID}}">comments</a>)</small></td>
|
||||||
<td>{{i.HighestRank}}</td>
|
<td>{{i.HighestRank}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
Loading…
Reference in New Issue
Block a user