summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Cully <bjc@kublai.com>2021-02-19 15:27:22 -0500
committerBrian Cully <bjc@kublai.com>2021-02-19 15:27:22 -0500
commita5e378e2b4c075f09d3293ccc301f0e504cb20d7 (patch)
tree5cadc502f422e180ac82030fd98e01692e4268d0
parented2b76634a6fb1a9fb45abdd7afc7342f5b6f12c (diff)
downloadmolsim2-a5e378e2b4c075f09d3293ccc301f0e504cb20d7.tar.gz
molsim2-a5e378e2b4c075f09d3293ccc301f0e504cb20d7.zip
Alter rule flow
It’s simpler to put kill/clone buttons on the final step, so kill the initial clone step. This is probably more sensible overall. The old, clone first method was done to simplify the state machine at the time, at the cost of expected instruction order.
-rw-r--r--index.html35
-rw-r--r--lethality-selector.mjs35
-rw-r--r--main.mjs4
-rw-r--r--rules.mjs122
4 files changed, 54 insertions, 142 deletions
diff --git a/index.html b/index.html
index aa3a25b..2d96b9d 100644
--- a/index.html
+++ b/index.html
@@ -29,26 +29,22 @@
<span id='remaining-iterations'>--</span> more times:
<ol>
- <li id='clone-nucleotide' class='step'>
- <button id='clone' disabled=''>Clone</button> the genome to
- start mutating it.
- </li>
-
<li id='roll-for-nucleotide' class='step'>
Roll to find the nucleotide to mutate.
+ </li>
+
+ <li id='nucleotide-select' class='step'>
+ Depending on the roll:
+
<ul>
<li>If the roll is between 1 through 18, inclusive, select
that nucleotide.</li>
- <li>Otherwise, skip mutation and clone the genome
- again.</li>
+ <li>Otherwise, skip mutation and
+ <button class='clone' disabled=''>clone</button> the
+ genome again.</li>
</ul>
</li>
- <li id='nucleotide-select' class='step'>
- Select the <span id='select-number'>rolled</span>
- nucleotide in the sequence.
- </li>
-
<li id='roll-for-mutation' class='step'>
Roll to see what kind of mutation to perform.
</li>
@@ -76,12 +72,12 @@
<li id='mark-as-lethal'>
Depending on the change to the codon:
<ul>
- <li>If the mutation caused a change in the amino acid being
- coded, mark this mutation as <em>lethal</em>, and start
- over with the genome from the previous iteration.</li>
+ <li>If the mutation caused a change in the amino acid
+ being coded, then <button id='kill' disabled=''>kill</button> it and
+ start again with the previous generation.</li>
- <li>Otherwise, mark the mutation as <em>non-lethal</em>,
- and continue with this new genome.</li>
+ <li>Otherwise, <button id='clone' disabled=''>clone</button> this
+ genome for the next generation.</li>
</ul>
</li>
</ol>
@@ -130,11 +126,6 @@
</ul>
</div>
- <div id='lethality-selector' class='hidden'>
- <button id='lethal'>Lethal</button>
- <button id='non-lethal'>Non-lethal</button>
- </div>
-
<script src='main.mjs' type='module'></script>
</body>
</html>
diff --git a/lethality-selector.mjs b/lethality-selector.mjs
deleted file mode 100644
index 80c3e71..0000000
--- a/lethality-selector.mjs
+++ /dev/null
@@ -1,35 +0,0 @@
-class LethalitySelector {
- constructor(elt) {
- this.elt = elt
-
- for (const elt of this.elt.querySelectorAll('button')) {
- elt.addEventListener('click', this.select.bind(this))
- }
- }
-
- attach() {
- this.elt.classList.remove('hidden')
- }
-
- detach() {
- this.elt.classList.add('hidden')
- }
-
- get onItemSelected() {
- if (this._onItemSelected !== undefined) {
- return this._onItemSelected
- }
- return () => {}
- }
-
- set onItemSelected(fn) {
- this._onItemSelected = fn
- }
-
- select(evt) {
- window.evt = evt
- this.onItemSelected(evt.target.id == 'lethal')
- }
-}
-
-export default LethalitySelector
diff --git a/main.mjs b/main.mjs
index 613eded..cb2b207 100644
--- a/main.mjs
+++ b/main.mjs
@@ -5,14 +5,12 @@ function init() {
const die = document.querySelector('#die')
const aminoAcidSelector = document.querySelector('#amino-acid-selector')
const nucleotideSelector = document.querySelector('#nucleotide-selector')
- const lethalitySelector = document.querySelector('#lethality-selector')
const instructions = document.querySelector('#instructions')
- const cloneButton = document.querySelector('#clone')
const remainingIterations = document.querySelector('#remaining-iterations')
const printButton = document.querySelector('#print')
const errors = document.querySelector('#errors')
- const rules = new Rules(die, instructions, genomeList, aminoAcidSelector, nucleotideSelector, lethalitySelector, cloneButton, remainingIterations, printButton, errors)
+ const rules = new Rules(die, instructions, genomeList, aminoAcidSelector, nucleotideSelector, remainingIterations, printButton, errors)
}
init()
diff --git a/rules.mjs b/rules.mjs
index 83c07bc..3cc2524 100644
--- a/rules.mjs
+++ b/rules.mjs
@@ -5,37 +5,9 @@ import Die from './die.mjs'
import Error from './error.mjs'
import Genome from './genome.mjs'
import GenomeList from './genome-list.mjs'
-import LethalitySelector from './lethality-selector.mjs'
import Nucleotide from './nucleotide.mjs'
import NucleotideSelector from './nucleotide-selector.mjs'
-class CloneNucleotide {
- constructor(rules) {
- this.rules = rules
-
- this.id = 'clone-nucleotide'
- this._boundClickHandler = this.clickHandler.bind(this)
- }
-
- enter() {
- this.rules.cloneButton.addEventListener('click',
- this._boundClickHandler)
- this.rules.cloneButton.disabled = false
- }
-
- exit() {
- this.rules.cloneButton.removeEventListener('click',
- this._boundClickHandler)
- this.rules.cloneButton.disabled = true
- }
-
- clickHandler(evt) {
- const genome = this.rules.currentGenome.clone()
- this.rules.genomeList.push(genome)
- this.rules.next(new RollForNucleotide(this.rules))
- }
-}
-
class RollForNucleotide {
constructor(rules) {
this.rules = rules
@@ -55,16 +27,7 @@ class RollForNucleotide {
}
handleDieRoll() {
- if (this.rules.die.value > Rules.initialGenomeBases.length) {
- this.rules.iterations--
- if (this.rules.isLastIteration) {
- this.rules.next(new DoNothing(this.rules))
- } else {
- this.rules.next(new CloneNucleotide(this.rules))
- }
- } else {
- this.rules.next(new NucleotideSelect(this.rules))
- }
+ this.rules.next(new NucleotideSelect(this.rules))
}
}
@@ -73,26 +36,56 @@ class NucleotideSelect {
this.rules = rules
this.id = 'nucleotide-select'
+ this._boundCloneHandler = this.handleClone.bind(this)
}
enter() {
- this.want = this.rules.die.value
- this.rules.instructions.querySelector('#select-number').innerHTML =
- `${this.want}<sup>${ordinalSuffix(this.want)}</sup>`
+ this.cloneButtons = document.querySelectorAll(`#${this.id} .clone`)
+ this.cloneButtons.forEach(button => {
+ button.addEventListener('click', this._boundCloneHandler)
+ button.disabled = false
+ })
+ this.want = this.rules.die.value
this.rules.currentGenome.onNucleotideSelectionChanged =
this.handleSelectionChanged.bind(this)
+
this.rules.currentGenome.unlock()
}
exit() {
this.rules.currentGenome.lock()
+
+ this.cloneButtons.forEach(button => {
+ button.removeEventListener('click', this._boundCloneHandler)
+ button.disabled = true
+ })
+
this.rules.currentGenome.onNucleotideSelectionChanged = undefined;
}
+ handleClone(evt) {
+ window.r = this.rules
+ console.debug('clone', this.rules.die.value, this.rules.currentGenome.length)
+ if (this.rules.die.value < this.rules.currentGenome.length) {
+ this.rules.error.innerHTML =
+ `TODO: this should have been a selection operation`
+ this.rules.next(new ShowError(this.rules, this))
+ return
+ }
+
+ this.rules.genomeList.push(this.rules.currentGenome.clone())
+ this.rules.next(new RollForNucleotide(this.rules))
+ }
+
handleSelectionChanged(nucleotide, i) {
i++;
- if (i != this.rules.die.value) {
+ if (this.rules.die.value > this.rules.currentGenome.length) {
+ this.rules.error.innerHTML =
+ `TODO: this should have been a clone operation`
+ this.rules.next(new ShowError(this.rules, this))
+ return
+ } else if (i != this.rules.die.value) {
this.rules.error.innerHTML =
`You selected the ${i}<sup>${ordinalSuffix(i)}</sup> nucleotide. Please select the ${this.want}<sup>${ordinalSuffix(this.want)}</sup> one.`
this.rules.next(new ShowError(this.rules, this))
@@ -245,12 +238,9 @@ class MarkAsLethal {
}
enter() {
- this.rules.lethalitySelector.onItemSelected = this.handleItemSelected.bind(this)
- this.rules.lethalitySelector.attach()
}
exit() {
- this.rules.lethalitySelector.detach()
}
get lethalHTML() {
@@ -260,25 +250,6 @@ class MarkAsLethal {
get nonLethalHTML() {
return 'A change in amino acid is a <em>lethal</em> change.'
}
-
- handleItemSelected(isLethal) {
- if (isLethal !== this.isLethal) {
- if (this.isLethal) {
- this.rules.error.innerHTML = this.lethalHTML
- } else {
- this.rules.error.innerHTML = this.nonLethalHTML
- }
- this.rules.next(new ShowError(this.rules, this))
- return
- }
-
- this.rules.iterations--
- if (this.rules.isLastIteration) {
- this.rules.next(new DoNothing(this.rules))
- } else {
- this.rules.next(new CloneNucleotide(this.rules))
- }
- }
}
class DoNothing {
@@ -328,21 +299,19 @@ class ShowError {
}
class Rules {
- constructor(die, instructions, genomeList, aminoAcidSelector, nucleotideSelector, lethalitySelector, cloneButton, remainingIterations, printButton, errors) {
+ constructor(die, instructions, genomeList, aminoAcidSelector, nucleotideSelector, remainingIterations, printButton, errors) {
this.die = new Die(die)
this.instructions = instructions
this.genomeList = new GenomeList(genomeList)
this.aminoAcidSelector = new AminoAcidSelector(aminoAcidSelector)
this.nucleotideSelector = new NucleotideSelector(nucleotideSelector)
- this.lethalitySelector = new LethalitySelector(lethalitySelector)
- this.cloneButton = cloneButton
this.remainingIterations = remainingIterations
this.printButton = printButton
this.error = new Error(errors)
this.iterations = Rules.maxIterations
- this.cloneButton.disabled = true
this.genomeList.push(new Genome(Rules.initialGenomeBases))
+ this.genomeList.push(this.currentGenome.clone())
if (false) {
this._debugStartAtRollForMutation()
@@ -350,12 +319,12 @@ class Rules {
this._debugStartAtPerformMutation(3)
} else if (false) {
this._debugStartAtSelectAminoAcid()
- } else if (true) {
+ } else if (false) {
this._debugStartAtSelectLethality()
} else if (false) {
this._debugStartWithError()
} else {
- this.currentState = new CloneNucleotide(this)
+ this.currentState = new RollForNucleotide(this)
}
this.enterState()
}
@@ -373,19 +342,12 @@ class Rules {
}
_debugStartAtRollForMutation() {
- this.genomeList.push(this.currentGenome.clone())
-
this.currentState = new RollForMutation(this)
const nucleotide = this.currentGenome.nucleotides[2]
this.currentGenome.selectedNucleotide = nucleotide
}
_debugStartAtPerformMutation(n) {
- // The semicolon below is necessary to prevent the array
- // expansion below it from being understood as an index
- // operation.
- this.genomeList.push(this.currentGenome.clone());
-
[...Array(n)].forEach(i => {
const n = randomItem(this.currentGenome.nucleotides)
n.value = randomItem(Nucleotide.bases)
@@ -401,8 +363,6 @@ class Rules {
}
_debugStartAtSelectAminoAcid() {
- this.genomeList.push(this.currentGenome.clone())
-
this.currentState = new SelectAminoAcid(this)
this.die.value = 15
const nucleotide = this.currentGenome.nucleotides[15]
@@ -411,8 +371,6 @@ class Rules {
}
_debugStartAtSelectLethality() {
- this.genomeList.push(this.currentGenome.clone())
-
this.currentState = new MarkAsLethal(this, true)
this.die.value = 15
const nucleotide = this.currentGenome.nucleotides[15]
@@ -422,7 +380,7 @@ class Rules {
}
_debugStartWithError() {
- this.currentState = new ShowError(this, new CloneNucleotide(this))
+ this.currentState = new ShowError(this, new RollForNucleotide(this))
this.error.innerHTML = 'test an error'
}