* Use embedded assets for templates
* All Critical functions are working
This commit is contained in:
Brian Buller 2017-07-08 21:51:43 -05:00
parent 02dbfc39ca
commit 262c855643
8 changed files with 293 additions and 194 deletions

View File

@ -46,6 +46,7 @@ func handleAdmin(w http.ResponseWriter, req *http.Request) {
case "mode": case "mode":
handleAdminSetMode(w, req, page) handleAdminSetMode(w, req, page)
default: default:
page.TemplateData = getCondorcetResult()
page.show("admin-main.html", w) page.show("admin-main.html", w)
} }
} }

View File

@ -1,84 +1,110 @@
package main package main
import ( import (
"fmt" "errors"
"net/http" "net/http"
"time" "time"
"github.com/gorilla/mux" "github.com/gorilla/mux"
) )
// getCondorcetResult returns the ranking of teams based on the condorcet method
// https://en.wikipedia.org/wiki/Condorcet_method
func getCondorcetResult() []Team { func getCondorcetResult() []Team {
type teamPair struct {
winner *Team
loser *Team
majority float32
}
var allPairs []teamPair
var ret []Team var ret []Team
type rankedTeam struct { for i := 0; i < len(site.Teams); i++ {
tm *Team for j := i + 1; j < len(site.Teams); j++ {
wins map[string]int // For each pairing find a winner
losses map[string]int winner, pct, _ := findWinnerBetweenTeams(&site.Teams[i], &site.Teams[j])
if winner != nil {
newPair := new(teamPair)
newPair.winner = winner
if winner.UUID == site.Teams[i].UUID {
newPair.loser = &site.Teams[j]
} else {
newPair.loser = &site.Teams[i]
} }
// Build our Ranked Teams slice newPair.majority = pct
allRanks := make(map[string]rankedTeam) allPairs = append(allPairs, *newPair)
}
}
}
teamWins := make(map[string]int)
for i := range site.Teams { for i := range site.Teams {
rt := new(rankedTeam) teamWins[site.Teams[i].UUID] = 0
rt.wins = make(map[string]int)
rt.losses = make(map[string]int)
rt.tm = &site.Teams[i]
for j := range site.Teams {
if site.Teams[i].UUID != site.Teams[j].UUID {
rt.wins[site.Teams[j].UUID] = 0
rt.losses[site.Teams[j].UUID] = 0
} }
for i := range allPairs {
teamWins[allPairs[i].winner.UUID]++
} }
allRanks[site.Teams[i].UUID] = *rt for len(teamWins) > 0 { //len(ret) <= len(site.Teams) {
} topWins := 0
/* var topTeam string
Go through all votes, for each choice (ct): for k, v := range teamWins {
* Go through all teams (tm) // If this team is already in ret, carry on
* if tm was processed earlier, do nothing if uuidIsInTeamSlice(k, ret) {
* otherwise mark a win for ct against tm, and a loss for tm against cm
*/
// Now go through all of the votes and figure wins/losses for each team
for _, vt := range site.Votes {
for i := 0; i < len(vt.Choices); i++ {
var p []string
for j := i; j < len(vt.Choices); j++ {
// vt.Choices[i] wins against vt.Choices[j]
p = append(p, vt.Choices[j].Team)
allRanks[vt.Choices[i].Team].wins[vt.Choices[j].Team]++
allRanks[vt.Choices[j].Team].losses[vt.Choices[i].Team]++
}
// Now go through site.Teams for every team that isn't vt.Choices[i]
// and isn't in 'p', mark it as a loss for the unused team
for j := range site.Teams {
var isUsed bool
if site.Teams[j].UUID == vt.Choices[i].Team {
continue continue
} }
for k := range p { // If this is the last key in teamWins, just add it
if site.Teams[j].UUID == p[k] { if len(teamWins) == 1 || v > topWins {
isUsed = true topWins = v
topTeam = k
} }
} }
if !isUsed { // Remove topTeam from map
allRanks[vt.Choices[i].Team].wins[site.Teams[j].UUID]++ delete(teamWins, topTeam)
allRanks[site.Teams[j].UUID].losses[vt.Choices[i].Team]++ // Now add topTeam to ret
} addTeam := site.getTeamByUUID(topTeam)
} if addTeam != nil {
} ret = append(ret, *addTeam)
} } else {
for _, v := range allRanks { break
fmt.Println("\n" + v.tm.UUID)
fmt.Println(" Wins:")
for k, v := range v.wins {
fmt.Print(" ", k, ":", v, "\n")
}
fmt.Println(" Losses:")
for k, v := range v.losses {
fmt.Print(" ", k, ":", v, "\n")
} }
} }
return ret return ret
} }
// This is a helper function for calculating results
func uuidIsInTeamSlice(uuid string, sl []Team) bool {
for _, v := range sl {
if v.UUID == uuid {
return true
}
}
return false
}
// findWinnerBetweenTeams returns the team that got the most votes
// and the percentage of votes they received
// or an error if a winner couldn't be determined.
func findWinnerBetweenTeams(tm1, tm2 *Team) (*Team, float32, error) {
// tally gets incremented for a tm1 win, decremented for a tm2 win
var tm1votes, tm2votes float32
for _, v := range site.Votes {
for _, chc := range v.Choices {
if chc.Team == tm1.UUID {
tm1votes++
break
} else if chc.Team == tm2.UUID {
tm2votes++
break
}
}
}
ttlVotes := tm1votes + tm2votes
if tm1votes > tm2votes {
return tm1, 100 * (tm1votes / ttlVotes), nil
} else if tm1votes < tm2votes {
return tm2, 100 * (tm2votes / ttlVotes), nil
}
return nil, 50, errors.New("Unable to determine a winner")
}
func getInstantRunoffResult() []Team { func getInstantRunoffResult() []Team {
var ret []Team var ret []Team
return ret return ret
@ -95,6 +121,7 @@ func handleAdminVotes(w http.ResponseWriter, req *http.Request, page *pageData)
} }
type votePageData struct { type votePageData struct {
AllVotes []vpdVote AllVotes []vpdVote
Results []Team
} }
vpd := new(votePageData) vpd := new(votePageData)
for i := range site.Votes { for i := range site.Votes {
@ -111,8 +138,8 @@ func handleAdminVotes(w http.ResponseWriter, req *http.Request, page *pageData)
} }
vpd.AllVotes = append(vpd.AllVotes, *v) vpd.AllVotes = append(vpd.AllVotes, *v)
} }
vpd.Results = getCondorcetResult()
page.TemplateData = vpd page.TemplateData = vpd
_ = getCondorcetResult()
switch vars["function"] { switch vars["function"] {
default: default:

162
assets.go
View File

@ -202,28 +202,28 @@ Y8Pj6dAeZ3gBzLZbhMnSW8r0f78+9y+zlDVuQ3ZNXD8zD+/mGzZjDfK53gEAAP//D/6XxHkAAAA=
"/assets/css/gjvote.css": { "/assets/css/gjvote.css": {
local: "assets/css/gjvote.css", local: "assets/css/gjvote.css",
size: 3763, size: 3784,
modtime: 1499342234, modtime: 1499536516,
compressed: ` compressed: `
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
/PlgHfrDCcyf/v8w/goAAP//zWrQALMOAAA= 6XJv/hOXPx+sQ384ofnT/w/jrwAAAP//9ey+zsgOAAA=
`, `,
}, },
@ -12055,14 +12055,15 @@ vh6n2F5nK55X3h/q0K8AAAD//5F9arwmAwAA
"/templates/admin-main.html": { "/templates/admin-main.html": {
local: "templates/admin-main.html", local: "templates/admin-main.html",
size: 836, size: 1024,
modtime: 1498141850, modtime: 1499533906,
compressed: ` compressed: `
H4sIAAAAAAAA/6yRzWrrMBCF9/cpBm2yspWQrW24q64Khf6tFWlsD5U1qSQnFON3L4pdSJvQhpDVAY/1 H4sIAAAAAAAA/6ySX0vzMBTG799PcSiD3bxrNnYnbUEUvFJEp15n7VkXzJ+ZnHZI6HeXLHNUN3WMXT2l
6dOcwtAOtFUhlEKzi+iiqP4BpO8pAYp2XT30G0sa7tlgIdv1PNj0MbIDdtqSfivFnpzhfW5Zq0js8tZj p/n1x3OSVaKFUnLn8qQ0mlBTUvwDCO9DAmTLaXHfzKUo4dZUmLHldDuYN0RGg9GlFOVrnqyFrsw6labk
XS6kMh052bFBuVyIr8u2vcdsImSRm8ZiVpMPEY4GMAxANeA75JNBEoAljOPx6a2nTvmPYQB0BsZRVK+K JIxOlxYX+ZDxSgnNlKmQjYfJ589WjcVRJIzI1LXE0UJYR9AbgPcgFoBvkEaDIABj6Lr+6ZUVitt37wF1
IrmmkNMfV+uuftW16hLb1Z+2L/xTtpDz9r+38D+ZwSPqpBtOizhVFRe+dscRw+KgguH82q6HR1Rdgj+l BV2XFC9ckNB1xuIXJ+tOftWV/BjbyZ+2z+a7bMa27f9I3NvQVWMtaoIHdI0k19uSkfHBe7Bc1wgD8R8G
vDW8Ud3B/C7lreF9QJ/gzynPFDTHZwAAAP//9zFOd0QDAAA= LVzkkM5QrSQnvObEI3VzRIrCexi06R1XCF2XMSl2kKgd2SzC+7678Ve/y9AqPGIZqnb7l2i/5uTITbWG
0A03NaI7vPLT4YRcBfgs5LnhNVcb85uQ54Y3Dm2AP4U8cLm28REAAP//GzmHcgAEAAA=
`, `,
}, },
@ -12114,14 +12115,15 @@ GXvy3PwYKZ6fyZHhEKvyv82bVJmo3N8XAPZYvcMb01mHkXzjyL9wpz4sHABCwHMXXoE7Wthy9p3rhfjJ
"/templates/admin-votes.html": { "/templates/admin-votes.html": {
local: "templates/admin-votes.html", local: "templates/admin-votes.html",
size: 591, size: 747,
modtime: 1499344306, modtime: 1499532926,
compressed: ` compressed: `
H4sIAAAAAAAA/2xSwW7CMAy98xVW1CO0h92mtNI0Llx22NDuJjEQLU2qxKs0Vf33KW0hG3B7tl/8nu1I H4sIAAAAAAAA/4RSTYvqMBTd91dcistnA77dIy08dONmFo7MPjZXGyZNSnIVhtL/PiRNrVOF2d3vc3JO
xoMlMLoWvWeKmykWoCzGWIvow0zovgNtbuHm4IOmQBoUOaYgmhWA5DOhTijhMIMp3exNS5Gx7WTF57+F eLOptlfn0BAc0F81ec6aTZVxq6us78EJc0FYqT+wusG/Eoojtp0WhDtBokgrMAwZANeq6ntY3Yo30SIM
V2vIMey2t4V3dF/GnWLOy2rumTKLjuSD1z9zeRggoDsRFGYNRQ/PNZR7ajuLTFtkLF+s/UyDwjjeW9TN A2daxSNoZBjhLBzlJE4aQckyv1lCv455DrUW3pe5t24c6K4O18twfbJOokMJNRpCl1cBmBoUMkQhdmMQ
MEDRl1ejMI6yYn3PmB3v9APCArMTlayoyUt6efZGZf2FWqi+fMOWYBzXuQE5nXlZ57KD/xxZXfcg+eg9 y9VRtehJtB1n1Dw2tlqFN+93y8ZBmE9lLn6uczbeDJWEw+lk5dfY/lWk/1p/hIeOKi0oyiTZnWjUjeTz
P7iBvhzW0pEFKG9jh64WTyLNZclB+WGYysuKYO8ZLUzhvb6sFh1ZTf+hWf0GAAD//xnIVWJPAgAA xMh4L18MpBAgujYlM7E6MKsjtXCosaqe6aTNZF69cO/hWHLxvsFmsJnQJNbPDc7ugnE6W0svzJLTD9B4
phxqq30nTJn/zQMxjQaKd0VYTFrC0ZLQENNnfM4SDmfx41TZdwAAAP//q70AIOsCAAA=
`, `,
}, },
@ -12176,50 +12178,56 @@ AAD//1puW/YhAwAA
"/templates/public-voting.html": { "/templates/public-voting.html": {
local: "templates/public-voting.html", local: "templates/public-voting.html",
size: 9253, size: 10440,
modtime: 1499346016, modtime: 1499536431,
compressed: ` compressed: `
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
`, `,
}, },

View File

@ -115,6 +115,7 @@ img.thumbnail {
display: block; display: block;
height: 120px; height: 120px;
background-color: #EEE; background-color: #EEE;
padding-top: 20px;
} }
.padding { .padding {

View File

@ -37,6 +37,15 @@ type siteData struct {
Votes []Vote Votes []Vote
} }
func (s *siteData) getTeamByUUID(uuid string) *Team {
for i := range s.Teams {
if s.Teams[i].UUID == uuid {
return &s.Teams[i]
}
}
return nil
}
// pageData is stuff that changes per request // pageData is stuff that changes per request
type pageData struct { type pageData struct {
Site *siteData Site *siteData

View File

@ -4,6 +4,16 @@
<button onclick="window.location.href='/admin/mode/0'" class="pure-button-toggle-first pure-button {{ if eq .PublicMode 0 }}pure-button-primary{{ end }}">Waiting</button> <button onclick="window.location.href='/admin/mode/0'" class="pure-button-toggle-first pure-button {{ if eq .PublicMode 0 }}pure-button-primary{{ end }}">Waiting</button>
<button onclick="window.location.href='/admin/mode/1'" class="pure-button-toggle-last pure-button {{ if eq .PublicMode 1 }}pure-button-primary{{ end }}">Voting</button> <button onclick="window.location.href='/admin/mode/1'" class="pure-button-toggle-last pure-button {{ if eq .PublicMode 1 }}pure-button-primary{{ end }}">Voting</button>
</div> </div>
{{ if eq .PublicMode 1 }}
<div>
<h3>Current Results</h3>
<ol>
{{ range $i, $v := .TemplateData }}
<li>{{ $v.Name }}</li>
{{ end }}
</ol>
</div>
{{ end }}
<div> <div>
<h3>Admin Sections</h3> <h3>Admin Sections</h3>
<button class="pure-button" onclick="window.location.href='/admin/votes'">Votes</button> <button class="pure-button" onclick="window.location.href='/admin/votes'">Votes</button>

View File

@ -1,3 +1,9 @@
<h2>Current Results</h2>
<ol>
{{ range $i, $v := .TemplateData.Results }}
<li>{{ $v.Name }}</li>
{{ end }}
</ol>
<table id="votes-table" class="sortable pure-table pure-table-bordered center"> <table id="votes-table" class="sortable pure-table pure-table-bordered center">
<thead> <thead>
<tr> <tr>

View File

@ -1,10 +1,10 @@
{{ if not .TemplateData.Teams }} {{ if not .TemplateData.Teams }}
<div>No games have been created</div> <div>No games have been created</div>
{{ else }} {{ else }}
<div class="content"> <div class="content">
Rank one or more games from your favorite to least favorite. Rank one or more games from your favorite to least favorite.
</div> </div>
<div class="content"> <div class="content">
<h2>Your Choices</h2> <h2>Your Choices</h2>
<table id="ranked-table" class="pure-table pure-table-bordered center"> <table id="ranked-table" class="pure-table pure-table-bordered center">
<thead> <thead>
@ -19,8 +19,8 @@ Rank one or more games from your favorite to least favorite.
<tbody> <tbody>
</tbody> </tbody>
</table> </table>
</div> </div>
<div class="content"> <div class="content">
<h2>Unranked Games</h2> <h2>Unranked Games</h2>
<table id="unranked-table" class="pure-table pure-table-bordered center"> <table id="unranked-table" class="pure-table pure-table-bordered center">
<thead> <thead>
@ -41,23 +41,60 @@ Rank one or more games from your favorite to least favorite.
{{ if not $v.Game.Screenshots }} {{ if not $v.Game.Screenshots }}
<i class="fa fa-image"></i> (No Screenshots) <i class="fa fa-image"></i> (No Screenshots)
{{ else }} {{ else }}
<a class="primary" tabindex="-1" href="javascript:showScreenshots({{$v.UUID}});"><i class="fa fa-image"></i> ({{ len $v.Game.Screenshots }})</a> <a class="primary" tabindex="-1" href="javascript:showScreenshots('{{$v.UUID}}');"><i class="fa fa-image"></i> ({{ len $v.Game.Screenshots }}) Click to View</a>
{{ end }} {{ end }}
</td> </td>
</tr> </tr>
{{ end }} {{ end }}
</tbody> </tbody>
</table> </table>
</div> </div>
<div class="content half"> <div class="content half">
<form action="/vote"> <form action="/vote">
<input id="uservote" type="hidden" name="uservote" value="" /> <input id="uservote" type="hidden" name="uservote" value="" />
<input id="timestamp" type="hidden" name="timestamp" value="{{.TemplateData.Timestamp}}" /> <input id="timestamp" type="hidden" name="timestamp" value="{{.TemplateData.Timestamp}}" />
<button class="pure-button pure-button-primary space-vertical pull-right" type="submit">Submit Vote!</button> <button class="pure-button pure-button-primary space-vertical pull-right" type="submit">Submit Vote!</button>
</form> </form>
</div> </div>
{{ range $i, $v := .TemplateData.Teams }}
<div class="pure-control-group" id="screenshots-{{ $v.UUID }}" style="display:none;">
<h3>{{ $v.Game.Name }} by {{ $v.Name }}</h3>
<label class="control-label">Click to view original size</label>
<div class="center-all horizontal-scroll thumbnail-container" id="thumbnail-container">
{{ range $imgi, $imgv := $v.Game.Screenshots }}
<a href="javascript:embiggenScreenshot(this.getElementsByTagName('img')[0]);">
<img data-teamid="{{ $v.UUID }}" data-ssid="{{ $imgv.UUID }}" class="thumbnail" alt="{{ $imgv.Description }}" src="data:image/png;base64,{{ $imgv.Image }}" />
</a>
{{ end }}
</div>
</div>
{{ end }}
{{ end }} {{ end }}
<script> <script>
var teamNames = { };
{{ range $i, $v := .TemplateData.Teams }}
teamNames[{{$v.UUID}}] = { "team-name": "{{$v.Name}}", "game-name": "{{$v.Game.Name}}" };
{{ end }}
function showScreenshots(tmuuid) {
var screenshots = document.getElementById('screenshots-'+tmuuid).cloneNode(true);
screenshots.style.display='';
showModal({
title: 'Screenshots',
subtitle: teamNames[tmuuid].game-name,
bodyNode: screenshots,
buttons: [{
title: 'Done',
position: 'right',
click: hideModal
}]
});
}
function embiggenScreenshot(img) {
}
function updateView() { function updateView() {
updateButtonStates(); updateButtonStates();