Skip to content

Commit 5ecb2ad

Browse files
committed
IncludeExcludeList model for managing and serializing favorites/exclude/pin items
1 parent 504213c commit 5ecb2ad

File tree

1 file changed

+96
-0
lines changed

1 file changed

+96
-0
lines changed

src/model/IncludeExcludeList.ts

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import * as _ from 'lodash';
2+
3+
export enum IEList { //these are flags so no direct equals, nothing requires them to be used as flags, but it would allow you to have an entry on both Include and Favorite at the same type
4+
Invalid = 0,
5+
Include = 1 << 1,
6+
Exclude = 1 << 2,
7+
Favorite = 1 << 3,
8+
}
9+
10+
function* mapIterableImpl<T, U>(f: (val: T) => U, iterable: Iterable<T>): Iterable<U> {
11+
for (const item of iterable) {
12+
yield f(item);
13+
}
14+
}
15+
const mapIterable = <T, U>(f: (val: T) => U) => (iterable: Iterable<T>) => mapIterableImpl(f, iterable);
16+
function* filterIterableImpl<T>(f: (item: T) => boolean, iterable: Iterable<T>): Iterable<T> {
17+
for (const item of iterable) {
18+
if (f(item)) {
19+
yield item;
20+
}
21+
}
22+
}
23+
const filterIterable = <T>(f: (val: T) => boolean) => (iterable: Iterable<T>) => filterIterableImpl(f, iterable);
24+
25+
interface SerializeData<ListKeyType>{
26+
known : Map<ListKeyType, IEList>;
27+
}
28+
type ItemResolver<T, TResult> = (value: T) => TResult;
29+
30+
export class IncludeExcludeList<ListKeyType> {
31+
32+
protected known = new Map<ListKeyType, IEList>();
33+
34+
GetSaveDataObject() : Object {
35+
return {known:new Map(this.known)} as SerializeData<ListKeyType>;
36+
}
37+
static LoadFromSaveDataObject<ListKeyType>(object : object) : IncludeExcludeList<ListKeyType> {
38+
let ret = new IncludeExcludeList<ListKeyType>();
39+
ret.known = new Map((object as SerializeData<ListKeyType>).known);
40+
return ret;
41+
}
42+
43+
AddOrUpdateToList = (key: ListKeyType, list: IEList) => this.known.set(key, list);
44+
RemoveFromLists = (key: ListKeyType) => this.known.delete(key);
45+
ClearList(list: IEList){
46+
let keys = this.GetKeysOnList(list);
47+
for (const key of keys)
48+
this.RemoveFromList(key,list);
49+
}
50+
RemoveFromList(key: ListKeyType, list: IEList){
51+
let current = this.GetKeyList(key);
52+
if (current == undefined)
53+
return;
54+
current &= ~list;
55+
if (current == IEList.Invalid)
56+
this.known.delete(key);
57+
else
58+
this.AddOrUpdateToList(key, current);
59+
}
60+
61+
GetKeyList = (key: ListKeyType) => this.known.get(key);
62+
GetKeysOnList(list: IEList) : ListKeyType[] {
63+
let filtered = filterIterable((kvp : [ListKeyType, IEList]) => (kvp[1] & list) != 0)(this.known.entries());
64+
let mapped = mapIterable((kvp : [ListKeyType, IEList]) => kvp[0])(filtered);
65+
return Array.from( mapped );
66+
}
67+
IsKeyOnList(key : ListKeyType, list: IEList, trueIfUnknown : boolean = false){
68+
let val = this.GetKeyList(key);
69+
if (val === undefined)
70+
return trueIfUnknown;
71+
return (val & list) != 0;
72+
}
73+
74+
/// returnUnknown true if you want items not on any list, false if they should be excluded
75+
FilterArrayAgainstList<T>(arr: Iterable<T>, list: IEList, returnUnknown : boolean = false, resolver : ItemResolver<T,ListKeyType>|undefined=undefined) : Iterable<T>{
76+
if (!resolver)
77+
resolver = (itm) => itm as any;
78+
return filterIterable( (key : T) => this.IsKeyOnList(resolver!(key),list,returnUnknown))(arr);
79+
}
80+
81+
/// return the list in the same order passed in except all items that are on the specified list are returned first
82+
* SortArrayAgainstList<T>(arr: Iterable<T>, list: IEList, resolver : ItemResolver<T,ListKeyType>|undefined=undefined) : IterableIterator<T> {
83+
let after = new Array() as Array<T>;
84+
if (! resolver)
85+
resolver = (itm) => itm as any;
86+
for (const item of arr) {
87+
if (this.IsKeyOnList(resolver(item),list))
88+
yield item;
89+
else
90+
after.push(item);
91+
}
92+
for (const itm of after)
93+
yield itm;
94+
}
95+
96+
}

0 commit comments

Comments
 (0)