UNPKG

afterwriting

Version:

Post-processing tools for Fountain screenplays

299 lines (246 loc) 12.6 kB
define(function(require) { var template = require('text!plugin/stats/view/stats.hbs'), $ = require('jquery'), helper = require('utils/helper'), Header = require('theme/aw-bubble/view/header'), Protoplast = require('protoplast'), SpiderChart = require('utils/charts/spider'), BarChart = require('utils/charts/bar'), PieChart = require('utils/charts/pie'), PageBalanceChart = require('utils/charts/page_balance'), LineChart = require('utils/charts/line'), LocationsBreakdown = require('utils/charts/locations_breakdown'), SectionViewMixin = require('theme/aw-bubble/view/section-view-mixin'), StatsViewPresenter = require('plugin/stats/view/stats-view-presenter'), ThemeModel = require('theme/aw-bubble/model/theme-model'), ThemeController = require('theme/aw-bubble/controller/theme-controller'), BaseComponent = require('core/view/base-component'); return BaseComponent.extend([SectionViewMixin], { $meta: { presenter: StatsViewPresenter }, hbs: template, themeController: { inject: ThemeController }, themeModel: { inject: ThemeModel }, $sceneLengthType: null, // TODO: Move to presenter? (+) settings: { inject: 'settings' }, whoWithWhoHeader: { component: Header }, scriptPulseHeader: { component: Header }, sceneLengthHeader: { component: Header }, locationsBreakdownHeader: { component: Header }, pageBalanceHeader: { component: Header }, daysAndNightsHeader: { component: Header }, intVsExtHeader: { component: Header }, data: null, spiderChart: null, barChart: null, pieChart: null, pageBalanceChart: null, lineChart: null, locationsBreakdown: null, init: function() { BaseComponent.init.call(this); this.spiderChart = SpiderChart; this.barChart = BarChart; this.pieChart = PieChart; this.pageBalanceChart = PageBalanceChart; this.lineChart = LineChart; this.locationsBreakdown = LocationsBreakdown; this.whoWithWhoHeader.id = "stats-who"; this.whoWithWhoHeader.title = "Who talks with whom (by number of scenes)"; this.whoWithWhoHeader.description = "Each character is represented by a circle (max. 10 characters). If characters are connected with a line that means they are talking in the same scene. Thicker the line - more scenes together. Hover the mouse cursor over a character circle to see how many dialogues scenes that character have with other characters."; this.scriptPulseHeader.id = "stats-tempo"; this.scriptPulseHeader.title = "Script Pulse"; this.scriptPulseHeader.description = "Short scenes and short action/dialogue blocks bump the tempo up. Long scenes and long blocks set it back."; this.sceneLengthHeader.id = "stats-scene-length"; this.sceneLengthHeader.title = "Scene length"; this.sceneLengthHeader.description = "Each bar represent one scene (white bars for day scenes, black bars for night scenes). Hover the mouse cursor over a bar to see estimated time of a scene. You can click on a bar to jump to selected scene in the editor."; this.locationsBreakdown.id = "stats-locations-breakdown"; this.locationsBreakdownHeader.title = "Locations breakdown"; this.locationsBreakdownHeader.description = "Blocks on the top strip represent amount of time spent in a location. If a location occurs more than once in the script, it's highlighted by a colour (white colour is used for each location occurring only once).<br />Pie chart below shows time distribution for each location. Mouse over the blocks to see corresponding data on the pie chart (and vice versa)."; this.pageBalanceHeader.id = "stats-page-balance"; this.pageBalanceHeader.title = "Page balance"; this.pageBalanceHeader.description = "Shows balance between action time and dialogue time on each page. Click on a page to jump to the editor."; this.daysAndNightsHeader.id = "stats-days-nights"; this.daysAndNightsHeader.title = "Days and nights"; this.daysAndNightsHeader.description = "Pie chart representing day vs night scenes breakdown. Hover over sections to see number of day/night scenes."; this.intVsExtHeader.id = "stats-int-ext"; this.intVsExtHeader.title = "INT. vs EXT."; this.intVsExtHeader.description = "Pie chart representing interior vs exterior scenes breakdown. Hover over sections to see number of int/ext scenes."; }, addBindings: function() { Protoplast.utils.bind(this, 'data', this._render); }, addInteractions: function() { var themeModel = this.themeModel; this.$sceneLengthType.on('change', this._render); Protoplast.utils.bind(themeModel, 'expanded', function() { if (this.active) { this._render(); } }.bind(this)); }, refresh: function() { // TODO: Remove refresh method, chart should refresh when parent content changes (+) // Timeout is added to make sure _render is called after content is fully expanded/collapsed // as chart components rely on query ".content" to calculate width of the chart setTimeout(function() { this._render(); }.bind(this), 0); }, _render: function() { var themeController = this.themeController; var themeModel = this.themeModel; if (!this.data) { return; } this.spiderChart.render('#who-with-who', this.data.who_with_who.characters, this.data.who_with_who.links, { label: 'name' }); this.barChart.render('#stats-scene-length', this.data.scenes, { tooltip: function(d) { return d.header + ' (time: ' + helper.format_time((d.length / this.settings.print.lines_per_page)) + ')'; }.bind(this), value: 'length', small: themeModel.small, show_tooltip: themeController.showTooltip.bind(themeController), hide_tooltip: themeController.hideTooltip.bind(themeController), move_tooltip: themeController.moveTooltip.bind(themeController), color: function(d) { if (this.$sceneLengthType.val() === "int_ext") { if (d.location_type === 'mixed') { return '#777777'; } else if (d.location_type === 'int') { return '#eeeeee'; } else if (d.location_type === 'ext') { return '#111111'; } else if (d.location_type === 'other') { return '#444444'; } } if (d.type == 'day') { return '#eeeeee'; } else if (d.type == 'night') { return '#222222'; } else { return '#777777'; } }.bind(this), bar_click: function(d) { if (!themeModel.small) { this._goto(d.token.line); } }.bind(this) }); this.pieChart.render('#stats-days-and-nights', this.data.days_and_nights, { tooltip: function(d) { return d.data.label + ': ' + d.data.value + (d.data.value == 1 ? ' scene' : ' scenes'); }, value: 'value', small: themeModel.small, show_tooltip: themeController.showTooltip.bind(themeController), hide_tooltip: themeController.hideTooltip.bind(themeController), move_tooltip: themeController.moveTooltip.bind(themeController), color: function(d) { if (d.data.label == 'DAY') { return '#eeeeee'; } else if (d.data.label == 'NIGHT') { return '#222222'; } else if (d.data.label == 'DAWN') { return '#777777'; } else if (d.data.label == 'DUSK') { return '#444444'; } else { return '#aaaaaa'; } } }); var int_ext_labels = { int: 'INT.', ext: 'EXT.', mixed: 'INT./EXT.', other: 'OTHER' }; this.pieChart.render('#stats-int-ext', this.data.int_and_ext, { tooltip: function(d) { return int_ext_labels[d.data.label] + ': ' + d.data.value + (d.data.value == 1 ? ' scene' : ' scenes'); }, value: 'value', small: themeModel.small, show_tooltip: themeController.showTooltip.bind(themeController), hide_tooltip: themeController.hideTooltip.bind(themeController), move_tooltip: themeController.moveTooltip.bind(themeController), color: function(d) { if (d.data.label == 'mixed') { return '#777777'; } else if (d.data.label == 'int') { return '#eeeeee'; } else if (d.data.label == 'ext') { return '#111111'; } else if (d.data.label == 'other') { return '#444444'; } } }); this.pageBalanceChart.render('#stats-page-balance', this.data.page_balance, { page_click: function(d) { if (!themeModel.small) { this._goto(d.first_line.token.line); } }.bind(this), small: themeModel.small, show_tooltip: themeController.showTooltip.bind(themeController), hide_tooltip: themeController.hideTooltip.bind(themeController), move_tooltip: themeController.moveTooltip.bind(themeController) }); this.lineChart.render('#stats-tempo', this.data.tempo, { value: 'tempo', small: themeModel.small, show_tooltip: themeController.showTooltip.bind(themeController), hide_tooltip: themeController.hideTooltip.bind(themeController), move_tooltip: themeController.moveTooltip.bind(themeController), tooltip: function(d, i) { if (i === this.data.tempo.length - 1) { return ''; } return d.scene + '<br />...' + d.line + '... '; }.bind(this), click: function(d) { if (!themeModel.small) { this._goto(d.line_no); } }.bind(this) }); this.locationsBreakdown.render('#locations-breakdown', this.data.locationsBreakdown, { small: themeModel.small, show_tooltip: themeController.showTooltip.bind(themeController), hide_tooltip: themeController.hideTooltip.bind(themeController), move_tooltip: themeController.moveTooltip.bind(themeController) }); }, _goto: function(position) { this.dispatch('goto', position); } }); });