Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: packages/charted/lib/charts/data_transformers/aggregation.dart

Issue 2213693002: Updated charted DEP to 0.4.X (Closed) Base URL: https://github.com/dart-lang/observatory_pub_packages.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // 1 //
2 // Copyright 2014 Google Inc. All rights reserved. 2 // Copyright 2014 Google Inc. All rights reserved.
3 // 3 //
4 // Use of this source code is governed by a BSD-style 4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at 5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd 6 // https://developers.google.com/open-source/licenses/bsd
7 // 7 //
8 8
9 part of charted.charts; 9 part of charted.charts;
10 10
11 ///Function callback to filter items in the input 11 ///Function callback to filter items in the input
12 typedef bool AggregationFilterFunc(var item); 12 typedef bool AggregationFilterFunc(var item);
13 13
14 typedef int CompareFunc(dynamic a, dynamic b);
15
14 typedef dynamic FieldAccessor(dynamic item, dynamic key); 16 typedef dynamic FieldAccessor(dynamic item, dynamic key);
15 17
16 /// Given list of items, dimensions and facts, compute 18 /// Given list of items, dimensions and facts, compute
17 /// aggregates (COUNT, SUM, MIN, MAX) for facts at each dimension level. 19 /// aggregates (COUNT, SUM, MIN, MAX) for facts at each dimension level.
18 class AggregationModel { 20 class AggregationModel {
19 // Number of aggregations we collect on each fact 21 // Number of aggregations we collect on each fact
20 int _aggregationTypesCount = 0; 22 int _aggregationTypesCount = 0;
21 23
22 // Currently supported list of aggregations. 24 // Currently supported list of aggregations.
23 static final List<String> supportedAggregationTypes = [ 25 static final List<String> supportedAggregationTypes = [
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 // Cache of entities created for the facts on this aggregation view. 84 // Cache of entities created for the facts on this aggregation view.
83 Map<String, AggregationItem> _entityCache; 85 Map<String, AggregationItem> _entityCache;
84 86
85 // List of field names that aggregation items will have. 87 // List of field names that aggregation items will have.
86 List<String> _itemFieldNamesCache; 88 List<String> _itemFieldNamesCache;
87 89
88 // Walk through the map, by splitting key at '.' 90 // Walk through the map, by splitting key at '.'
89 final bool walkThroughMap; 91 final bool walkThroughMap;
90 92
91 // Map of fieldName to comparator function. 93 // Map of fieldName to comparator function.
92 final Map<String, Function> comparators; 94 final Map<String, CompareFunc> comparators;
93 95
94 // Timing operations 96 // Timing operations
95 static final Logger _logger = new Logger('aggregations'); 97 static final Logger _logger = new Logger('aggregations');
96 Stopwatch _timeItWatch; 98 Stopwatch _timeItWatch;
97 String _timeItName; 99 String _timeItName;
98 100
99 FieldAccessor dimensionAccessor; 101 FieldAccessor dimensionAccessor;
100 FieldAccessor factsAccessor; 102 FieldAccessor factsAccessor;
101 103
102 /// Create a new [AggregationModel] from a [collection] of items, 104 /// Create a new [AggregationModel] from a [collection] of items,
103 /// list of [dimensions] on which the items are grouped and a list of [facts] 105 /// list of [dimensions] on which the items are grouped and a list of [facts]
104 /// on which aggregations are computed. 106 /// on which aggregations are computed.
105 AggregationModel(List collection, List dimensions, List facts, 107 AggregationModel(Iterable collection, List dimensions, List facts,
106 {List<String> aggregationTypes, 108 {List<String> aggregationTypes,
107 this.walkThroughMap: false, 109 this.walkThroughMap: false,
108 this.comparators, 110 this.comparators: const <String, CompareFunc>{},
109 this.dimensionAccessor, 111 this.dimensionAccessor,
110 this.factsAccessor}) { 112 this.factsAccessor}) {
111 _init(collection, dimensions, facts, aggregationTypes); 113 _init(collection, dimensions, facts, aggregationTypes);
112 } 114 }
113 115
114 void _timeItStart(String name) { 116 void _timeItStart(String name) {
115 _timeItName = name; 117 _timeItName = name;
116 _timeItWatch = new Stopwatch(); 118 _timeItWatch = new Stopwatch();
117 _timeItWatch.start(); 119 _timeItWatch.start();
118 } 120 }
119 121
120 void _timeItEnd() { 122 void _timeItEnd() {
121 _timeItWatch.stop(); 123 _timeItWatch.stop();
122 _logger.info('[aggregations/$_timeItName] ' 124 _logger.info('[aggregations/$_timeItName] '
123 '${_timeItWatch.elapsed.inMilliseconds}ms/${_rows.length}r'); 125 '${_timeItWatch.elapsed.inMilliseconds}ms/${_rows.length}r');
124 } 126 }
125 127
126 List get factFields => _factFields; 128 List get factFields => _factFields;
127 List get dimensionFields => _dimFields; 129 List get dimensionFields => _dimFields;
128 130
129 /// Initialize the view 131 /// Initialize the view
130 void _init(List collection, List dimensions, List facts, 132 void _init(Iterable collection, List dimensions, List facts,
131 List<String> aggregationTypes) { 133 List<String> aggregationTypes) {
132 if (collection == null) { 134 if (collection == null) {
133 throw new ArgumentError('Data cannot be empty or null'); 135 throw new ArgumentError('Data cannot be empty or null');
134 } 136 }
135 137
136 if (facts == null || facts.isEmpty) { 138 if (facts == null || facts.isEmpty) {
137 throw new ArgumentError('Facts cannot be empty or null'); 139 throw new ArgumentError('Facts cannot be empty or null');
138 } 140 }
139 141
140 if (dimensions == null) { 142 if (dimensions == null) {
(...skipping 17 matching lines...) Expand all
158 } 160 }
159 } else { 161 } else {
160 aggregationTypes = ['sum']; 162 aggregationTypes = ['sum'];
161 } 163 }
162 164
163 // Always adding 'count' for correct computation of average and count. 165 // Always adding 'count' for correct computation of average and count.
164 if (!aggregationTypes.contains('valid')) { 166 if (!aggregationTypes.contains('valid')) {
165 aggregationTypes.add('valid'); 167 aggregationTypes.add('valid');
166 } 168 }
167 169
168 _rows = collection; 170 _rows = new List.from(collection, growable: false);
169 _dimFields = new List.from(dimensions, growable: false); 171 _dimFields = new List.from(dimensions, growable: false);
170 _factFields = new List.from(facts, growable: false); 172 _factFields = new List.from(facts, growable: false);
171 _entityCache = new Map<String, AggregationItem>(); 173 _entityCache = new Map<String, AggregationItem>();
172 174
173 _createBuffers(); 175 _createBuffers();
174 176
175 _aggregationTypesCount = aggregationTypes.length; 177 _aggregationTypesCount = aggregationTypes.length;
176 for (int i = 0; i < _aggregationTypesCount; i++) { 178 for (int i = 0; i < _aggregationTypesCount; i++) {
177 switch (aggregationTypes[i]) { 179 switch (aggregationTypes[i]) {
178 case 'sum': 180 case 'sum':
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 entity.update(); 265 entity.update();
264 } else { 266 } else {
265 _entityCache.remove(key); 267 _entityCache.remove(key);
266 entity.clear(); 268 entity.clear();
267 } 269 }
268 } 270 }
269 }); 271 });
270 } 272 }
271 273
272 final Map<String, List> _parsedKeys = {}; 274 final Map<String, List> _parsedKeys = {};
275
273 /// Get value from a map-like object 276 /// Get value from a map-like object
274 dynamic _fetch(var item, String key) { 277 dynamic _fetch(var item, String key) {
275 if (walkThroughMap && key.contains('.')) { 278 if (walkThroughMap && key.contains('.')) {
276 return walk(item, key, _parsedKeys); 279 return walk(item, key, _parsedKeys);
277 } else { 280 } else {
278 return item[key]; 281 return item[key];
279 } 282 }
280 } 283 }
281 284
282 /// Preprocess Data 285 /// Preprocess Data
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 _dimToIntMap[di][dimensionVal] = dimensionValCount[di]; 323 _dimToIntMap[di][dimensionVal] = dimensionValCount[di];
321 dimensionValEnum = dimensionValCount[di]++; 324 dimensionValEnum = dimensionValCount[di]++;
322 } 325 }
323 _dimEnumCache[dimDataOffset + di] = dimensionValEnum; 326 _dimEnumCache[dimDataOffset + di] = dimensionValEnum;
324 } 327 }
325 } 328 }
326 329
327 // Sort all dimensions internally 330 // Sort all dimensions internally
328 // The resulting arrays would be used to sort the entire data 331 // The resulting arrays would be used to sort the entire data
329 332
330 List oldSortOrders = _dimSortOrders; 333 List<List<int>> oldSortOrders = _dimSortOrders;
331 _dimSortOrders = new List.generate(dimensionsCount, (i) { 334 _dimSortOrders = new List.generate(dimensionsCount, (i) {
332 if (groupBy && i < _dimPrefixLength) { 335 if (groupBy && i < _dimPrefixLength) {
333 return oldSortOrders[i]; 336 return oldSortOrders[i];
334 } 337 }
335 338
336 List dimensionVals = new List.from(_dimToIntMap[i].keys); 339 List dimensionVals = new List.from(_dimToIntMap[i].keys);
337 List retval = new List(_dimToIntMap[i].length); 340 List<int> retval = new List<int>(_dimToIntMap[i].length);
338 341
339 // When a comparator is not specified, our implementation of the 342 // When a comparator is not specified, our implementation of the
340 // comparator tries to gracefully handle null values. 343 // comparator tries to gracefully handle null values.
341 dimensionVals.sort( 344 if (comparators.containsKey(_dimFields[i])) {
342 comparators != null && comparators.containsKey(_dimFields[i]) 345 dimensionVals.sort(comparators[_dimFields[i]]);
343 ? comparators[_dimFields[i]] 346 } else {
344 : _defaultDimComparator); 347 dimensionVals.sort(_defaultDimComparator);
348 }
345 349
346 for (int si = 0; si < retval.length; ++si) { 350 for (int si = 0; si < retval.length; ++si) {
347 retval[_dimToIntMap[i][dimensionVals[si]]] = si; 351 retval[_dimToIntMap[i][dimensionVals[si]]] = si;
348 } 352 }
349 return retval; 353 return retval;
350 }, growable: false); 354 }, growable: false);
351 355
352 // Create a list of sorted indices - only if we are not having a full 356 // Create a list of sorted indices - only if we are not having a full
353 // overlap of dimensionFields. 357 // overlap of dimensionFields.
354 if (!groupBy || _dimPrefixLength != _dimFields.length) { 358 if (!groupBy || _dimPrefixLength != _dimFields.length) {
355 _sorted = new List<int>.generate(_rows.length, (i) => i, growable: false); 359 _sorted = new List<int>.generate(_rows.length, (i) => i, growable: false);
356 _sorted.sort(_comparator); 360 _sorted.sort(_comparator);
357 } 361 }
358 362
359 // Pre-compute frequently used values 363 // Pre-compute frequently used values
360 _offsetSortedIndex = factsCount * _aggregationTypesCount; 364 _offsetSortedIndex = factsCount * _aggregationTypesCount;
361 _offsetFilteredCount = factsCount * _aggregationTypesCount + 1; 365 _offsetFilteredCount = factsCount * _aggregationTypesCount + 1;
362 366
363 _timeItEnd(); 367 _timeItEnd();
364 } 368 }
365 369
366 // Ensures that null dimension values don't cause an issue with sorting 370 // Ensures that null dimension values don't cause an issue with sorting
367 _defaultDimComparator(Comparable left, Comparable right) => 371 int _defaultDimComparator(Comparable left, Comparable right) =>
368 (left == null && right == null) 372 (left == null && right == null)
369 ? 0 373 ? 0
370 : (left == null) ? -1 : (right == null) ? 1 : left.compareTo(right); 374 : (left == null) ? -1 : (right == null) ? 1 : left.compareTo(right);
371 375
372 /// Given item indices in rows, compare them based 376 /// Given item indices in rows, compare them based
373 /// on the sort orders created while pre-processing data. 377 /// on the sort orders created while pre-processing data.
374 _comparator(int one, int two) { 378 int _comparator(int one, int two) {
375 if (one == two) { 379 if (one == two) {
376 return 0; 380 return 0;
377 } 381 }
378 382
379 int offsetOne = _dimFields.length * one; 383 int offsetOne = _dimFields.length * one;
380 int offsetTwo = _dimFields.length * two; 384 int offsetTwo = _dimFields.length * two;
381 385
382 for (int i = 0; i < _dimFields.length; ++i) { 386 for (int i = 0; i < _dimFields.length; ++i) {
383 int diff = _dimSortOrders[i][_dimEnumCache[offsetOne + i]] - 387 int diff = _dimSortOrders[i][_dimEnumCache[offsetOne + i]] -
384 _dimSortOrders[i][_dimEnumCache[offsetTwo + i]]; 388 _dimSortOrders[i][_dimEnumCache[offsetTwo + i]];
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 throw new UnimplementedError(); 546 throw new UnimplementedError();
543 } 547 }
544 548
545 /// Return an [AggregationItem] that represents facts for dimension 549 /// Return an [AggregationItem] that represents facts for dimension
546 /// represented by [dimension] Only one instance of an entity is created 550 /// represented by [dimension] Only one instance of an entity is created
547 /// per dimension (even if this function is called multiple times) 551 /// per dimension (even if this function is called multiple times)
548 /// 552 ///
549 /// Callers of this method can observe the returned entity for updates to 553 /// Callers of this method can observe the returned entity for updates to
550 /// aggregations caused by changes to filter or done through add, remove 554 /// aggregations caused by changes to filter or done through add, remove
551 /// or modify of items in the collection. 555 /// or modify of items in the collection.
552 AggregationItem facts(List dimension) { 556 AggregationItem facts(List<String> dimension) {
553 List<int> enumeratedList = new List<int>(); 557 List<int> enumeratedList = new List<int>();
554 for (int i = 0; i < dimension.length; ++i) { 558 for (int i = 0; i < dimension.length; ++i) {
555 enumeratedList.add(_dimToIntMap[i][dimension[i]]); 559 enumeratedList.add(_dimToIntMap[i][dimension[i]]);
556 } 560 }
557 561
558 String key = enumeratedList.join(':'); 562 String key = enumeratedList.join(':');
559 AggregationItem item = _entityCache[key]; 563 AggregationItem item = _entityCache[key];
560 564
561 if (item == null && _dimToAggrMap.containsKey(key)) { 565 if (item == null && _dimToAggrMap.containsKey(key)) {
562 item = new _AggregationItemImpl(this, dimension, key); 566 item = new _AggregationItemImpl(this, dimension, key);
563 _entityCache[key] = item; 567 _entityCache[key] = item;
564 } 568 }
565 569
566 return item; 570 return item;
567 } 571 }
568 572
569 /// Return a list of values that are present for a dimension field. 573 /// Return a list of values that are present for a dimension field.
570 List valuesForDimension(dynamic dimensionFieldName) { 574 List valuesForDimension(dynamic dimensionFieldName) {
571 int di = _dimFields.indexOf(dimensionFieldName); 575 int di = _dimFields.indexOf(dimensionFieldName);
572 if (di < 0) { 576 if (di < 0) {
573 return null; 577 return null;
574 } 578 }
575 List values = new List.from(_dimToIntMap[di].keys); 579 List values = new List.from(_dimToIntMap[di].keys);
576 values.sort( 580 if (comparators.containsKey(dimensionFieldName)) {
577 comparators != null && comparators.containsKey(dimensionFieldName) 581 values.sort(comparators[dimensionFieldName]);
578 ? comparators[dimensionFieldName] 582 } else {
579 : _defaultDimComparator); 583 values.sort(_defaultDimComparator);
584 }
580 return values; 585 return values;
581 } 586 }
582 } 587 }
583 588
584 /// Parse a path for nested map-like objects. 589 /// Parse a path for nested map-like objects.
585 /// Caches the parsed key in the passed map. 590 /// Caches the parsed key in the passed map.
586 /// 591 ///
587 /// Takes map keys of the format: 592 /// Takes map keys of the format:
588 /// "list(key=val;val=m).another(state=good).state" 593 /// "list(key=val;val=m).another(state=good).state"
589 /// and outputs: 594 /// and outputs:
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
681 }); 686 });
682 if (match) { 687 if (match) {
683 return current[i]; 688 return current[i];
684 } 689 }
685 } 690 }
686 } else { 691 } else {
687 return current[part]; 692 return current[part];
688 } 693 }
689 }); 694 });
690 } 695 }
OLDNEW
« no previous file with comments | « packages/charted/lib/charts/charts.dart ('k') | packages/charted/lib/charts/data_transformers/aggregation_item.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698