Created
May 5, 2013 20:27
-
-
Save holyjak/5522060 to your computer and use it in GitHub Desktop.
Intention Hidden In Implementation And Misty Edge of Validity - why does this function do what it does and under what assumptions does it operate? REFACTORED. See http://wondersofcode.wordpress.com/2013/05/05/intention-hidden-in-implementation-and-misty-edge-of-validity/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Set seriesData.previous to hold data series of the previous period | |
// so that we may compute deltas (e.g. +10%). | |
// We also ensure that all the series, previous and current, have the same | |
// number of data points, adding fake ones if necessary, so that the delta-computation | |
// code <tbd:add reference> doesn't blow up. There may be some data missing | |
// at the end of a period, for example because months have different numbers of days. | |
// The fake elements and also any other undefined values will default to [0,0], which | |
// should be OK with all (line,area,..) graphs and tables. | |
// E.x.: seriesData.series[0].data = [ [1,"12%"],[2,"22%"],..,[31,"18%"] ], | |
// the previous month had only 30 days so we add a fake element for day 31; | |
// See the class Series for more information. | |
augmentSeriesWithPreviousValues:function (seriesData, previousSeriesData) { | |
var series = seriesData.series; | |
seriesData.previous = []; | |
var previousSeries = previousSeriesData.series; | |
... // checks, computing maxRows, maxColumns, previousCategories | |
// that maps category name to series index (id) | |
var matcher = new SeriesMatcher(seriesData, previousCategories); // a helper | |
// The current and previous series must have data for the same unit (e.g. day 15 if period=month), | |
// only at the end of the period there may be missing entries (shorter month etc.) | |
assertMatchingDaysInCurrentAndPrevious(series, previousSeries); | |
for (var seriesId = 0; seriesId < series.length; seriesId++) { | |
var previousSeriesId = matcher.previousSeriesIdFor(seriesId) | |
for (var rowId = 0; rowId < maxRows; rowId++) { | |
for (var columnId = 1; columnId < maxColumns; columnId++) { | |
createDataPointIfMissing(series, seriesId, rowId); | |
replaceNaNWithDefaultOf(0, series, seriesId, rowId, columnId); | |
createDataPointIfMissing(seriesData.previous, seriesId, rowId); | |
copyPreviousValueIfDefined(seriesData.previous[seriesId], previousSeries[previousSeriesId], rowId, columnId); | |
replaceNaNWithDefaultOf(0, seriesData.previous, seriesId, rowId, columnId); | |
} | |
} | |
} | |
} | |
// Make sure the 3D array series has the element [seriesId][rowId]; | |
// it's assumed that [seriesId-1][rowId-1] exist, unless 0. | |
function createDataPointIfMissing(series, seriesId, rowId) { | |
var array = series; | |
[seriesId, rowId].forEach(function(idx){ | |
if (!array[idx]) { | |
array[idx] = []; | |
} | |
array = array[idx]; | |
}); | |
return series; | |
} | |
// If x or y coordinate of the data point series[seriesId][rowId] is undefined, | |
// set it to the given default value | |
function replaceNaNWithDefaultOf(default, series, seriesId, rowId, columnId) { | |
var value = series[seriesId][rowId][columnId]; | |
if (isNaN(value)) { | |
series[seriesId][rowId][columnId] = default; | |
} | |
} | |
// Copy the given data point's coordinate from source (if defined) to target | |
function copyPreviousValueIfDefined(target, source, rowId, columnId) { | |
if (source && source[rowId] && source[rowId][columnId]) { | |
target[rowId][columnId] = source[rowId][columnId]; | |
} | |
} | |
... // implementation of other helper functions, such as assertNoMissing, not shown |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment