| 
 | 1 | +package main  | 
 | 2 | + | 
 | 3 | +import (  | 
 | 4 | +	"context"  | 
 | 5 | +	"math/rand/v2"  | 
 | 6 | +	"slices"  | 
 | 7 | +	"strconv"  | 
 | 8 | +	"time"  | 
 | 9 | + | 
 | 10 | +	"github.com/indigo-web/indigo/http"  | 
 | 11 | +	"github.com/indigo-web/indigo/http/mime"  | 
 | 12 | + | 
 | 13 | +	"indigo/app/models"  | 
 | 14 | +	"indigo/app/templates"  | 
 | 15 | +)  | 
 | 16 | + | 
 | 17 | +type (  | 
 | 18 | +	App struct {  | 
 | 19 | +		DB    *DB  | 
 | 20 | +		Cache models.Worlds  | 
 | 21 | +	}  | 
 | 22 | +)  | 
 | 23 | + | 
 | 24 | +func NewApp(DB *DB) *App {  | 
 | 25 | +	return &App{DB: DB}  | 
 | 26 | +}  | 
 | 27 | + | 
 | 28 | +func (app *App) PopulateCache(ctx context.Context) error {  | 
 | 29 | +	cache := make(models.Worlds, 10000)  | 
 | 30 | + | 
 | 31 | +	err := app.DB.FillWorlds(context.Background(), cache)  | 
 | 32 | +	if err != nil {  | 
 | 33 | +		return err  | 
 | 34 | +	}  | 
 | 35 | + | 
 | 36 | +	app.Cache = cache  | 
 | 37 | + | 
 | 38 | +	return nil  | 
 | 39 | +}  | 
 | 40 | + | 
 | 41 | +func (app *App) HandleJSON(request *http.Request) *http.Response {  | 
 | 42 | +	return request.Respond().Header("Date", time.Now().Format(time.RFC1123)).Header("Server", "indigo").JSON(&models.Message{  | 
 | 43 | +		Message: "Hello, World!",  | 
 | 44 | +	})  | 
 | 45 | +}  | 
 | 46 | + | 
 | 47 | +func (app *App) HandleDB(request *http.Request) *http.Response {  | 
 | 48 | +	world := &models.World{  | 
 | 49 | +		ID: rand.IntN(10000) + 1,  | 
 | 50 | +	}  | 
 | 51 | + | 
 | 52 | +	err := app.DB.FillWorldByID(context.Background(), world)  | 
 | 53 | +	if err != nil {  | 
 | 54 | +		return http.Error(request, err)  | 
 | 55 | +	}  | 
 | 56 | + | 
 | 57 | +	return request.Respond().Header("Date", time.Now().Format(time.RFC1123)).Header("Server", "indigo").JSON(world)  | 
 | 58 | +}  | 
 | 59 | + | 
 | 60 | +func (app *App) HandleQuery(request *http.Request) *http.Response {  | 
 | 61 | +	n := normalizeNumber(request.Params.Lookup("n"))  | 
 | 62 | + | 
 | 63 | +	i, worlds := 0, make(models.Worlds, n)  | 
 | 64 | + | 
 | 65 | +	for i = range worlds {  | 
 | 66 | +		worlds[i].ID = rand.IntN(10000) + 1  | 
 | 67 | +	}  | 
 | 68 | + | 
 | 69 | +	err := app.DB.FillWorldsByID(context.Background(), worlds)  | 
 | 70 | +	if err != nil {  | 
 | 71 | +		return http.Error(request, err)  | 
 | 72 | +	}  | 
 | 73 | + | 
 | 74 | +	return request.Respond().Header("Date", time.Now().Format(time.RFC1123)).Header("Server", "indigo").JSON(&worlds)  | 
 | 75 | +}  | 
 | 76 | + | 
 | 77 | +func (app *App) HandleUpdate(request *http.Request) *http.Response {  | 
 | 78 | +	n := normalizeNumber(request.Params.Lookup("n"))  | 
 | 79 | + | 
 | 80 | +	i, worlds := 0, make(models.Worlds, n)  | 
 | 81 | + | 
 | 82 | +	for i = range worlds {  | 
 | 83 | +		worlds[i].ID = rand.IntN(10000) + 1  | 
 | 84 | +	}  | 
 | 85 | + | 
 | 86 | +	err := app.DB.FillWorldsByID(context.Background(), worlds)  | 
 | 87 | +	if err != nil {  | 
 | 88 | +		return http.Error(request, err)  | 
 | 89 | +	}  | 
 | 90 | + | 
 | 91 | +	for i = range worlds {  | 
 | 92 | +		worlds[i].RandomNumber = rand.IntN(10000) + 1  | 
 | 93 | +	}  | 
 | 94 | + | 
 | 95 | +	slices.SortFunc(worlds, func(a, b models.World) int {  | 
 | 96 | +		return a.ID - b.ID  | 
 | 97 | +	})  | 
 | 98 | + | 
 | 99 | +	err = app.DB.UpdateWorlds(context.Background(), worlds)  | 
 | 100 | +	if err != nil {  | 
 | 101 | +		return http.Error(request, err)  | 
 | 102 | +	}  | 
 | 103 | + | 
 | 104 | +	return request.Respond().Header("Date", time.Now().Format(time.RFC1123)).Header("Server", "indigo").JSON(&worlds)  | 
 | 105 | +}  | 
 | 106 | + | 
 | 107 | +func (app *App) HandleCachedQuery(request *http.Request) *http.Response {  | 
 | 108 | +	n := normalizeNumber(request.Params.Lookup("n"))  | 
 | 109 | + | 
 | 110 | +	i, worlds := 0, make(models.Worlds, n)  | 
 | 111 | + | 
 | 112 | +	for i = range worlds {  | 
 | 113 | +		worlds[i] = app.Cache[rand.Int32N(10000)]  | 
 | 114 | +	}  | 
 | 115 | + | 
 | 116 | +	return request.Respond().Header("Date", time.Now().Format(time.RFC1123)).Header("Server", "indigo").JSON(&worlds)  | 
 | 117 | +}  | 
 | 118 | + | 
 | 119 | +func (app *App) HandleFortune(request *http.Request) *http.Response {  | 
 | 120 | +	fortunes, err := app.DB.GetFortunes(context.Background())  | 
 | 121 | +	if err != nil {  | 
 | 122 | +		return http.Error(request, err)  | 
 | 123 | +	}  | 
 | 124 | + | 
 | 125 | +	fortunes = append(fortunes, models.Fortune{  | 
 | 126 | +		Message: "Additional fortune added at request time.",  | 
 | 127 | +	})  | 
 | 128 | + | 
 | 129 | +	slices.SortFunc(fortunes, func(a, b models.Fortune) int {  | 
 | 130 | +		if a.Message < b.Message {  | 
 | 131 | +			return -1  | 
 | 132 | +		} else if a.Message > b.Message {  | 
 | 133 | +			return 1  | 
 | 134 | +		}  | 
 | 135 | + | 
 | 136 | +		return 0  | 
 | 137 | +	})  | 
 | 138 | + | 
 | 139 | +	return request.Respond().Header("Date", time.Now().Format(time.RFC1123)).Header("Server", "indigo").ContentType(mime.HTML + "; charset=UTF-8").String(templates.HTMLFortunes(fortunes))  | 
 | 140 | +}  | 
 | 141 | + | 
 | 142 | +func (app *App) HandlePlaintext(request *http.Request) *http.Response {  | 
 | 143 | +	return request.Respond().Header("Date", time.Now().Format(time.RFC1123)).Header("Server", "indigo").ContentType(mime.Plain).String("Hello, World!")  | 
 | 144 | +}  | 
 | 145 | + | 
 | 146 | +func normalizeNumber(nString string, found bool) int {  | 
 | 147 | +	if !found {  | 
 | 148 | +		nString = "0"  | 
 | 149 | +	}  | 
 | 150 | + | 
 | 151 | +	n, err := strconv.Atoi(nString)  | 
 | 152 | +	if err != nil {  | 
 | 153 | +		n = 0  | 
 | 154 | +	}  | 
 | 155 | + | 
 | 156 | +	if n < 1 {  | 
 | 157 | +		n = 1  | 
 | 158 | +	} else if n > 500 {  | 
 | 159 | +		n = 500  | 
 | 160 | +	}  | 
 | 161 | + | 
 | 162 | +	return n  | 
 | 163 | +}  | 
0 commit comments