support partitioned tables in frontend

This commit is contained in:
nate smith 2024-04-30 21:19:57 -07:00
부모 92a35eb823
커밋 4b497a8185
2개의 변경된 파일109개의 추가작업 그리고 13개의 파일을 삭제

파일 보기

@ -122,10 +122,27 @@ a {
<a is="theme-toggler"></a>
</p>
<p id="about">
HELLO. THIS IS A <a href="https://github.com/vilmibm/trunkless">SOFT WARE</a> FOR MAKING <a href="https://en.wikipedia.org/wiki/Cut-up_technique">CUT-UP POETRY</a>. THERE ARE 467,014,991 POSSIBLE LINES YOU MAY SEE. ALL OF THE LINES ARE FROM THE ENGLISH CORPUS OF <a href="https://gutenberg.org">PROJECT GUTERNBERG</a>. SOME MAY BE OBJECTIONABLE AND I'M SORRY. THE AUTHOR OF THIS SOFT WARE IS <a href="https://tilde.town/~vilmibm">~VILMIBM</a>.
<div>
HELLO. THIS IS A <a href="https://github.com/vilmibm/trunkless">SOFT WARE</a> FOR MAKING <a href="https://en.wikipedia.org/wiki/Cut-up_technique">CUT-UP POETRY</a>. THERE ARE A VARIETY OF CORPORA TO CHOOSE FROM:
</div>
<ul>
<li><code>gutenberg</code>, THE ENTIRE ENGLISH CONTENT OF <a href="https://gutenberg.org">PROJECT GUTENBERG</a>. IT IS UNABRIDGED: BE WARNED.</li>
</ul>
<div>
THE AUTHOR OF THIS SOFT WARE IS <a href="https://tilde.town/~vilmibm">~VILMIBM</a>.
</div>
</p>
<div class="controls">
<button is="poem-resetter"></button>
<form is="corpus-picker" style="display:inline">
<label for="corpus-select">corpus:</label>
<select name="corpus" id="corpus-select">
{{range .Corpora}}
<option value="{{.ID}}">{{.Name}} ({{.MaxID}} possible lines)</option>
{{end}}
</select>
</form>
<form is="poem-saver" style="border: 1px solid grey; display:inline; padding:4px;">
<button class="copy" type="submit">copy</button>

파일 보기

@ -3,6 +3,7 @@ package web
import (
"context"
"crypto/rand"
"fmt"
"html/template"
"log"
"math/big"
@ -26,6 +27,12 @@ type phrase struct {
Source source
}
type corpus struct {
ID string
Name string
MaxID *big.Int
}
func Serve() error {
r := gin.Default()
r.SetFuncMap(template.FuncMap{
@ -39,8 +46,65 @@ func Serve() error {
r.StaticFile("/main.js", "./web/assets/main.js")
r.StaticFile("/html2canvas.min.js", "./web/assets/html2canvas.min.js")
// TODO use new db functions for id ranges
randMax := big.NewInt(db.MaxID)
bctx := context.Background()
pool, err := db.Pool()
if err != nil {
return fmt.Errorf("db pool failed: %w", err)
}
defer pool.Close()
corpora := []corpus{}
conn, err := db.Connect()
if err != nil {
return err
}
fmt.Println("gathering max IDs...")
rows, err := conn.Query(bctx, "SELECT tablename FROM pg_tables WHERE tablename LIKE '%phrases_%'")
if err != nil {
return fmt.Errorf("tablename query failed: %w", err)
}
defer rows.Close()
tables := []string{}
for rows.Next() {
var tablename string
err = rows.Scan(&tablename)
if err != nil {
return err
}
tables = append(tables, tablename)
}
rows.Close()
fmt.Printf("found %d tables\n", len(tables))
for _, tablename := range tables {
fmt.Printf("- %s...", tablename)
var maxID int64
err = conn.QueryRow(bctx, fmt.Sprintf("SELECT max(id) FROM %s", tablename)).Scan(&maxID)
if err != nil {
return err
}
fmt.Printf("%v...", maxID)
parts := strings.Split(tablename, "_")
corpusid := parts[1]
var name string
err := conn.QueryRow(bctx, "SELECT name FROM corpora WHERE id=$1", corpusid).Scan(&name)
if err != nil {
return err
}
fmt.Printf("%s.\n", name)
corpora = append(corpora, corpus{
ID: corpusid,
Name: name,
MaxID: big.NewInt(maxID),
})
}
conn.Close(bctx)
fmt.Println("...done")
r.HEAD("/", func(c *gin.Context) {
c.String(http.StatusOK, "")
@ -48,39 +112,54 @@ func Serve() error {
r.GET("/", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.tmpl", struct {
// TODO handle multiple corpora
MaxID int
}{db.MaxID})
Corpora []corpus
}{corpora})
})
// TODO retool this for pg
r.GET("/line", func(c *gin.Context) {
conn, err := db.Connect()
conn, err := pool.Acquire(bctx)
if err != nil {
log.Println(err.Error())
c.String(http.StatusInternalServerError, "oh no.")
return
}
defer conn.Close(context.Background())
defer conn.Release()
id, err := rand.Int(rand.Reader, randMax)
corpusid := c.DefaultQuery("corpus", "c3d8e9")
var cpus corpus
var tablename string
for _, corpus := range corpora {
if corpus.ID == corpusid {
cpus = corpus
tablename = fmt.Sprintf("phrases_%s", corpusid)
}
}
if tablename == "" {
c.String(http.StatusTeapot, "have some tea :)")
}
id, err := rand.Int(rand.Reader, cpus.MaxID)
if err != nil {
log.Println(err.Error())
c.String(http.StatusInternalServerError, "oh no.")
return
}
row := conn.QueryRow(context.Background(), "select p.phrase, s.id, s.name from phrases p join sources s on p.sourceid = s.id where p.id = $1", id.Int64())
var p phrase
var s source
err = row.Scan(&p.Text, &s.ID, &s.Name)
err = conn.QueryRow(bctx,
fmt.Sprintf(
"SELECT p.phrase, s.id, s.name FROM phrases_%s p join sources s on p.sourceid = s.id where p.id = $1", cpus.ID),
id.Int64()).Scan(&p.Text, &s.ID, &s.Name)
if err != nil {
log.Println(err.Error())
c.String(http.StatusInternalServerError, "oh no.")
}
p.Source = s
p.ID = id.Int64()
conn.Release()
c.JSON(http.StatusOK, p)
})