import 'dart:math'; final gear = [ Machine('Guitar', 'sample'), Machine('Piano', 'sample'), Machine('YouTube', 'sample'), Machine('Digitakt', 'synth sequencer fx'), Machine('Digitone', 'synth sequencer fx'), Machine('Peak', 'synth fx'), Machine('DrumBrute Impact', 'drums'), Machine('MB33', 'synth'), Machine('MiniBrute II', 'synth sequencer'), Machine('RackBrute', 'synth'), Machine('Microcosm', 'fx'), Machine('Echo Park', 'fx'), Machine('Hall of Fame II', 'fx'), Machine('MXR Bass DI', 'fx'), Machine('RC-1 LoopStation', 'looper'), ]; /// Bias the counts some. const counts = [1, 1, 2, 2, 2, 3]; final random = Random(); /// Completed jams, so that I don't repeat them. final done = [ makeSetup(['DrumBrute Impact', 'MXR Bass DI']), makeSetup(['Digitakt', 'Minibrute II']), makeSetup(['Digitakt', 'Rackbrute']), ]; /// Gear I want to make sure gets used at least once before repeating other /// gear. final unused = ['Digitone', 'Microcosm', 'Peak']; void main(List arguments) { print(pickMachines().join(' + ')); } List makeSetup(List names) { return names .map((name) => gear.firstWhere((machine) => machine.name == name)) .toList(); } List pickMachines() { while (true) { var machines = gear.toList(); machines.shuffle(); var count = counts[random.nextInt(counts.length)]; machines = machines.sublist(0, count); var reason = validate(machines); if (reason != null) { // print('[$reason] $machines'); continue; } machines.sort((a, b) => gear.indexOf(a).compareTo(gear.indexOf(b))); return machines; } } String? validate(List machines) { // Need a sampler if using samples. if (machines.has('sample') && !machines.has('Digitakt')) { return 'samples but no sampler'; } // An unsequenced synth needs a sequencer. if (machines.has('synth') && !machines.has('sequencer') && !machines.has('looper')) { return 'no sequencer for synth'; } // Always want some FX. if (!machines.has('fx')) return 'too dry'; // Need a sound source. if (!machines.has('synth') && !machines.has('drums')) return 'no sounds'; // Must use an unused important piece of gear. if (!machines.hasAny(unused)) return 'no unused gear'; return null; } extension on List { bool has(String name) => any((machine) => machine.matches(name)); bool hasAny(Iterable names) => any((machine) => names.any(machine.matches)); } class Machine { final String name; final Set features; Machine(this.name, String features) : features = features.split(' ').toSet(); bool matches(String name) => this.name == name || features.contains(name); @override String toString() => name; }