var express = require('express') var bodyParser = require('body-parser') var fs=require('fs') var hashindex=require('hash-index') var app = express() var Candidates=[ "Chris Christie", "Donald Trump", "Mike Pence", "Nikki Haley", "Ron DeSantis", "Tim Scott", "Vivek Ramaswamy", ]; function CanId(c) { let w=c.split(" "); let lastname=w[w.length-1].toLowerCase(); let id=lastname.split("-"); let rval=id[id.length-1]; return(rval); } // Set up data structures for Range Votes and Plur Votes var RangeVotes=new Map(); var RangePower=new Map(); var RangeResult=new Map(); var PlurVotes=new Map(); var PlurResult=new Map(); var PlurCount=0; for (let c of Candidates) { let k=CanId(c); let v=RangePower.get(k); if (typeof(v)!='number' || v==NaN || v==Infinity) RangePower.set(k,0); v=RangeResult.get(k); if (typeof(v)!='number' || v==NaN || v==Infinity) RangeResult.set(k,0); v=PlurResult.get(k); if (typeof(v)!='number' || v==NaN || v==Infinity) PlurResult.set(k,0); } // Construct the static page for range voting var RangeHTML=""; for (let c of Candidates) { RangeHTML=RangeHTML+' '+ ' '+c+'No Opinion\n'; } var TemplateHTML=fs.readFileSync("rangevote.html").toString(); var TemplateSearch=""; var TemplateIndex=TemplateHTML.indexOf(TemplateSearch); RangeHTML=TemplateHTML.substr(0,TemplateIndex)+RangeHTML+TemplateHTML.substr(TemplateIndex+TemplateSearch.length,1000000); // Construct the static page for Plurality Voting var PlurHTML=""; for (let c of Candidates) { PlurHTML=PlurHTML+' '+ ' '+c+'\n'; } TemplateHTML=fs.readFileSync("plurvote.html").toString(); TemplateSearch=""; TemplateIndex=TemplateHTML.indexOf(TemplateSearch); PlurHTML=TemplateHTML.substr(0,TemplateIndex)+PlurHTML+TemplateHTML.substr(TemplateIndex+TemplateSearch.length,1000000); // create application/json parser var jsonParser = bodyParser.json() // create application/x-www-form-urlencoded parser var urlencodedParser = bodyParser.urlencoded({ extended: false }) app.get('/', (req, res) => { let kind=hashindex(req.socket.remoteAddress+"salt",2); if (kind==0) res.send(RangeHTML); else res.send(PlurHTML); }) function lerp(a,b,c,d,e) { if (ac) a=c; let rval=d+(a-b)*(e-d)/(c-b); return(rval); } function PlurVote(ip,NewChoice) { let OldChoice=PlurResult.get(ip); if (typeof(OldChoice)=='string') { PlurResult.set(OldChoice,PlurResult.get(OldChoice)-1); PlurCount=PlurCount-1; } if (!NewChoice) return; NewChoice=CanId(NewChoice); if (typeof(NewChoice)=='string') { PlurResult.set(NewChoice,PlurResult.get(NewChoice)+1); PlurCount=PlurCount+1; } } function AddToRangeResult(vote,mult=1) { for (let[key,val] of vote) if (key) if (val>=0) { RangeResult.set(key,RangeResult.get(key)+val*mult); RangePower.set(key,RangePower.get(key)+mult); } } function RangeVote(ip,entries) { console.log('IP: '+ip); let r0=null,r1=null; for (let [key,val] of entries) if (typeof(key)=="string" && val>=0) { if (r0==null) { r0=val; r1=val; } r0=Math.min(r0,val); r1=Math.max(r1,val); } if (r1<=r0) return; let NewVote=new Map() for (let [key,val] of entries) if (typeof(key)=="string") { let id=CanId(key); let norm=Math.round(lerp(val,r0,r1,0,100)); if (val>=0) NewVote.set(id,norm); } let OldVote=RangeVotes.get(ip); // if (OldVote) AddToRangeResult(OldVote,-1); RangeVotes.set(ip,NewVote); AddToRangeResult(NewVote,1); } // POST /login gets urlencoded bodies app.post('/range_vote', urlencodedParser, function (req, res) { RangeVote(req.socket.remoteAddress,Object.entries(req.body)); let str="Results from "+RangeVotes.size+" Voters:
"; for (let c of Candidates) { let key=CanId(c); if (RangePower.get(key)>0) str=str+c+': '+Math.round(RangeResult.get(key)/RangePower.get(key))+'%
'; } res.send(str); }) app.post('/plur_vote', urlencodedParser, function (req, res) { PlurVote(req.socket.remoteAddress,req.body.pick); let str="Results:
"; for (let c of Candidates) { let key=CanId(c); if (PlurResult.get(key)>0) str=str+c+': '+Math.round(100.0*PlurResult.get(key)/PlurCount)+'%
'; } res.send(str); }) app.listen(3000,function(req,res) { console.log("Listening for connections"); })