Skip to content

Commit

Permalink
one index2pos array
Browse files Browse the repository at this point in the history
  • Loading branch information
sgratzl committed Dec 2, 2018
1 parent 361bc18 commit 6a8f9db
Show file tree
Hide file tree
Showing 11 changed files with 147 additions and 69 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ src/**/*.css
src/**/*.d.ts
/node_modules/
.cache-loader
/build2
/build*
2 changes: 1 addition & 1 deletion demo/big.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
window.onload = function () {
const arr = [];
const cats = ['c1', 'c2', 'c3'];
for (let i = 0; i < 500000; ++i) {
for (let i = 0; i < 100000; ++i) {
arr.push({
a: Math.random() * 10,
d: 'Row ' + i,
Expand Down
88 changes: 88 additions & 0 deletions demo/big_d.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<!DOCTYPE html>
<html>

<head lang="en">
<meta charset="UTF-8">
<title>LineUp Taggle Test</title>

<link href="../build_d/LineUpJS.css" rel="stylesheet">
<link href="./demo.css" rel="stylesheet">
</head>

<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="../build_d/LineUpJS.js"></script>

<script>
window.onload = function () {
const arr = [];
const cats = ['c1', 'c2', 'c3'];
for (let i = 0; i < 500000; ++i) {
arr.push({
a: Math.random() * 10,
d: 'Row ' + i,
cat: cats[Math.floor(Math.random() * 3)],
cat2: cats[Math.floor(Math.random() * 3)]
})
}
console.log('generated');
const desc = [{
label: 'D',
type: 'string',
column: 'd'
},
{
label: 'A',
type: 'number',
column: 'a',
'domain': [0, 10]
},
{
label: 'Cat',
type: 'categorical',
column: 'cat',
categories: ['c1', 'c2', 'c3']
},
{
label: 'Cat Label',
type: 'categorical',
column: 'cat2',
categories: [{
name: 'c1',
label: 'C1',
color: 'green'
}, {
name: 'c2',
label: 'C2',
color: 'blue'
}, {
name: 'c3',
label: 'C3',
color: 'red'
}]
}
];

const p = new LineUpJS.LocalDataProvider(arr, desc, {
grouping: true
});
p.deriveDefault();
p.getLastRanking().insert(p.create({
type: 'selection',
label: 'S'
}), 0);
p.getLastRanking().insert(p.create({
type: 'aggregate',
label: 'A'
}), 0);
p.getLastRanking().push(p.create(desc[1]));

const instance = new LineUpJS.Taggle(document.body, p);
instance.update();
};

</script>

</body>

</html>
1 change: 0 additions & 1 deletion src/model/Group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ export declare type IndicesArray = ReadonlyArray<number> | UIntTypedArray;

export interface IOrderedGroup extends IGroup {
order: IndicesArray;
index2pos: IndicesArray;
}

export const defaultGroup: IGroup = {
Expand Down
11 changes: 1 addition & 10 deletions src/model/RankColumn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,7 @@ export default class RankColumn extends Column {
if (!ranking) {
return -1;
}
const groups = ranking.getGroups();
let offset = 0;
for (const group of groups) {
const rank = group.index2pos[row.i];
if (typeof rank === 'number' && !isNaN(rank) && rank > 0) {
return rank + offset;
}
offset += group.order.length;
}
return -1;
return ranking.getRank(row);
}

getValue(row: IDataRow) {
Expand Down
14 changes: 12 additions & 2 deletions src/model/Ranking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,9 @@ export default class Ranking extends AEventDispatcher implements IColumnParent {
* the current ordering as an sorted array of indices
* @type {Array}
*/
private groups: IOrderedGroup[] = [Object.assign({order: <number[]>[], index2pos: <number[]>[]}, defaultGroup)];
private groups: IOrderedGroup[] = [Object.assign({order: <number[]>[]}, defaultGroup)];
private order: IndicesArray = [];
private index2pos: IndicesArray = [];

constructor(public id: string) {
super();
Expand Down Expand Up @@ -202,14 +203,23 @@ export default class Ranking extends AEventDispatcher implements IColumnParent {
this.fire(Ranking.EVENT_LABEL_CHANGED, this.label, this.label = value);
}

setGroups(groups: IOrderedGroup[]) {
setGroups(groups: IOrderedGroup[], index2pos: IndicesArray) {
const old = this.order;
const oldGroups = this.groups;
this.groups = groups;
this.index2pos = index2pos;
this.order = toOrder(groups);
this.fire([Ranking.EVENT_ORDER_CHANGED, Ranking.EVENT_GROUPS_CHANGED, Ranking.EVENT_DIRTY_VALUES, Ranking.EVENT_DIRTY], old, this.order, oldGroups, groups);
}

getRank(row: IDataRow) {
if (row.i < 0 || row.i > this.index2pos.length) {
return -1;
}
const v = this.index2pos[row.i];
return v != null && !isNaN(v) && v > 0 ? v : -1;
}

getOrder() {
return this.order;
}
Expand Down
8 changes: 0 additions & 8 deletions src/provider/ACommonDataProvider.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {createAggregateDesc, createRankDesc, createSelectionDesc, IColumnDesc, IDataRow, isSupportType} from '../model';
import {IOrderedGroup} from '../model/Group';
import Ranking from '../model/Ranking';
import ADataProvider from './ADataProvider';
import {IDataProviderOptions} from './interfaces';
Expand Down Expand Up @@ -70,13 +69,6 @@ abstract class ACommonDataProvider extends ADataProvider {
return clone;
}

sort(ranking: Ranking): Promise<IOrderedGroup[]> | IOrderedGroup[] {
//use the server side to sort
return this.sortImpl(ranking);
}

protected abstract sortImpl(ranking: Ranking): Promise<IOrderedGroup[]> | IOrderedGroup[];

/**
* adds another column description to this data provider
* @param column
Expand Down
8 changes: 4 additions & 4 deletions src/provider/ADataProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,9 @@ abstract class ADataProvider extends AEventDispatcher implements IDataProvider {

protected triggerReorder(ranking: Ranking) {
this.fireBusy(true);
Promise.resolve(this.sort(ranking)).then((order) => {
unifyParents(order);
ranking.setGroups(order);
Promise.resolve(this.sort(ranking)).then(({groups, index2pos}) => {
unifyParents(groups);
ranking.setGroups(groups, index2pos);
this.fireBusy(false);
});
}
Expand Down Expand Up @@ -657,7 +657,7 @@ abstract class ADataProvider extends AEventDispatcher implements IDataProvider {
* @param ranking
* @return {Promise<any>}
*/
abstract sort(ranking: Ranking): Promise<IOrderedGroup[]> | IOrderedGroup[];
abstract sort(ranking: Ranking): Promise<{groups: IOrderedGroup[], index2pos: IndicesArray}> | {groups: IOrderedGroup[], index2pos: IndicesArray};

/**
* returns a view in the order of the given indices
Expand Down
38 changes: 27 additions & 11 deletions src/provider/LocalDataProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,9 @@ export default class LocalDataProvider extends ACommonDataProvider {
super.cleanUpRanking(ranking);
}

sortImpl(ranking: Ranking): IOrderedGroup[] | Promise<IOrderedGroup[]> {
sort(ranking: Ranking) {
if (this._data.length === 0) {
return [];
return {groups: [], index2pos: []};
}
//do the optional filtering step
let filter: ((d: IDataRow) => boolean) | null = null;
Expand Down Expand Up @@ -178,11 +178,12 @@ export default class LocalDataProvider extends ACommonDataProvider {
order[i] = i;
index2pos[i] = i + 1; // shift since default is 0
}
return [Object.assign({order, index2pos}, defaultGroup)];
return {groups: [Object.assign({order}, defaultGroup)], index2pos};
}

const groups = new Map<string, ISortHelper>();
const lookups = isSortedBy ? new CompareLookup(this._data.length, ranking.toCompareValueType()) : undefined;
let maxDataIndex = -1;

for (const r of this._dataRows) {
if (filter && !filter(r)) {
Expand All @@ -198,20 +199,23 @@ export default class LocalDataProvider extends ACommonDataProvider {
} else {
groups.set(groupKey, {group, rows: [r.i]});
}
if (maxDataIndex < r.i) {
maxDataIndex = r.i;
}
}

if (groups.size === 0) {
return [];
return {groups: [], index2pos: []};
}

const groupLookup = isGroupedSortedBy ? new CompareLookup(groups.size, ranking.toGroupCompareValueType()) : undefined;

return Promise.all(Array.from(groups.values()).map((g, i) => {
const group = g.group;
return this.sortWorker.sort(this._data.length, g.rows, groups.size === 1, lookups)
return this.sortWorker.sort(g.rows, groups.size === 1, lookups)
// to group info
.then(({order, index2pos}) => {
const o: IOrderedGroup = Object.assign({order, index2pos}, group);
.then((order) => {
const o: IOrderedGroup = Object.assign({order}, group);

// compute sort group value
if (groupLookup) {
Expand All @@ -223,11 +227,23 @@ export default class LocalDataProvider extends ACommonDataProvider {
})).then((groups) => {
// sort groups
if (!groupLookup) {
return groups.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()));
groups.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()));
} else {
const groupIndices = groups.map((_, i) => i);
sortComplex(groupIndices, groupLookup.sortOrders);
groups = groupIndices.map((i) => groups[i]);
}

const index2pos = chooseByLength(maxDataIndex + 1);
let offset = 1;
for (const g of groups) {
// tslint:disable-next-line
for (let i = 0; i < g.order.length; i++ , offset++) {
index2pos[g.order[i]] = offset;
}
}
const groupIndices = groups.map((_, i) => i);
sortComplex(groupIndices, groupLookup.sortOrders);
return groupIndices.map((i) => groups[i]);

return {groups, index2pos};
});
}

Expand Down
8 changes: 4 additions & 4 deletions src/provider/RemoteDataProvider.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Column, {IColumnDesc, IDataRow} from '../model';
import {defaultGroup, IOrderedGroup} from '../model/Group';
import {defaultGroup} from '../model/Group';
import Ranking from '../model/Ranking';
import ACommonDataProvider from './ACommonDataProvider';
import {IDataProviderOptions, IStatsBuilder} from './interfaces';
Expand Down Expand Up @@ -47,7 +47,7 @@ export interface IRemoteDataProviderOptions {
function createIndex2Pos(order: number[]) {
const index2pos = <number[]>[];
for (let i = 0; i < order.length; ++i) {
index2pos[order[i]] = i;
index2pos[order[i]] = i + 1;
}
return index2pos;
}
Expand All @@ -73,9 +73,9 @@ export default class RemoteDataProvider extends ACommonDataProvider {
return this.cache.size;
}

sortImpl(ranking: Ranking): Promise<IOrderedGroup[]> {
sort(ranking: Ranking) {
//use the server side to sort
return this.server.sort(ranking).then((order) => [Object.assign({order, index2pos: createIndex2Pos(order)}, defaultGroup)]);
return this.server.sort(ranking).then((order) => ({groups: [Object.assign({order}, defaultGroup)], index2pos: createIndex2Pos(order)}));
}

private loadFromServer(indices: number[]) {
Expand Down
Loading

0 comments on commit 6a8f9db

Please sign in to comment.