Setup for Simulating in a Browser
-
I want to put code up that can run in a browser to simulate elections. A peripheral question I am struggling with concerns how from the user's viewpoint to set up the volatile memory of the parameter values.
I say volatile memory, because at this point I am not planning to tackle allowing people to register and log in so they could store values on the server. So I want to allow that you could fill in form widgets to set up the values you want for the parameters of the simulation, and those would be there in front of you, so long as you didn't navigate to another website. I want to make an encoding of the parameter values available as text that you could copy out and paste somewhere else to save.
It should be possible to load the volatile memory with a set of preset values from the server; those would be constant for a given version of the server.
It should be possible to clear out the parameter values and start over.
It should be possible to edit the volatile memory of the parameters.
So, a question I have is of whether to provide a way that the user could access several named slots in the volatile memory, each slot to have a complete assignment of values to parameters. The alternative would be to just have a single slot.
-
What do you mean by "volatile memory"? It sounds like you are just speaking of normal JavaScript variables. If you want things to persist, use cookies or localStorage to save and then repopulate them (or save them on the server, of course).
Otherwise it is simply variables, declared with "var" or "let", or as properties of an object, etc. Easy peasy.
-
Hey Jack, if you're interested on working on something like this together, take a look at this little project of mine:
https://elegant-shaw-2cb49a.netlify.app/votevote
I'd like to expand it to be an educational tool that compares a very large number of electoral systems together, but for now it just has these 3.
-
@culi I'd started working on a project, but got distracted by other projects.
-
@culi Love the idea of using color ("RGB distance")in the way you do. Communicates the concept of similarity visually very effectively, and with 3 dimensions.
-
-
-
@jack-waugh we implemented something like this for Pivot - an open source Ranked Pairs web application.
We invented a textual format - BFF. If you were to create something like this today, I would recommend using ABIF instead.
-
@carlschroedl Thanks for the links.
Neither respondent to my question above interpreted it the way I meant it. I kind of wish I had withdrawn the question.
I wrote, "So, a question I have is of whether to provide a way that the user could access several named slots in the volatile memory, each slot to have a complete assignment of values to parameters. The alternative would be to just have a single slot."
My current plan is just to offer a single slot and the text will probably be just a presentation in JSON of a tree format peculiar to the particular simulator.
Here is the data schema for a problem definition in the simulator. It is in a notation peculiar to my technique. Therefore, it would require verbal explanation to be understood by anybody other than me.
const model = u.Model.new( ['entities', 'VotingSystem', 'Election', 'Candidate', 'Faction', 'Slider']
The "entities" in the data model, in the sense of an entity-relationship diagram, are Voting System, Election, Candidate, (voting) Faction, and Slider.
The importance of sliders is that slider controls affect the counts of voters in voting factions. This allows the researcher to try a whole spectrum of different balances in the counts of people holding certain valuations of the possible electoral outcomes. The researcher can try different balances by manipulating the sliders. The simulator will respond as quickly as it can, to, at every moment, the most recent manipulation.
The next section just has to do with how the rest of the code can see and manipulate the problem-definition data model.
, [ 'rootConnected', ['candidates', 'Candidate'], ['factions' , 'Faction' ], ['sliders' , 'Slider' ], ['elections' , 'Election' ], ] , ['rootConnected fixed', ['votingSystems', 'VotingSystem']]
The next section describes the many-to-one relations among the entities.
, ['||---o<', ['VotingSystem', 'votingSystem', 'elections', 'Election']]
The above says there is a one-to-many relationship between voting systems and elections. A given election follows only one voting system, and a voting system may be followed by zero to infinity elections.
, [ '>o---|| $ ||---o<', [ 'Candidate', 'candidate', 'candidateFactions', 'CandidateFaction', 'candidateFactions', 'faction', 'Faction', ], [ 'Election', 'election', 'electionFactions', 'ElectionFaction', 'electionFactions', 'faction', 'Faction', ], [ 'Faction', 'faction', 'factionSliders', 'FactionSlider', 'factionSliders', 'slider', 'Slider', ], ]
The above describes three many-to-many relationships.
There is a many-to-many relationship between candidates and factions, and the join-relation between them is called CandidateFaction. In these joint names, I stuck to alphabetical order. That is why I did not call this one, for example, FactionCandidate.
There is a many-to-many relationship between elections and factions.
There is a many-to-many relationship between factions and sliders.
The next section describes some attributes that some of the entities have.
, [ 'attributes', ['Candidate', [['name', {initValue: ""}]]],
Every candidate has a name.
['Faction', [ ['name', {initValue: ""}], ['constantSizeTerm', {initValue: 1e4}], ]],
Every faction has a name and a constant size term. The size of a faction (meaning the count of voters in it) is calculated as the sum of the constant term with the products of the slider positions with coefficients recorded in the join relation between the factions and the sliders.
['CandidateFaction', [['affinity', {initValue: 0 }]]],
Each faction has an affinity toward each candidate. I normalize these, so you can use whatever scale you want.
['Slider', [ ['tag', {initValue: ""}], ['value', {initValue: 0 }], ]],
Each slider has a "tag", which is basically a name. I used the term "name" for the names of persons and groups, and "tag" for inanimate things like sliders and elections. In either event, the tag or name identifies the individual thing or person.
The value field reflects the slider's current position. Zero is the middle position, -1 is the extreme left, and 1 is the extreme right. These do not necessarily represent political "left" and "right", although you can use one that way if you wish. Sliders happen to appear in a horizontal position, so "left" and "right" describe the positions of their ends relative to one another.
['FactionSlider', [['coefficient', {initValue: 0 }]]],
At the intersection of a faction and a slider, there is a field for the coefficient of the slider value for when the program is recalculating the faction size.
[ 'VotingSystem', [ ['evictAllElections', { initValue: function () { if ('VotingSystem' !== this.class.name) throw Error("Expected a voting system."); Array.from(this.elections).forEach( election => { if('Election' !== election.class.name) throw Error("Expected an election!"); election.delete() }); },}],
Oh, well, I threw some executable code in the middle of the declaration of the schema; that probably wasn't necessary. The code is necessary, but I could have put it somewhere else in the source code, besides in the middle of the instructions to the model builder for establishing the entities and the relationships among them.
['setDefaultElections', { initValue: function () { const election = this.class.model.Election.new({ votingSystem: this, }); election.insert(); },}], ]], ] );
More code.
Outside of the above exercise of notation, I also associate a single field to the problem model as a whole, and that field holds the random seed. I think the voting systems should be modeled in a deterministic manner, but the voting decision procedures (i. e. conversion from affinities to ballots) must sometimes appeal to random numbers. The use of a seeded generator makes all experiments exactly repeatable.
A data model that is constructed in conformance to an entity-relationship diagram, where many-to-many relationships are included, might not in a single, obvious, canonical way, lend itself to representation in serializable form. However, it's certainly possible to come up with several ways that one could be serialized, so that the full model could be recoverable from the serialized form.