var express = require('express') var bodyParser = require('body-parser') var fs=require('fs') var hashindex=require('hash-index') var fc=require("./filechunker.js"); var app = express() var TemplateVoteRange=new fc("./rangevote.html"); var TemplateVotePlur =new fc("./plurvote.html"); 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 Experiment; fs.readFile('./rangevote.json', 'utf8', (err, data) => { if (err) { Experiment={}; Experiment.RangeVotes=new Map(); Experiment.RangePower=new Map(); Experiment.RangeResult=new Map(); Experiment.PlurVotes=new Map(); Experiment.PlurResult=new Map(); Experiment.PlurCount=0; } else Experiment=JSON.parse(data,MapReviver); for (let c of Candidates) { let k=CanId(c); let v=Experiment.RangePower.get(k); if (typeof(v)!='number' || v==NaN || v==Infinity) Experiment.RangePower.set(k,0); v=Experiment.RangeResult.get(k); if (typeof(v)!='number' || v==NaN || v==Infinity) Experiment.RangeResult.set(k,0); v=Experiment.PlurResult.get(k); if (typeof(v)!='number' || v==NaN || v==Infinity) Experiment.PlurResult.set(k,0); } }) function LogErr(err) { if (err) console.log(err); } function MapReplacer(key, value) { if(value instanceof Map) { return { dataType: 'Map', value: Array.from(value.entries()), // or with spread: value: [...value] }; } else { return value; } } function MapReviver(key, value) { if(typeof value === 'object' && value !== null) { if (value.dataType === 'Map') { return new Map(value.value); } } return value; } function Persist() { var str=JSON.stringify(Experiment,MapReplacer); fs.writeFile("./rangevote.json",str,LogErr); } // Construct the static page for range voting var RangeHTML=""; for (let c of Candidates) { RangeHTML=RangeHTML+' '+ ' '+c+'No Opinion\n'; } RangeHTML=TemplateVoteRange.Chunks[0]+RangeHTML+TemplateVoteRange.Chunks[1]; // Construct the static page for Plurality Voting var PlurHTML=""; for (let c of Candidates) { PlurHTML=PlurHTML+' '+ ' '+c+'\n'; } PlurHTML=TemplateVotePlur.Chunks[0]+PlurHTML+TemplateVotePlur.Chunks[1]; // 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+"saltA",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=Experiment.PlurVotes.get(ip); if (typeof(OldChoice)=='string') { Experiment.PlurResult.set(OldChoice,Experiment.PlurResult.get(OldChoice)-1); Experiment.PlurCount-=1; } if (!NewChoice) return; NewChoice=CanId(NewChoice); if (typeof(NewChoice)=='string') { Experiment.PlurResult.set(NewChoice,Experiment.PlurResult.get(NewChoice)+1); Experiment.PlurCount+=1; } Experiment.PlurVotes.set(ip,NewChoice); console.log(Experiment); } function AddToRangeResult(vote,mult=1) { for (let[key,val] of vote) if (key) if (val>=0) { Experiment.RangeResult.set(key,Experiment.RangeResult.get(key)+val*mult); Experiment.RangePower.set(key,Experiment.RangePower.get(key)+mult); } } function RangeVote(ip,entries) { 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=Experiment.RangeVotes.get(ip); if (OldVote) AddToRangeResult(OldVote,-1); Experiment.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 "+Experiment.RangeVotes.size+" Voters:
"; for (let c of Candidates) { let key=CanId(c); if (Experiment.RangePower.get(key)>0) str=str+c+': '+Math.round(Experiment.RangeResult.get(key)/Experiment.RangePower.get(key))+'% ('+Experiment.RangePower.get(key)+' Voters)
'; } Persist(); res.send(str); }) app.post('/plur_vote', urlencodedParser, function (req, res) { PlurVote(req.socket.remoteAddress,req.body.pick); let str="Results from "+Experiment.PlurVotes.size+" Voters:
"; for (let c of Candidates) { let key=CanId(c); if (Experiment.PlurResult.get(key)>0) str=str+c+': '+Math.round(100.0*Experiment.PlurResult.get(key)/Experiment.PlurCount)+'%
'; } Persist(); res.send(str); }) app.listen(3000,function(req,res) { console.log("Listening for connections"); })