summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLizzy Hunt <elizabeth.hunt@simponic.xyz>2024-03-10 16:45:26 -0600
committerLizzy Hunt <elizabeth.hunt@simponic.xyz>2024-03-10 16:45:26 -0600
commitdef61909c2423b19b063a5807cc399a41de39974 (patch)
tree0b035fbb1c29ac858b042092d183824f8bc1a5b5
parent5a85dd89bc82d8fc133c0e9a58859ae9b98dbe0f (diff)
downloadtilde.club-def61909c2423b19b063a5807cc399a41de39974.tar.gz
tilde.club-def61909c2423b19b063a5807cc399a41de39974.zip
fruitvote
-rw-r--r--go.mod2
-rw-r--r--go.sum2
-rw-r--r--html/fruitvote/fruits.json126
-rwxr-xr-xhtml/fruitvote/fruitvotebin0 -> 13320296 bytes
-rw-r--r--html/fruitvote/main.go249
-rw-r--r--html/fruitvote/templates/stats.html17
-rw-r--r--html/fruitvote/templates/vote.html28
-rw-r--r--html/public/css/style.css97
-rw-r--r--html/public/fruitvote/GoPage.php18
-rw-r--r--html/public/fruitvote/health.php7
-rw-r--r--html/public/fruitvote/stats.php7
-rw-r--r--html/public/img/fruitvote/apricot.jpgbin0 -> 24200 bytes
-rw-r--r--html/public/img/fruitvote/avocado.jpgbin0 -> 33382 bytes
-rw-r--r--html/public/img/fruitvote/banana.pngbin0 -> 346610 bytes
-rw-r--r--html/public/img/fruitvote/blackberry.jpgbin0 -> 126739 bytes
-rw-r--r--html/public/img/fruitvote/blueberry.jpgbin0 -> 24181 bytes
-rw-r--r--html/public/img/fruitvote/cherry.jpgbin0 -> 23236 bytes
-rw-r--r--html/public/img/fruitvote/coconut.jpgbin0 -> 130435 bytes
-rw-r--r--html/public/img/fruitvote/cranberry.jpgbin0 -> 131508 bytes
-rw-r--r--html/public/img/fruitvote/dock-april.pngbin0 -> 500834 bytes
-rw-r--r--html/public/img/fruitvote/fig.jpgbin0 -> 32905 bytes
-rw-r--r--html/public/img/fruitvote/grape.jpgbin0 -> 23839 bytes
-rw-r--r--html/public/img/fruitvote/guava.jpgbin0 -> 36517 bytes
-rw-r--r--html/public/img/fruitvote/honeydew.jpegbin0 -> 281636 bytes
-rw-r--r--html/public/img/fruitvote/kiwi.jpgbin0 -> 19700 bytes
-rw-r--r--html/public/img/fruitvote/lemon.jpgbin0 -> 130118 bytes
-rw-r--r--html/public/img/fruitvote/lime.jpgbin0 -> 43473 bytes
-rw-r--r--html/public/img/fruitvote/mango.jpgbin0 -> 43318 bytes
-rw-r--r--html/public/img/fruitvote/melon.jpgbin0 -> 128804 bytes
-rw-r--r--html/public/img/fruitvote/nectarine.jpgbin0 -> 29788 bytes
-rw-r--r--html/public/img/fruitvote/orange.jpgbin0 -> 62043 bytes
-rw-r--r--html/public/img/fruitvote/peach.jpgbin0 -> 21383 bytes
-rw-r--r--html/public/img/fruitvote/pear.jpgbin0 -> 30339 bytes
-rw-r--r--html/public/img/fruitvote/persimmon.jpgbin0 -> 62875 bytes
-rw-r--r--html/public/img/fruitvote/pineapple.jpgbin0 -> 65826 bytes
-rw-r--r--html/public/img/fruitvote/plum.jpgbin0 -> 60167 bytes
-rw-r--r--html/public/img/fruitvote/pomegranate.jpgbin0 -> 92033 bytes
-rw-r--r--html/public/img/fruitvote/pumpkin.jpgbin0 -> 113972 bytes
-rw-r--r--html/public/img/fruitvote/raspberry.jpgbin0 -> 175080 bytes
-rw-r--r--html/public/img/fruitvote/strawberry.jpgbin0 -> 55318 bytes
-rw-r--r--html/public/img/fruitvote/tomato.jpgbin0 -> 11422 bytes
-rw-r--r--html/public/img/fruitvote/versus.gifbin0 -> 37777 bytes
-rw-r--r--html/public/img/fruitvote/watermelon.jpgbin0 -> 50510 bytes
43 files changed, 533 insertions, 20 deletions
diff --git a/go.mod b/go.mod
index bb8a917..b06e58c 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,5 @@
module tilde.club/~simponic
go 1.21.5
+
+require github.com/mattn/go-sqlite3 v1.14.22 // indirect
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..e8d092a
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,2 @@
+github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
+github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
diff --git a/html/fruitvote/fruits.json b/html/fruitvote/fruits.json
new file mode 100644
index 0000000..a97f846
--- /dev/null
+++ b/html/fruitvote/fruits.json
@@ -0,0 +1,126 @@
+[
+ {
+ "name": "apple",
+ "img": "/~simponic/img/fruitvote/dock-april.png"
+ },
+ {
+ "name": "apricot",
+ "img": "/~simponic/img/fruitvote/apricot.jpg"
+ },
+ {
+ "name": "avocado",
+ "img": "/~simponic/img/fruitvote/avocado.jpg"
+ },
+ {
+ "name": "banana",
+ "img": "/~simponic/img/fruitvote/banana.png"
+ },
+ {
+ "name": "blackberry",
+ "img": "/~simponic/img/fruitvote/blackberry.jpg"
+ },
+ {
+ "name": "blueberry",
+ "img": "/~simponic/img/fruitvote/blueberry.jpg"
+ },
+ {
+ "name": "cherry",
+ "img": "/~simponic/img/fruitvote/cherry.jpg"
+ },
+ {
+ "name": "coconut",
+ "img": "/~simponic/img/fruitvote/coconut.jpg"
+ },
+ {
+ "name": "cranberry",
+ "img": "/~simponic/img/fruitvote/cranberry.jpg"
+ },
+ {
+ "name": "fig",
+ "img": "/~simponic/img/fruitvote/fig.jpg"
+ },
+ {
+ "name": "grape",
+ "img": "/~simponic/img/fruitvote/grape.jpg"
+ },
+ {
+ "name": "guava",
+ "img": "/~simponic/img/fruitvote/guava.jpg"
+ },
+ {
+ "name": "honeydew",
+ "img": "/~simponic/img/fruitvote/honeydew.jpeg"
+ },
+ {
+ "name": "kiwi",
+ "img": "/~simponic/img/fruitvote/kiwi.jpg"
+ },
+ {
+ "name": "lemon",
+ "img": "/~simponic/img/fruitvote/lemon.jpg"
+ },
+ {
+ "name": "lime",
+ "img": "/~simponic/img/fruitvote/lime.jpg"
+ },
+ {
+ "name": "mango",
+ "img": "/~simponic/img/fruitvote/mango.jpg"
+ },
+ {
+ "name": "melon",
+ "img": "/~simponic/img/fruitvote/melon.jpg"
+ },
+ {
+ "name": "nectarine",
+ "img": "/~simponic/img/fruitvote/nectarine.jpg"
+ },
+ {
+ "name": "orange",
+ "img": "/~simponic/img/fruitvote/orange.jpg"
+ },
+ {
+ "name": "peach",
+ "img": "/~simponic/img/fruitvote/peach.jpg"
+ },
+ {
+ "name": "pear",
+ "img": "/~simponic/img/fruitvote/pear.jpg"
+ },
+ {
+ "name": "pineapple",
+ "img": "/~simponic/img/fruitvote/pineapple.jpg"
+ },
+ {
+ "name": "persimmon",
+ "img": "/~simponic/img/fruitvote/persimmon.jpg"
+ },
+ {
+ "name": "plum",
+ "img": "/~simponic/img/fruitvote/plum.jpg"
+ },
+ {
+ "name": "pomegranate",
+ "img": "/~simponic/img/fruitvote/pomegranate.jpg"
+ },
+ {
+ "name": "pumpkin",
+ "img": "/~simponic/img/fruitvote/pumpkin.jpg"
+ },
+ {
+ "name": "raspberry",
+ "img": "/~simponic/img/fruitvote/raspberry.jpg"
+ },
+ {
+ "name": "strawberry",
+ "img": "/~simponic/img/fruitvote/strawberry.jpg"
+ },
+ {
+ "name": "tomato",
+ "img": "/~simponic/img/fruitvote/tomato.jpg"
+ },
+ {
+ "name": "watermelon",
+ "img": "/~simponic/img/fruitvote/watermelon.jpg"
+ }
+]
diff --git a/html/fruitvote/fruitvote b/html/fruitvote/fruitvote
new file mode 100755
index 0000000..51485cf
--- /dev/null
+++ b/html/fruitvote/fruitvote
Binary files differ
diff --git a/html/fruitvote/main.go b/html/fruitvote/main.go
index b41c88f..cfd1bb8 100644
--- a/html/fruitvote/main.go
+++ b/html/fruitvote/main.go
@@ -1,9 +1,13 @@
package main
import (
+ "database/sql"
+ "encoding/json"
"flag"
"fmt"
+ _ "github.com/mattn/go-sqlite3"
"log"
+ "math"
"net"
"net/http"
"os"
@@ -11,51 +15,241 @@ import (
"os/signal"
"strings"
"syscall"
+ "text/template"
)
-func indexHandler(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(http.StatusOK)
- w.Write([]byte("Hello, this is a Unix socket HTTP server in Go!"))
+type Fruit struct {
+ Name string `json:"name"`
+ Img string `json:"img"`
+ Elo int `json:"elo"`
}
-func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(http.StatusOK)
- w.Write([]byte("healthy"))
+type Context struct {
+ db *sql.DB
+ users []string
+ templatePath string
+ socketPath string
+ fruitsPath string
+}
+
+type CurriedContextHandler func(*Context, http.ResponseWriter, *http.Request)
+
+func curryContext(context *Context) func(CurriedContextHandler) http.HandlerFunc {
+ return func(handler CurriedContextHandler) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ log.Println(r.Method, r.URL.Path, r.RemoteAddr)
+
+ handler(context, w, r)
+ }
+ }
+}
+
+func indexHandler(context *Context, resp http.ResponseWriter, req *http.Request) {
+ // get from POST
+ winner := req.FormValue("winner")
+ contestants := req.Form["contestant[]"]
+
+ if winner != "" && len(contestants) == 2 {
+ losingFruitName := string(contestants[0])
+ if losingFruitName == winner {
+ losingFruitName = string(contestants[1])
+ }
+ winningFruit := fruitByName(context.db, winner)
+ losingFruit := fruitByName(context.db, losingFruitName)
+
+ winningFruit.Elo, losingFruit.Elo = updateElo(winningFruit.Elo, losingFruit.Elo)
+
+ updateFruit(context.db, winningFruit)
+ updateFruit(context.db, losingFruit)
+
+ log.Println(winningFruit.Name, "won against", losingFruit.Name, "new elo:", winningFruit.Elo, losingFruit.Elo)
+ }
+
+ fruitOne := randomFruit(context.db)
+ fruitTwo := randomFruit(context.db)
+ for fruitOne.Name == fruitTwo.Name {
+ fruitTwo = randomFruit(context.db)
+ }
+
+ templateFile := context.templatePath + "/vote.html"
+ vote, err := template.ParseFiles(templateFile)
+ if err != nil {
+ panic(err)
+ }
+
+ fruits := []Fruit{fruitOne, fruitTwo}
+ err = vote.Execute(resp, fruits)
+ if err != nil {
+ panic(err)
+ }
+ resp.Header().Set("Content-Type", "text/html")
+}
+
+func getStatsHandler(context *Context, resp http.ResponseWriter, _req *http.Request) {
+ rows, err := context.db.Query("SELECT name, img, elo FROM fruits ORDER BY elo DESC")
+ if err != nil {
+ panic(err)
+ }
+ defer rows.Close()
+
+ fruits := []Fruit{}
+ for rows.Next() {
+ fruit := Fruit{}
+ err = rows.Scan(&fruit.Name, &fruit.Img, &fruit.Elo)
+ if err != nil {
+ panic(err)
+ }
+ fruits = append(fruits, fruit)
+ }
+
+ templateFile := context.templatePath + "/stats.html"
+ stats, err := template.ParseFiles(templateFile)
+ if err != nil {
+ panic(err)
+ }
+
+ err = stats.Execute(resp, fruits)
+ if err != nil {
+ panic(err)
+ }
+ resp.Header().Set("Content-Type", "text/html")
+}
+
+func healthCheckHandler(context *Context, resp http.ResponseWriter, req *http.Request) {
+ resp.WriteHeader(http.StatusOK)
+ resp.Write([]byte("healthy"))
}
func main() {
- socketPath, users := getArgs()
- os.Remove(socketPath)
+ log.Println("starting server...")
+ log.SetFlags(log.LstdFlags | log.Lshortfile)
+
+ context := getArgs()
+ log.Println("removing socket file", context.socketPath)
+ os.Remove(context.socketPath)
- listener, err := net.Listen("unix", socketPath)
+ log.Println("migrating database...")
+ migrate(context.db)
+ seedFruits(context.db, context.fruitsPath)
+
+ listener, err := net.Listen("unix", context.socketPath)
if err != nil {
panic(err)
}
- os.Chmod(socketPath, 0700)
+ log.Println("listening on", context.socketPath)
+ os.Chmod(context.socketPath, 0700)
sigc := make(chan os.Signal, 1)
signal.Notify(sigc, os.Interrupt, os.Kill, syscall.SIGTERM)
go func(c chan os.Signal) {
- // Wait for a SIGINT or SIGKILL:
sig := <-c
- log.Printf("Caught signal %s: shutting down.", sig)
+ log.Printf("caught signal %s: shutting down.", sig)
listener.Close()
os.Exit(0)
}(sigc)
defer listener.Close()
- for _, user := range strings.Split(users, ",") {
- setACL(socketPath, user)
+ log.Println("setting ACLs for users", context.users)
+ for _, user := range context.users {
+ setACL(context.socketPath, user)
}
+ curriedContext := curryContext(context)
mux := http.NewServeMux()
- mux.HandleFunc("/", indexHandler)
- mux.HandleFunc("/health", healthCheckHandler)
+ mux.HandleFunc("/", curriedContext(indexHandler))
+ mux.HandleFunc("/health", curriedContext(healthCheckHandler))
+ mux.HandleFunc("/stats", curriedContext(getStatsHandler))
+ log.Println("serving http...")
http.Serve(listener, mux)
}
+func calculateRatingDelta(winnerRating int, loserRating int, K int) (int, int) {
+ winnerRatingFloat := float64(winnerRating)
+ loserRatingFloat := float64(loserRating)
+
+ expectedScoreWinner := 1 / (1 + math.Pow(10, (loserRatingFloat-winnerRatingFloat)/400))
+ expectedScoreLoser := 1 - expectedScoreWinner
+
+ changeWinner := int(math.Round(float64(K) * (1 - expectedScoreWinner)))
+ changeLoser := -int(math.Round(float64(K) * (expectedScoreLoser)))
+
+ return changeWinner, changeLoser
+}
+
+func updateElo(winnerElo int, loserElo int) (int, int) {
+ const K = 32
+
+ changeWinner, changeLoser := calculateRatingDelta(winnerElo, loserElo, K)
+
+ newWinnerElo := winnerElo + changeWinner
+ newLoserElo := loserElo + changeLoser
+
+ return newWinnerElo, newLoserElo
+}
+
+func seedFruits(db *sql.DB, fruitsPath string) {
+ log.Println("seeding fruits (haha)...")
+
+ fruitsContents, err := os.ReadFile(fruitsPath)
+ if err != nil {
+ panic(err)
+ }
+ jsonFruits := []Fruit{}
+ err = json.Unmarshal(fruitsContents, &jsonFruits)
+ if err != nil {
+ panic(err)
+ }
+
+ for _, fruit := range jsonFruits {
+ // insert if not exists
+ _, err := db.Exec("INSERT OR IGNORE INTO fruits (name, img) VALUES (?, ?)", fruit.Name, fruit.Img)
+ if err != nil {
+ panic(err)
+ }
+ }
+}
+
+func migrate(db *sql.DB) {
+ log.Println("creating fruits table...")
+ _, err := db.Exec(`
+ CREATE TABLE IF NOT EXISTS fruits (
+ name TEXT PRIMARY KEY,
+ img TEXT,
+ elo INTEGER DEFAULT 1400
+ );
+ `)
+ if err != nil {
+ panic(err)
+ }
+}
+
+func randomFruit(db *sql.DB) Fruit {
+ fruit := Fruit{}
+ err := db.QueryRow("SELECT name, img, elo FROM fruits ORDER BY RANDOM() LIMIT 1").Scan(&fruit.Name, &fruit.Img, &fruit.Elo)
+ if err != nil {
+ panic(err)
+ }
+ return fruit
+}
+
+func fruitByName(db *sql.DB, name string) Fruit {
+ fruit := Fruit{}
+ err := db.QueryRow("SELECT name, img, elo FROM fruits WHERE name = ?", name).Scan(&fruit.Name, &fruit.Img, &fruit.Elo)
+ if err != nil {
+ panic(err)
+ }
+ return fruit
+}
+
+func updateFruit(db *sql.DB, fruit Fruit) {
+ _, err := db.Exec("UPDATE fruits SET img = ?, elo = ? WHERE name = ?", fruit.Img, fruit.Elo, fruit.Name)
+ if err != nil {
+ panic(err)
+ }
+}
+
func setACL(socketPath, user string) {
cmd := exec.Command("setfacl", "-m", "u:"+user+":rwx", socketPath)
if err := cmd.Run(); err != nil {
@@ -63,15 +257,34 @@ func setACL(socketPath, user string) {
}
}
-func getArgs() (string, string) {
+func getArgs() *Context {
socketPath := flag.String("socket-path", "/tmp/go-server.sock", "Path to the Unix socket")
users := flag.String("users", "", "Comma-separated list of users for ACL")
+ database := flag.String("database-path", "/tmp/go-server.db", "Path to the SQLite database")
+ fruitsPath := flag.String("fruits", "/dev/null", "Path to the fruits file")
+ templatePath := flag.String("template", "", "Path to the template directory")
flag.Parse()
if *users == "" {
fmt.Println("You must specify at least one user with --users")
os.Exit(1)
}
+ if *templatePath == "" {
+ fmt.Println("You must specify a template directory with --template")
+ os.Exit(1)
+ }
- return *socketPath, *users
+ log.Println("opening database at", *database, "with foreign keys enabled")
+ db, err := sql.Open("sqlite3", *database+"?_foreign_keys=on")
+ if err != nil {
+ panic(err)
+ }
+
+ return &Context{
+ db: db,
+ users: strings.Split(*users, ","),
+ socketPath: *socketPath,
+ fruitsPath: *fruitsPath,
+ templatePath: *templatePath,
+ }
}
diff --git a/html/fruitvote/templates/stats.html b/html/fruitvote/templates/stats.html
new file mode 100644
index 0000000..c5fea5c
--- /dev/null
+++ b/html/fruitvote/templates/stats.html
@@ -0,0 +1,17 @@
+<table>
+ <tr>
+ <th>picture</th>
+ <th>name</th>
+ <th>elo</th>
+ </tr>
+ {{ range . }}
+ <tr>
+ <td><img src="{{ .Img }}" alt="{{ .Name }}" width="100" height="100"></td>
+ <td>{{ .Name }}</td>
+ <td>{{ .Elo }}</td>
+ </tr>
+ {{ end }}
+</table>
+<br />
+<a href="/~simponic/fruitvote">back</a>
+<br />
diff --git a/html/fruitvote/templates/vote.html b/html/fruitvote/templates/vote.html
new file mode 100644
index 0000000..6bc27df
--- /dev/null
+++ b/html/fruitvote/templates/vote.html
@@ -0,0 +1,28 @@
+
+<form method="POST">
+ <div class="fruitvote">
+ {{ range $i, $fruit := . }}
+ {{ if $i }}
+ <div class="versus">
+ <h1>OR</h1>
+ </div>
+ {{ end }}
+ <label class="contestant">
+ <input type="radio" name="winner" value="{{ .Name }}" {{ if eq $i 0 }} checked {{ end }} />
+ <div>
+ <img src="{{ .Img }}" alt="image" />
+ <p>{{ .Name }}</p>
+ </div>
+ </label>
+ <input type="hidden" name="contestant[]" value="{{ .Name }}" />
+ {{ end }}
+ </div>
+ <br />
+ <div>
+ <input type="submit" value="Vote" />
+ </div>
+</form>
+<br />
+<div><a href="/~simponic/fruitvote"><button>Skip</button></a></div>
+<br />
+<div><a href="/~simponic/fruitvote/stats">view rankings!</a></div>
diff --git a/html/public/css/style.css b/html/public/css/style.css
index a4f243f..95829c3 100644
--- a/html/public/css/style.css
+++ b/html/public/css/style.css
@@ -75,3 +75,100 @@ p {
li {
margin-left: 20px;
}
+
+.fruitvote {
+ display: flex;
+ flex-direction: row;
+ margin-top: 20px;
+ gap: 2rem;
+ max-width: 800px;
+}
+
+.contestant {
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ align-items: stretch;
+ border: 2px solid #ff69b4;
+ border-radius: 10px;
+ padding: 0.5rem;
+}
+
+.contestant div {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ border-radius: 10px;
+ height: 100%;
+ transition: background-color 0.3s ease;
+ padding: 1rem;
+}
+
+.contestant > input {
+ visibility: hidden;
+ position: absolute;
+}
+
+.contestant div:hover {
+ background-color: #ff69b4;
+ color: #2a2a2a;
+
+ cursor: pointer;
+}
+
+.contestant > input:checked + div {
+ background-color: #ff69b4;
+ color: #2a2a2a;
+
+ cursor: pointer;
+}
+
+.contestant div img {
+ width: auto;
+ height: auto;
+ max-width: 100%;
+ max-height: 100%;
+
+ border-radius: 10px;
+}
+
+.versus {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 20px;
+}
+
+table {
+ width: auto; /* Adjust based on content, not full width */
+ border-collapse: collapse;
+ background-color: #383838; /* Darker background for contrast */
+}
+
+th,
+td {
+ padding: 12px 20px; /* Good padding for readability */
+ border: 1px solid #f4c2c2; /* Soft pink borders */
+ color: #f4c2c2; /* Soft pink text */
+ text-align: left;
+}
+
+thead th {
+ background-color: #ff69b4; /* Brighter pink for header */
+ color: white; /* White text for contrast */
+ font-family: "Comic Sans MS", "Chalkboard SE", sans-serif;
+}
+
+tbody tr:nth-child(odd) {
+ background-color: #2f2f2f; /* Slightly lighter background for every other row for readability */
+}
+
+tbody tr {
+ transition: background-color 0.3s ease;
+}
+
+tbody tr:hover {
+ background-color: #ff47da; /* Change to a lighter pink on hover for interactivity */
+ color: #2a2a2a; /* Dark text for contrast */
+}
diff --git a/html/public/fruitvote/GoPage.php b/html/public/fruitvote/GoPage.php
index 864c1f7..7e03c35 100644
--- a/html/public/fruitvote/GoPage.php
+++ b/html/public/fruitvote/GoPage.php
@@ -4,7 +4,7 @@ class GoPage {
private $socket;
private $template;
- public function __construct($page, $socket = "/home/simponic/fruitvote/http.sock", $template = "../template.html") {
+ public function __construct($page, $socket = "/home/lizzy/fruitvote/http.sock", $template = "../template.html") {
$this->page = $page;
$this->socket = $socket;
$this->template = $template;
@@ -24,9 +24,23 @@ class GoPage {
curl_setopt($ch, CURLOPT_UNIX_SOCKET_PATH, $this->socket);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ // forward query params
+ $query = $_SERVER['QUERY_STRING'];
+ if ($query) {
+ curl_setopt($ch, CURLOPT_URL, $url."?".$query);
+ }
+
+ //forward post data
+ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, file_get_contents('php://input'));
+ }
+
+
$output = curl_exec($ch);
curl_close($ch);
- // todo: get headers / cookies, forward back response
+
+
return $output;
}
diff --git a/html/public/fruitvote/health.php b/html/public/fruitvote/health.php
new file mode 100644
index 0000000..8cea676
--- /dev/null
+++ b/html/public/fruitvote/health.php
@@ -0,0 +1,7 @@
+<?php
+
+require_once("GoPage.php");
+
+$page = new GoPage("/health");
+echo $page->render();
+?>
diff --git a/html/public/fruitvote/stats.php b/html/public/fruitvote/stats.php
new file mode 100644
index 0000000..5147723
--- /dev/null
+++ b/html/public/fruitvote/stats.php
@@ -0,0 +1,7 @@
+<?php
+
+require_once("GoPage.php");
+
+$page = new GoPage("/stats");
+echo $page->render();
+?>
diff --git a/html/public/img/fruitvote/apricot.jpg b/html/public/img/fruitvote/apricot.jpg
new file mode 100644
index 0000000..5ffc321
--- /dev/null
+++ b/html/public/img/fruitvote/apricot.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/avocado.jpg b/html/public/img/fruitvote/avocado.jpg
new file mode 100644
index 0000000..a0eb21c
--- /dev/null
+++ b/html/public/img/fruitvote/avocado.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/banana.png b/html/public/img/fruitvote/banana.png
new file mode 100644
index 0000000..6e69d77
--- /dev/null
+++ b/html/public/img/fruitvote/banana.png
Binary files differ
diff --git a/html/public/img/fruitvote/blackberry.jpg b/html/public/img/fruitvote/blackberry.jpg
new file mode 100644
index 0000000..e097829
--- /dev/null
+++ b/html/public/img/fruitvote/blackberry.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/blueberry.jpg b/html/public/img/fruitvote/blueberry.jpg
new file mode 100644
index 0000000..9794493
--- /dev/null
+++ b/html/public/img/fruitvote/blueberry.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/cherry.jpg b/html/public/img/fruitvote/cherry.jpg
new file mode 100644
index 0000000..277c17c
--- /dev/null
+++ b/html/public/img/fruitvote/cherry.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/coconut.jpg b/html/public/img/fruitvote/coconut.jpg
new file mode 100644
index 0000000..76044f4
--- /dev/null
+++ b/html/public/img/fruitvote/coconut.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/cranberry.jpg b/html/public/img/fruitvote/cranberry.jpg
new file mode 100644
index 0000000..fe8513a
--- /dev/null
+++ b/html/public/img/fruitvote/cranberry.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/dock-april.png b/html/public/img/fruitvote/dock-april.png
new file mode 100644
index 0000000..1cd82d2
--- /dev/null
+++ b/html/public/img/fruitvote/dock-april.png
Binary files differ
diff --git a/html/public/img/fruitvote/fig.jpg b/html/public/img/fruitvote/fig.jpg
new file mode 100644
index 0000000..643a49b
--- /dev/null
+++ b/html/public/img/fruitvote/fig.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/grape.jpg b/html/public/img/fruitvote/grape.jpg
new file mode 100644
index 0000000..ce341d4
--- /dev/null
+++ b/html/public/img/fruitvote/grape.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/guava.jpg b/html/public/img/fruitvote/guava.jpg
new file mode 100644
index 0000000..953ed0b
--- /dev/null
+++ b/html/public/img/fruitvote/guava.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/honeydew.jpeg b/html/public/img/fruitvote/honeydew.jpeg
new file mode 100644
index 0000000..1e796e5
--- /dev/null
+++ b/html/public/img/fruitvote/honeydew.jpeg
Binary files differ
diff --git a/html/public/img/fruitvote/kiwi.jpg b/html/public/img/fruitvote/kiwi.jpg
new file mode 100644
index 0000000..6b048d5
--- /dev/null
+++ b/html/public/img/fruitvote/kiwi.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/lemon.jpg b/html/public/img/fruitvote/lemon.jpg
new file mode 100644
index 0000000..9623514
--- /dev/null
+++ b/html/public/img/fruitvote/lemon.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/lime.jpg b/html/public/img/fruitvote/lime.jpg
new file mode 100644
index 0000000..10302fa
--- /dev/null
+++ b/html/public/img/fruitvote/lime.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/mango.jpg b/html/public/img/fruitvote/mango.jpg
new file mode 100644
index 0000000..a9eb35e
--- /dev/null
+++ b/html/public/img/fruitvote/mango.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/melon.jpg b/html/public/img/fruitvote/melon.jpg
new file mode 100644
index 0000000..dc45f27
--- /dev/null
+++ b/html/public/img/fruitvote/melon.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/nectarine.jpg b/html/public/img/fruitvote/nectarine.jpg
new file mode 100644
index 0000000..24fddbe
--- /dev/null
+++ b/html/public/img/fruitvote/nectarine.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/orange.jpg b/html/public/img/fruitvote/orange.jpg
new file mode 100644
index 0000000..1bb12a1
--- /dev/null
+++ b/html/public/img/fruitvote/orange.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/peach.jpg b/html/public/img/fruitvote/peach.jpg
new file mode 100644
index 0000000..9690ca6
--- /dev/null
+++ b/html/public/img/fruitvote/peach.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/pear.jpg b/html/public/img/fruitvote/pear.jpg
new file mode 100644
index 0000000..22c2a01
--- /dev/null
+++ b/html/public/img/fruitvote/pear.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/persimmon.jpg b/html/public/img/fruitvote/persimmon.jpg
new file mode 100644
index 0000000..6af3afe
--- /dev/null
+++ b/html/public/img/fruitvote/persimmon.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/pineapple.jpg b/html/public/img/fruitvote/pineapple.jpg
new file mode 100644
index 0000000..bbeeeb2
--- /dev/null
+++ b/html/public/img/fruitvote/pineapple.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/plum.jpg b/html/public/img/fruitvote/plum.jpg
new file mode 100644
index 0000000..61a8893
--- /dev/null
+++ b/html/public/img/fruitvote/plum.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/pomegranate.jpg b/html/public/img/fruitvote/pomegranate.jpg
new file mode 100644
index 0000000..5be6859
--- /dev/null
+++ b/html/public/img/fruitvote/pomegranate.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/pumpkin.jpg b/html/public/img/fruitvote/pumpkin.jpg
new file mode 100644
index 0000000..8a20485
--- /dev/null
+++ b/html/public/img/fruitvote/pumpkin.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/raspberry.jpg b/html/public/img/fruitvote/raspberry.jpg
new file mode 100644
index 0000000..07a33b2
--- /dev/null
+++ b/html/public/img/fruitvote/raspberry.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/strawberry.jpg b/html/public/img/fruitvote/strawberry.jpg
new file mode 100644
index 0000000..22ee16b
--- /dev/null
+++ b/html/public/img/fruitvote/strawberry.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/tomato.jpg b/html/public/img/fruitvote/tomato.jpg
new file mode 100644
index 0000000..846fb08
--- /dev/null
+++ b/html/public/img/fruitvote/tomato.jpg
Binary files differ
diff --git a/html/public/img/fruitvote/versus.gif b/html/public/img/fruitvote/versus.gif
new file mode 100644
index 0000000..6d45ee6
--- /dev/null
+++ b/html/public/img/fruitvote/versus.gif
Binary files differ
diff --git a/html/public/img/fruitvote/watermelon.jpg b/html/public/img/fruitvote/watermelon.jpg
new file mode 100644
index 0000000..1db28d9
--- /dev/null
+++ b/html/public/img/fruitvote/watermelon.jpg
Binary files differ