agentscript
Version:
AgentScript Model in Model/View architecture
135 lines (113 loc) • 4.13 kB
HTML
<html>
<head>
<title>tsp</title>
<link rel="icon" type="image/x-icon" href="../favicon.ico" />
</head>
<body>
<script type="module">
import * as util from '../src/utils.js'
import TwoDraw from '../src/TwoDraw.js'
import Animator from '../src/Animator.js'
import Model from '../models/TspModel.js'
import Mouse from '../src/Mouse.js'
import dat from '../vendor/dat.gui.js'
import Plot from '../src/Plot.js'
const breedSize = { nodes: 2, travelers: 0 }
const drawOptions = {
patchesColor: 'black',
turtlesShape: 'circle',
// turtlesSize of 0 will skip drawing this turle
// here "travelers" are skipped
// turtlesSize: t => (t.breed.name === 'nodes' ? nodeSize : 0),
turtlesSize: t => breedSize[t.breed.name],
turtlesColor: 'yellow',
linksColor: 'red',
}
// =========== Init Model, View, Animator ===================
const model = new Model()
await model.startup()
model.setup()
const view = new TwoDraw(model, {
div: 'modelDiv',
width: 500,
drawOptions,
})
const anim = new Animator(
() => {
model.step()
view.draw()
if (model.done) anim.stop()
},
-1, // run until model stops: best tour constant for 500 steps
30 // 30 fps
).startStats()
// =========== UI Elements ===================
const gui = new dat.GUI()
gui.width = 280 // increase dat.gui width
const miscGuis = {
stop: false
}
gui.add(anim, 'fps', 1, 60, 1)
.onChange(() => anim.reset())
gui.add(anim, 'toggle')
.onChange(() => miscGuis.stop = anim.isRunning())
gui.add(miscGuis, 'stop')
.listen()
.onChange(val => { if (val) { anim.stop() } else { anim.start() } })
gui.add(anim, 'once').onChange(() => miscGuis.stop = true)
gui.add(view, 'width', 100, 1000, 25)
gui.add(view.drawOptions, 'turtlesSize', 1, 10, 1)
gui.add(breedSize, 'nodes', 1, 10, 1)
gui.add(model, 'bestTourLength')
.listen()
gui.add(model, 'ticks')
.listen()
gui.add(view, 'downloadCanvas')
// gui.addColor(view.drawOptions, 'patchesColor')
// ============ Independent Mouse Handling ==================
let dragNode
function mouseCallback(mouse) {
const { x, y, action } = mouse
switch (action) {
case 'mousedown':
dragNode = model.nodes.minOneOf(t => t.distanceXY(x, y))
break
case 'mousedrag':
if (dragNode) model.moveNode(dragNode, x, y)
break
case 'mouseup':
dragNode = null
break
}
view.draw() // Draw whenever mouse has an event
}
const mouse = new Mouse(
model,
view,
mouseCallback
).start()
// view.draw() // Draw once to get started ??
// ============ Plot new tours ==================
const options = {
width: 1000,
height: 500,
title: 'Tour Length',
}
const plot = new Plot('plot', {
tourLength: 'blue',
}, options)
// ============ Tour Change Callback ==================
model.onChange = (length, changes, ticks) => {
const tourLength = Math.round(length)
plot.setData({ tourLength: tourLength })
console.log(
`new best tour at tick ${ticks}: ${length}, changes ${changes}`
)
}
util.toWindow({ util, model, view, anim, gui, plot })
</script>
<div id="modelDiv"></div>
<div id="plot"></div>
<!-- <div id="plot" style="width: 100vw"></div> -->
</body>
</html>