Files
rangevote/rangevote.js
2023-09-29 12:42:58 -04:00

167 lines
4.6 KiB
JavaScript

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+' <tr>'+
' <td>'+c+'</td><td><input style="width:95%" type="range" min="-1" max="100" value="-1" id="i-'+CanId(c)+'" name="n-'+CanId(c)+'" /></td><td><span id="o-'+CanId(c)+'">No Opinion</span></td></tr>\n';
}
var TemplateHTML=fs.readFileSync("rangevote.html").toString();
var TemplateSearch="<!-- INJECT0 -->";
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+' <tr>'+
' <td><input type="radio" value="v-'+CanId(c)+'" name="pick" /></td><td>'+c+'</td></tr>\n';
}
TemplateHTML=fs.readFileSync("plurvote.html").toString();
TemplateSearch="<!-- INJECT0 -->";
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 (a<b) a=b;
if (a>c) 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:<br>";
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))+'%<br>';
}
res.send(str);
})
app.post('/plur_vote', urlencodedParser, function (req, res) {
PlurVote(req.socket.remoteAddress,req.body.pick);
let str="Results:<br>";
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)+'%<br>';
}
res.send(str);
})
app.listen(3000,function(req,res) { console.log("Listening for connections"); })