2023-09-28 14:57:13 -04:00
|
|
|
var express = require('express')
|
|
|
|
|
var bodyParser = require('body-parser')
|
|
|
|
|
var fs=require('fs')
|
2023-09-29 12:42:58 -04:00
|
|
|
var hashindex=require('hash-index')
|
2023-10-15 22:14:32 -04:00
|
|
|
var fc=require("./filechunker.js");
|
2023-09-28 14:57:13 -04:00
|
|
|
|
|
|
|
|
var app = express()
|
|
|
|
|
|
2023-10-18 08:52:39 -04:00
|
|
|
var TemplateVoteRange=new fc("./rangevote.html");
|
|
|
|
|
var TemplateVotePlur =new fc("./plurvote.html");
|
|
|
|
|
|
2023-09-29 12:42:58 -04:00
|
|
|
var Candidates=[
|
|
|
|
|
"Chris Christie",
|
|
|
|
|
"Donald Trump",
|
|
|
|
|
"Mike Pence",
|
|
|
|
|
"Nikki Haley",
|
|
|
|
|
"Ron DeSantis",
|
|
|
|
|
"Tim Scott",
|
|
|
|
|
"Vivek Ramaswamy",
|
|
|
|
|
];
|
2023-09-28 14:57:13 -04:00
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-28 16:36:00 -04:00
|
|
|
|
|
|
|
|
|
2023-09-28 14:57:13 -04:00
|
|
|
// Set up data structures for Range Votes and Plur Votes
|
2023-10-03 08:51:42 -04:00
|
|
|
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()
|
2023-09-28 14:57:13 -04:00
|
|
|
{
|
2023-10-03 08:51:42 -04:00
|
|
|
var str=JSON.stringify(Experiment,MapReplacer);
|
|
|
|
|
fs.writeFile("./rangevote.json",str,LogErr);
|
2023-09-28 14:57:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Construct the static page for range voting
|
2023-09-28 16:36:00 -04:00
|
|
|
var RangeHTML="";
|
2023-09-28 14:57:13 -04:00
|
|
|
for (let c of Candidates)
|
|
|
|
|
{
|
2023-09-28 16:36:00 -04:00
|
|
|
RangeHTML=RangeHTML+' <tr>'+
|
2023-09-29 12:42:58 -04:00
|
|
|
' <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';
|
2023-09-28 14:57:13 -04:00
|
|
|
}
|
2023-10-18 08:52:39 -04:00
|
|
|
RangeHTML=TemplateVoteRange.Chunks[0]+RangeHTML+TemplateVoteRange.Chunks[1];
|
|
|
|
|
|
2023-09-28 16:36:00 -04:00
|
|
|
|
|
|
|
|
// 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';
|
|
|
|
|
}
|
2023-10-18 08:52:39 -04:00
|
|
|
PlurHTML=TemplateVotePlur.Chunks[0]+PlurHTML+TemplateVotePlur.Chunks[1];
|
2023-09-28 14:57:13 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
// 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) => {
|
2023-10-02 00:19:45 -04:00
|
|
|
let kind=hashindex(req.socket.remoteAddress+"saltA",2);
|
2023-09-29 12:42:58 -04:00
|
|
|
if (kind==0) res.send(RangeHTML);
|
|
|
|
|
else res.send(PlurHTML);
|
2023-09-28 14:57:13 -04:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-02 00:19:45 -04:00
|
|
|
|
2023-09-28 14:57:13 -04:00
|
|
|
function PlurVote(ip,NewChoice)
|
|
|
|
|
{
|
2023-10-02 00:19:45 -04:00
|
|
|
let OldChoice=Experiment.PlurVotes.get(ip);
|
|
|
|
|
if (typeof(OldChoice)=='string') { Experiment.PlurResult.set(OldChoice,Experiment.PlurResult.get(OldChoice)-1); Experiment.PlurCount-=1; }
|
2023-09-28 16:36:00 -04:00
|
|
|
if (!NewChoice) return;
|
|
|
|
|
NewChoice=CanId(NewChoice);
|
2023-10-02 00:19:45 -04:00
|
|
|
if (typeof(NewChoice)=='string') { Experiment.PlurResult.set(NewChoice,Experiment.PlurResult.get(NewChoice)+1); Experiment.PlurCount+=1; }
|
|
|
|
|
Experiment.PlurVotes.set(ip,NewChoice);
|
|
|
|
|
console.log(Experiment);
|
2023-09-28 14:57:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function AddToRangeResult(vote,mult=1)
|
|
|
|
|
{
|
|
|
|
|
for (let[key,val] of vote) if (key) if (val>=0)
|
|
|
|
|
{
|
2023-10-02 00:19:45 -04:00
|
|
|
Experiment.RangeResult.set(key,Experiment.RangeResult.get(key)+val*mult);
|
|
|
|
|
Experiment.RangePower.set(key,Experiment.RangePower.get(key)+mult);
|
2023-09-28 14:57:13 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2023-10-03 08:51:42 -04:00
|
|
|
|
|
|
|
|
|
2023-09-28 14:57:13 -04:00
|
|
|
function RangeVote(ip,entries)
|
|
|
|
|
{
|
|
|
|
|
let r0=null,r1=null;
|
|
|
|
|
for (let [key,val] of entries) if (typeof(key)=="string" && val>=0)
|
|
|
|
|
{
|
2023-09-28 16:36:00 -04:00
|
|
|
if (r0==null) { r0=val; r1=val; }
|
|
|
|
|
r0=Math.min(r0,val);
|
|
|
|
|
r1=Math.max(r1,val);
|
2023-09-28 14:57:13 -04:00
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
|
}
|
2023-10-02 00:19:45 -04:00
|
|
|
let OldVote=Experiment.RangeVotes.get(ip);
|
|
|
|
|
if (OldVote) AddToRangeResult(OldVote,-1);
|
|
|
|
|
Experiment.RangeVotes.set(ip,NewVote);
|
2023-09-28 14:57:13 -04:00
|
|
|
AddToRangeResult(NewVote,1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// POST /login gets urlencoded bodies
|
|
|
|
|
app.post('/range_vote', urlencodedParser, function (req, res) {
|
|
|
|
|
RangeVote(req.socket.remoteAddress,Object.entries(req.body));
|
2023-10-02 00:19:45 -04:00
|
|
|
let str="Results from "+Experiment.RangeVotes.size+" Voters:<br>";
|
2023-09-28 14:57:13 -04:00
|
|
|
for (let c of Candidates)
|
|
|
|
|
{
|
|
|
|
|
let key=CanId(c);
|
2023-10-02 00:19:45 -04:00
|
|
|
if (Experiment.RangePower.get(key)>0) str=str+c+': '+Math.round(Experiment.RangeResult.get(key)/Experiment.RangePower.get(key))+'% ('+Experiment.RangePower.get(key)+' Voters)<br>';
|
2023-09-28 14:57:13 -04:00
|
|
|
}
|
2023-10-03 08:51:42 -04:00
|
|
|
Persist();
|
2023-09-28 14:57:13 -04:00
|
|
|
res.send(str);
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
app.post('/plur_vote', urlencodedParser, function (req, res) {
|
2023-09-28 16:36:00 -04:00
|
|
|
PlurVote(req.socket.remoteAddress,req.body.pick);
|
2023-10-02 00:19:45 -04:00
|
|
|
let str="Results from "+Experiment.PlurVotes.size+" Voters:<br>";
|
2023-09-28 16:36:00 -04:00
|
|
|
for (let c of Candidates)
|
|
|
|
|
{
|
|
|
|
|
let key=CanId(c);
|
2023-10-02 00:19:45 -04:00
|
|
|
if (Experiment.PlurResult.get(key)>0) str=str+c+': '+Math.round(100.0*Experiment.PlurResult.get(key)/Experiment.PlurCount)+'%<br>';
|
2023-09-28 16:36:00 -04:00
|
|
|
}
|
2023-10-03 08:51:42 -04:00
|
|
|
Persist();
|
2023-09-28 16:36:00 -04:00
|
|
|
res.send(str);
|
2023-09-28 14:57:13 -04:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app.listen(3000,function(req,res) { console.log("Listening for connections"); })
|
|
|
|
|
|