import * as util from './lib/util' import * as data from './data' import * as player from './player' /* initialization */ const mass_fields = [ "date", "timestamp", "fatalities", "injured", "total_victims", "age", "case", "weapon_type", "weapon_details" ].reduce((a,b,i) => { a[b] = i return a }, {}) const gv_fields = [ "incident_id", "date", "state", "city_or_county", "address", "n_killed", "n_injured", "incident_url", "source_url", "incident_url_fields_missing", "congressional_district", "gun_stolen", "gun_type", "incident_characteristics", "latitude", "location_description", "longitude", "n_guns_involved", "notes", "participant_age", "participant_age_group", "participant_gender", "participant_name", "participant_relationship", "participant_status", "participant_type", "sources", "state_house_district", "state_senate_district" ].reduce((a,b,i) => { a[b] = i return a }, {}) const year_days_by_month = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0 ].reduce((a, b, i) => { if (i === 0) { return [b] } return a.concat(a[i-1] + b) }, []) let i = 0, max_i = 0, mass_i = 0 let datasets = {}, dataset = {}, bounds = {}, diff = [] let play_fn = play_sequence data.load().then(lists => { console.log(lists) const ar15 = lists.ar_15_2016_18 datasets['AR-15 2016-18'] = {} datasets['AR-15 2016-18'].name = 'AR-15 (2016-18)' datasets['AR-15 2016-18'].pedal = true datasets['AR-15 2016-18'].play_fn = play_mass_shootings const ar_lines = ar15.lines.map(l => { if (l[gv_fields.incident_characteristics].match('Shots Fired - No Injuries')) { return null } if (l[gv_fields.n_killed] + l[gv_fields.n_injured] < 4) return null const [y, m, d] = l[gv_fields.date].split('-') if (parseInt(y) > 2017) return null const yy = (parseInt(y) - 2016) * 365 const mm = year_days_by_month[parseInt(m)] const dd = Math.floor(parseInt(d)) + 14 const date = Math.floor((yy + mm + dd) / 7) // console.log(date, y, m, d) let total = l[gv_fields.n_killed] + l[gv_fields.n_injured] if (l[gv_fields.n_killed] === 0) { total = - l[gv_fields.n_injured] } return [ date, Math.log(Math.log(total + 10) + 1), "** !!, $$, {} killed, [] injured".replace('**', l[gv_fields.date]).replace('!!', l[gv_fields.city_or_county]).replace('$$', l[gv_fields.state]).replace('{}', l[gv_fields.n_killed]).replace('[]', l[gv_fields.n_injured]), l[gv_fields.n_killed], l[gv_fields.n_injured], ] }).filter(n => !!n) datasets['AR-15 2016-18'].dates = ar_lines.map(a => a[0]) datasets['AR-15 2016-18'].dates.push(ar_lines.length) datasets['AR-15 2016-18'].lines = [ar_lines.map(a => a[1])] datasets['AR-15 2016-18'].labels = ar_lines.map(a => a[2]) const fm = lists.firearms_manufactured datasets['Firearms Manufactured'] = {} datasets['Firearms Manufactured'].name = 'Firearms Manufactured' datasets['Firearms Manufactured'].play_fn = play_sequence datasets['Firearms Manufactured'].h = fm.h.slice(1, 5) datasets['Firearms Manufactured'].labels = fm.lines.map(l => l.slice(0, 1)) datasets['Firearms Manufactured'].lines = fm.lines.map(l => l.slice(1, 5)) datasets["Mass Shootings"] = lists.mass_shootings_from_columbine datasets["Mass Shootings"].name = "Mass Shootings" datasets["Mass Shootings"].pedal = true datasets["Mass Shootings"].isMass = true datasets["Mass Shootings"].play_fn = play_mass_shootings const lines = datasets["Mass Shootings"].lines.reverse() const [min_y, ...rest_a] = lines[0][mass_fields.date].split('/') const [max_y, ...rest_b] = lines[lines.length-1][mass_fields.date].split('/') datasets["Mass Shootings"].dates = lines.map(row => { const [y, m, d] = row[mass_fields.date].split('/') return (parseInt(y) - parseInt(min_y)) * 12 + parseInt(m) }) datasets["Mass Shootings"].max_i = (parseInt(max_y) - parseInt(min_y)) * 12 + parseInt(12) // console.log('max i', max_i) datasets["Mass Shootings"].data = lines datasets["Mass Shootings"].lines = [lines.map(row => row[mass_fields.total_victims])] ready() }) /* play function for mass shooting data w/ custom timing */ function play_mass_shootings(i, bounds, diff, note_time, channel="all", exporting) { const { min, max } = bounds const total = dataset.dates.length let pedal_note let notes = [], midi_notes = [] let cases = [] let timings let week = Math.floor((i)/4) % 4 let year = Math.floor((i - (4*4*3)) / 48) // + 2 console.log(year) let yy = -year if (year > 0) year += 1 let this_one = 0 // console.log(i, mass_i, dataset.dates[mass_i], channel, exporting) while (i >= dataset.dates[mass_i] && mass_i < total) { // console.log(i, dataset.dates[mass_i]) notes.push(dataset.lines[0][mass_i]) if (dataset.isMass) { cases.push(dataset.data[mass_i][mass_fields.date] + ' ' + dataset.data[mass_i][mass_fields.case] + ", " + dataset.data[mass_i][mass_fields.fatalities] + ' dead, ' + dataset.data[mass_i][mass_fields.injured] + ' injured') } else { cases.push(dataset.labels[mass_i]) // console.log(dataset.labels[mass_i]) } // console.log('push case', dataset.data[mass_i][mass_fields.date] + ' ' + dataset.data[mass_i][mass_fields.case]) mass_i += 1 this_one += 1 if (this_one >= 4) break } if (cases.length) { document.querySelector('#cases').innerHTML = cases.join('
') } if (total <= mass_i) { mass_i = 0 i = 0 } else { i += 1 } return [i, [], [], pedal_note] } /* play the next note in sequence */ function play_sequence(i, bounds, diff, note_time, channel="all", exporting) { const { rows, min, max } = bounds const count = rows.length * rows[0].length if (i >= count) i = 0 const y = Math.floor(i / rows[0].length) const x = i % rows[0].length // if (!x) console.log(y) const n = rows[y][x] i += 1 if (i >= count) i = 0 const midi_note = play_note( norm(n, min, max) * nx.multiply.value, note_time, channel, exporting) return [i, [midi_note], [128]] } /* play next note according to sonification */ function play_next(){ if (paused) return let note_time = 120000 / Tone.Transport.bpm.value * note_values[nx.timing.active][0] clearTimeout(playTimeout) playTimeout = setTimeout(play_next, note_time) let [new_i, notes, timings] = play_fn(i, bounds, diff, note_time) if (dataset.labels) { // const j = Math.floor(i / bounds.rows[0].length) // document.querySelector('#cases').innerHTML = dataset.labels[j] } i = new_i if (recording) { let timing = note_values[nx.timing.active][2] if (timing.length) timing = timing[i % timing.length] recorder.addEvent(new MidiWriter.NoteEvent({ pitch: notes, duration: 't' + timing })) } } /* build and bind the UI */ function ready() { document.querySelector('.loading').classList.remove('loading') }