Last active
February 21, 2020 22:58
-
-
Save AustinEast/52b873e850c35cf5ed6e933240df21b7 to your computer and use it in GitHub Desktop.
Simple Store Abstract For Haxe
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
using Math; | |
/** | |
* A Simple Store of Data that is accessible through Queries. It is Abstracted over the Array type, so casting between the two is supported. | |
*/ | |
abstract Store<T>(Array<T>) from Array<T> to Array<T> { | |
public inline function new(?v:Array<T>) this = v == null ? [] : v; | |
/** | |
* Gets the first item that matches the Query. | |
*/ | |
public inline function get(query:Query<T>):Null<QueryResult<T>> { | |
var min = (query.min == null ? 0 : query.min).min(this.length).max(0).floor(); | |
var max = (query.max == null ? this.length : query.max).min(this.length).max(min).floor(); | |
if (query.id != null) return query.id >= min && query.id <= max ? { | |
id: query.id, | |
item: this[query.id] | |
} : null; | |
var item = null; | |
var id = 0; | |
for (i in min...max) { | |
id = i; | |
item = this[i]; | |
if (this[i] == null) continue; | |
// Check if the item matches all the values | |
if (query.values != null) for (j in 0...query.values.length) { | |
var val = Reflect.field(item, query.values[j].field); | |
if (val != null && val == query.values[j].value) continue; | |
item = null; | |
break; | |
} | |
// Check if the item matches the filter | |
if (item != null && query.filter != null && !query.filter(item)) item = null; | |
// If we have an item still, break out of the loop and return it | |
if (item != null) break; | |
} | |
return item == null ? null : { | |
id: id, | |
item: item | |
}; | |
} | |
/** | |
* Gets all items that match the Query. | |
*/ | |
public inline function get_all(query:Query<T>):Array<QueryResult<T>> { | |
var arr = []; | |
var min:Int = query.min == null ? 0 : query.min; | |
while (min < this.length) { | |
query.min = min; | |
var result = get(query); | |
if (result != null) { | |
arr.push(result); | |
min = result.id + 1; | |
} | |
else min = this.length; | |
} | |
return arr; | |
} | |
/** | |
* Gets the id of an item. If the item doesn't exist in the store, this returns -1. | |
* @param item The item to get the id for. | |
* @param from The starting id to search the Store for. | |
* @return The id of the item, or -1 if the item's id is not found. | |
*/ | |
public inline function get_id(item:T, from:Int = 0):Int return this.indexOf(item, from); | |
/** | |
* Sets an item in the Store. If an id is not specified, the item is added as a new entry to the Store. | |
* @param item The item to set in the Store. | |
* @param id The id of the item. If not set, the item will be added as a new entry in the Store. | |
* @return The id of the item. | |
*/ | |
public function set(item:T, ?id:Null<Int>):Int { | |
if (id != null) { | |
this[id] = item; | |
return id; | |
} | |
return this.push(item) - 1; | |
} | |
/** | |
* Adds an item to the Store. | |
* @param item The item to add to the Store. | |
* @return The id of the item. | |
*/ | |
public inline function add(item:T):Int return set(item); | |
/** | |
* Adds an Array of items to the Store. | |
* @param items Array of items to add to the Store. | |
*/ | |
public inline function add_all(items:Array<T>):Void for (v in items) add(v); | |
} | |
@:structInit | |
class Query<T> { | |
/** | |
* Id to search for items in a Store. | |
*/ | |
@:optional public var id:Null<Int>; | |
/** | |
* Minimum id to search for items in a Store. | |
*/ | |
@:optional public var min:Null<Int>; | |
/** | |
* Maximum id to search for items in a Store. | |
*/ | |
@:optional public var max:Null<Int>; | |
/** | |
* Array of QueryValues to compare against items in a Store. | |
*/ | |
@:optional public var values:Null<Array<QueryValue>>; | |
/** | |
* Method to filter items against in a Store. | |
*/ | |
@:optional public var filter:Null<T->Bool>; | |
} | |
@:structInit | |
class QueryResult<T> { | |
/** | |
* Id of the Queried item. | |
*/ | |
public var id:Int; | |
/** | |
* The Queried item. | |
*/ | |
public var item:T; | |
public function toString() return 'QueryResult ( id: $id, item: $item )'; | |
} | |
@:structInit | |
class QueryValue { | |
/** | |
* Name of the field to compare. | |
*/ | |
public var field:String; | |
/** | |
* Value of the field to compare. | |
*/ | |
public var value:Dynamic; | |
} |
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
class Test { | |
/** | |
* Test usage of Store.hx | |
*/ | |
static function main() { | |
// Create a new Store | |
var store = new Store<Person>(); | |
// Add a bunch of items to the Store | |
for (i in 0...100) { | |
store.add(new Person()); | |
} | |
// Get everyone named Bob who is over the age of 18 | |
var results = store.get_all({ | |
values: [{field: 'name', value: 'Bob'}], | |
filter: (person) -> return person.age > 18 | |
}); | |
// Change every found Bob's name to Rachel | |
for (result in results) result.item.name = 'Rachel'; | |
// Get the Person with id 5 | |
trace(store.get({ | |
id: 5 | |
})); | |
// Get all Bobs | |
trace(store.get_all({ | |
values: [{field: 'name', value: 'Bob'}] | |
})); | |
// Get all Rachels | |
trace(store.get_all({ | |
values: [{field: 'name', value: 'Rachel'}] | |
})); | |
// Get the first person with an age under 50 | |
trace(store.get({ | |
filter: (person) -> return person.age < 50 | |
})); | |
} | |
} | |
class Person { | |
static var possible_names = ['Austin', 'Bob', 'Sandra']; | |
public var name:String; | |
public var age:Int; | |
public function new() { | |
name = possible_names[Std.random(3)]; | |
age = Std.random(100); | |
} | |
public function toString() return '$name, age $age'; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment