+
+ Interfacing mechanisms
+
+
+
+ XP–45 / vessel
+
+
+
Fabulous typography encountering spring
diff --git a/misc/dynmet-search.js b/misc/dynmet-search.js
new file mode 100644
index 000000000..33189b8ea
--- /dev/null
+++ b/misc/dynmet-search.js
@@ -0,0 +1,98 @@
+//
+// Program that searches for optimal a,b,c values for dynamic metrics.
+//
+// Provide ideal tracking values for font sizes in idealTracking and start
+// this program. It will run forever and print to stdout when it finds
+// better a,b,c values that brings you closer to the ideal values.
+//
+// These are the initial a,b,c values. (Update if you find better values.)
+let a = -0.02, b = 0.0755, c = -0.1021 // 0.00092
+//
+// These are the ideal tracking values.
+let idealTracking = {
+ // 6: 0.05,
+ // 7: 0.04,
+ // 8: 0.03,
+ 9: 0.01,
+ // 10: 0.015,
+ 11: 0.005,
+ 12: 0.0025,
+ 13: 0,
+ // 14: 0,
+ // 15: -0.002,
+ 16: -0.005,
+ // 17: -0.008,
+ 18: -0.01,
+ // 20: -0.014,
+ // 24: -0.016,
+ // 30: -0.019,
+ 40: -0.022,
+}
+
+
+let idealTrackingList = Object.keys(idealTracking).map(fontSize =>
+ [fontSize, idealTracking[fontSize]]
+)
+
+function sample(a, b, c) {
+ let idealDist = 0.0
+ for (let [fontSize, idealTracking] of idealTrackingList) {
+
+ let tracking = a + b * Math.pow(Math.E, c * fontSize)
+
+ let dist = Math.abs(tracking - idealTracking)
+
+ idealDist += dist
+ // console.log(`${fontSize} d=${tracking - idealTracking} d'=${dist}`)
+ }
+ // console.log(`idealDist=${idealDist}`)
+ return idealDist / idealTrackingList.length
+}
+
+const prec = 4 // precision
+let bestConstants = { a, b, c }
+let isneg = {
+ a: a < 0,
+ b: b < 0,
+ c: c < 0,
+}
+let bestDistance = sample(a, b, c)
+
+console.log(
+ '------------------------------------------------------------------\n' +
+ `| Started at ${(new Date()).toLocaleString()} with initial values:\n` +
+ `| a = ${bestConstants.a}, b = ${bestConstants.b},` +
+ ` c = ${bestConstants.c} // D ${bestDistance.toFixed(5)}\n` +
+ `| Ctrl-C to end.\n` +
+ '------------------------------------------------------------------'
+)
+
+function logNewBest() {
+ console.log(
+ `new best: a = ${a.toFixed(prec)}, b = ${b.toFixed(prec)}, c = ${c.toFixed(prec)} // D ${bestDistance.toFixed(5)}`
+ )
+}
+
+while (true) {
+ // a = parseFloat((bestConstants.a * ((Math.random() * 2.0) - 1.0)).toFixed(prec))
+ // b = parseFloat((bestConstants.b * ((Math.random() * 2.0) - 1.0)).toFixed(prec))
+ // c = parseFloat((bestConstants.c * ((Math.random() * 2.0) - 1.0)).toFixed(prec))
+
+ let a2 = bestConstants.a * ((Math.random() * 2.0) - 1.0)
+ let b2 = bestConstants.b * ((Math.random() * 2.0) - 1.0)
+ let c2 = bestConstants.c * ((Math.random() * 2.0) - 1.0)
+
+ if (isneg.a) { if (a2 > 0) { a2 = a } } else if (a2 < 0) { a2 = a }
+ if (isneg.b) { if (b2 > 0) { b2 = b } } else if (b2 < 0) { b2 = b }
+ if (isneg.c) { if (c2 > 0) { c2 = c } } else if (c2 < 0) { c2 = c }
+
+ a = a2
+ b = b2
+ c = c2
+
+ let dist = sample(a, b, c)
+ if (dist < bestDistance) {
+ bestDistance = dist
+ logNewBest()
+ }
+}