mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-12 05:36:59 -04:00
added order_by support to position function, orders are cached; TODO: clear the cache when a card changes
git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@109 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
+37
-14
@@ -14,6 +14,7 @@
|
|||||||
#include <data/field.hpp>
|
#include <data/field.hpp>
|
||||||
#include <data/field/text.hpp> // for 0.2.7 fix
|
#include <data/field/text.hpp> // for 0.2.7 fix
|
||||||
#include <util/tagged_string.hpp> // for 0.2.7 fix
|
#include <util/tagged_string.hpp> // for 0.2.7 fix
|
||||||
|
#include <util/order_cache.hpp>
|
||||||
#include <script/value.hpp>
|
#include <script/value.hpp>
|
||||||
#include <script/script_manager.hpp>
|
#include <script/script_manager.hpp>
|
||||||
#include <wx/sstream.h>
|
#include <wx/sstream.h>
|
||||||
@@ -100,20 +101,6 @@ void Set::validate(Version file_app_version) {
|
|||||||
*/ }
|
*/ }
|
||||||
}
|
}
|
||||||
|
|
||||||
void mark_dependency_member(Set* value, const String& name, const Dependency& dep) {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
void mark_dependency_member(const SetP& value, const String& name, const Dependency& dep) {
|
|
||||||
mark_dependency_member(value.get(), name, dep);
|
|
||||||
}
|
|
||||||
|
|
||||||
// in scripts, set.something is read from the set_info
|
|
||||||
template <typename Tag>
|
|
||||||
void reflect_set_info_get_member(Tag& tag, const IndexMap<FieldP, ValueP>& data) {}
|
|
||||||
void reflect_set_info_get_member(GetMember& tag, const IndexMap<FieldP, ValueP>& data) {
|
|
||||||
REFLECT_NAMELESS(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_REFLECTION(Set) {
|
IMPLEMENT_REFLECTION(Set) {
|
||||||
tag.addAlias(300, _("style"), _("stylesheet")); // < 0.3.0 used style instead of stylesheet
|
tag.addAlias(300, _("style"), _("stylesheet")); // < 0.3.0 used style instead of stylesheet
|
||||||
tag.addAlias(300, _("extra set info"), _("styling"));
|
tag.addAlias(300, _("extra set info"), _("styling"));
|
||||||
@@ -135,6 +122,42 @@ IMPLEMENT_REFLECTION(Set) {
|
|||||||
REFLECT(apprentice_code);
|
REFLECT(apprentice_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Script utilities
|
||||||
|
|
||||||
|
ScriptValueP make_iterator(const Set& set) {
|
||||||
|
return new_intrusive1<ScriptCollectionIterator<vector<CardP> > >(&set.cards);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mark_dependency_member(Set* value, const String& name, const Dependency& dep) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
void mark_dependency_member(const SetP& value, const String& name, const Dependency& dep) {
|
||||||
|
mark_dependency_member(value.get(), name, dep);
|
||||||
|
}
|
||||||
|
|
||||||
|
// in scripts, set.something is read from the set_info
|
||||||
|
template <typename Tag>
|
||||||
|
void reflect_set_info_get_member(Tag& tag, const IndexMap<FieldP, ValueP>& data) {}
|
||||||
|
void reflect_set_info_get_member(GetMember& tag, const IndexMap<FieldP, ValueP>& data) {
|
||||||
|
REFLECT_NAMELESS(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Set::positionOfCard(const CardP& card, const ScriptValueP& order_by) {
|
||||||
|
// TODO : Lock the map?
|
||||||
|
assert(order_by);
|
||||||
|
OrderCacheP& order = order_cache[order_by];
|
||||||
|
if (!order) {
|
||||||
|
// 1. make a list of the order value for each card
|
||||||
|
vector<String> values; values.reserve(cards.size());
|
||||||
|
FOR_EACH_CONST(c, cards) {
|
||||||
|
values.push_back(*order_by->eval(getContext(c)));
|
||||||
|
}
|
||||||
|
// 2. initialize order cache
|
||||||
|
order.reset(new OrderCache<CardP>(cards, values));
|
||||||
|
}
|
||||||
|
return order->find(card);
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Styling
|
// ----------------------------------------------------------------------------- : Styling
|
||||||
|
|
||||||
// Extra set data, for a specific stylesheet
|
// Extra set data, for a specific stylesheet
|
||||||
|
|||||||
@@ -23,9 +23,12 @@ DECLARE_POINTER_TYPE(Styling);
|
|||||||
DECLARE_POINTER_TYPE(Field);
|
DECLARE_POINTER_TYPE(Field);
|
||||||
DECLARE_POINTER_TYPE(Value);
|
DECLARE_POINTER_TYPE(Value);
|
||||||
DECLARE_POINTER_TYPE(Keyword);
|
DECLARE_POINTER_TYPE(Keyword);
|
||||||
|
DECLARE_INTRUSIVE_POINTER_TYPE(ScriptValue);
|
||||||
class ScriptManager;
|
class ScriptManager;
|
||||||
class Context;
|
class Context;
|
||||||
class Dependency;
|
class Dependency;
|
||||||
|
template <typename> class OrderCache;
|
||||||
|
typedef shared_ptr<OrderCache<CardP> > OrderCacheP;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Set
|
// ----------------------------------------------------------------------------- : Set
|
||||||
|
|
||||||
@@ -81,6 +84,9 @@ class Set : public Packaged {
|
|||||||
throw InternalError(_("Expected a set field with name '")+name+_("'"));
|
throw InternalError(_("Expected a set field with name '")+name+_("'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Find the position of a card in this set, when the card list is sorted using the given cirterium
|
||||||
|
int positionOfCard(const CardP& card, const ScriptValueP& order_by);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual String typeName() const;
|
virtual String typeName() const;
|
||||||
virtual void validate(Version);
|
virtual void validate(Version);
|
||||||
@@ -89,11 +95,14 @@ class Set : public Packaged {
|
|||||||
private:
|
private:
|
||||||
/// Object for managing and executing scripts
|
/// Object for managing and executing scripts
|
||||||
scoped_ptr<ScriptManager> script_manager;
|
scoped_ptr<ScriptManager> script_manager;
|
||||||
|
/// Cache of cards ordered by some criterion
|
||||||
|
map<ScriptValueP,OrderCacheP> order_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline int item_count(const Set& set) {
|
inline int item_count(const Set& set) {
|
||||||
return (int)set.cards.size();
|
return (int)set.cards.size();
|
||||||
}
|
}
|
||||||
|
ScriptValueP make_iterator(const Set& set);
|
||||||
|
|
||||||
void mark_dependency_member(const SetP& value, const String& name, const Dependency& dep);
|
void mark_dependency_member(const SetP& value, const String& name, const Dependency& dep);
|
||||||
void mark_dependency_member(Set* value, const String& name, const Dependency& dep);
|
void mark_dependency_member(Set* value, const String& name, const Dependency& dep);
|
||||||
|
|||||||
@@ -378,7 +378,7 @@ void TextValueEditor::showCaret() {
|
|||||||
// it is not 0 for empty text, because TextRenderer handles that case
|
// it is not 0 for empty text, because TextRenderer handles that case
|
||||||
if (cursor.height == 0) {
|
if (cursor.height == 0) {
|
||||||
if (style().always_symbol && style().symbol_font.valid()) {
|
if (style().always_symbol && style().symbol_font.valid()) {
|
||||||
RealSize s = style().symbol_font.font->defaultSymbolSize(viewer.getContext(), rot.trS(1));
|
RealSize s = style().symbol_font.font->defaultSymbolSize(viewer.getContext(), rot.trS(style().symbol_font.size));
|
||||||
cursor.height = s.height;
|
cursor.height = s.height;
|
||||||
} else {
|
} else {
|
||||||
cursor.height = v.heightOfLastLine();
|
cursor.height = v.heightOfLastLine();
|
||||||
|
|||||||
@@ -1135,6 +1135,9 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath=".\util\for_each.hpp">
|
RelativePath=".\util\for_each.hpp">
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\util\order_cache.hpp">
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\util\prec.hpp">
|
RelativePath=".\util\prec.hpp">
|
||||||
</File>
|
</File>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <script/value.hpp>
|
#include <script/value.hpp>
|
||||||
#include <script/context.hpp>
|
#include <script/context.hpp>
|
||||||
#include <util/tagged_string.hpp>
|
#include <util/tagged_string.hpp>
|
||||||
|
#include <data/set.hpp>
|
||||||
#include <wx/regex.h>
|
#include <wx/regex.h>
|
||||||
|
|
||||||
DECLARE_TYPEOF_COLLECTION(UInt);
|
DECLARE_TYPEOF_COLLECTION(UInt);
|
||||||
@@ -370,14 +371,53 @@ SCRIPT_RULE_1(tag_remove, String, tag) {
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Vector stuff
|
// ----------------------------------------------------------------------------- : Vector stuff
|
||||||
|
|
||||||
|
/// compare script values for equallity
|
||||||
|
bool equal(const ScriptValue& a, const ScriptValue& b) {
|
||||||
|
ScriptType at = a.type(), bt = b.type();
|
||||||
|
if (at != bt) {
|
||||||
|
return false;
|
||||||
|
} else if (at == SCRIPT_INT) {
|
||||||
|
return (int)a == (int)b;
|
||||||
|
} else if (at == SCRIPT_DOUBLE) {
|
||||||
|
return (double)a == (double)b;
|
||||||
|
} else if (at == SCRIPT_STRING) {
|
||||||
|
return (String)a == (String)b;
|
||||||
|
} else if (at == SCRIPT_OBJECT) {
|
||||||
|
// HACK for ScriptObject<shared_ptr<X> >
|
||||||
|
// assumes different types are layed out the same, and that
|
||||||
|
// should be void*, but then we need getMember for void
|
||||||
|
const ScriptObject<int*>& av = reinterpret_cast<const ScriptObject<int*>&>(a);
|
||||||
|
const ScriptObject<int*>& bv = reinterpret_cast<const ScriptObject<int*>&>(b);
|
||||||
|
return av.getValue() == bv.getValue();
|
||||||
|
}
|
||||||
|
return &a == &b;
|
||||||
|
}
|
||||||
|
|
||||||
/// position of some element in a vector
|
/// position of some element in a vector
|
||||||
/** 0 based index, -1 if not found */
|
/** 0 based index, -1 if not found */
|
||||||
int position_in_vector(const ScriptValueP& of, const ScriptValueP& in, const ScriptValueP& order_by) {
|
int position_in_vector(const ScriptValueP& of, const ScriptValueP& in, const ScriptValueP& order_by) {
|
||||||
ScriptType of_t = of->type(), in_t = in->type();
|
ScriptType of_t = of->type(), in_t = in->type();
|
||||||
if (of_t == SCRIPT_STRING || in_t == SCRIPT_STRING) {
|
if (of_t == SCRIPT_STRING || in_t == SCRIPT_STRING) {
|
||||||
|
// string finding
|
||||||
return (int)((String)*of).find(*in); // (int)npos == -1
|
return (int)((String)*of).find(*in); // (int)npos == -1
|
||||||
|
} else if (order_by) {
|
||||||
|
ScriptObject<Set*>* s = dynamic_cast<ScriptObject<Set*>* >(in.get());
|
||||||
|
ScriptObject<CardP>* c = dynamic_cast<ScriptObject<CardP>*>(of.get());
|
||||||
|
if (s && c) {
|
||||||
|
return s->getValue()->positionOfCard(c->getValue(), order_by);
|
||||||
|
} else {
|
||||||
|
throw ScriptError(_("position: using 'order_by' is only supported for finding cards in the set"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// unordered position
|
||||||
|
ScriptValueP it = in->makeIterator();
|
||||||
|
int i = 0;
|
||||||
|
while (ScriptValueP v = it->next()) {
|
||||||
|
if (equal(*of, *v)) return i;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return -1; // TODO
|
return -1; // TODO?
|
||||||
}
|
}
|
||||||
|
|
||||||
// finding positions, also of substrings
|
// finding positions, also of substrings
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ ScriptValueP ScriptValue::dependencies(Context&, const Dependency&
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Iterators
|
// ----------------------------------------------------------------------------- : Iterators
|
||||||
|
|
||||||
ScriptType ScriptIterator::type() const { return SCRIPT_OBJECT; }
|
ScriptType ScriptIterator::type() const { return SCRIPT_ITERATOR; }
|
||||||
String ScriptIterator::typeName() const { return _("iterator"); }
|
String ScriptIterator::typeName() const { return _("iterator"); }
|
||||||
|
|
||||||
// Iterator over a range of integers
|
// Iterator over a range of integers
|
||||||
|
|||||||
+17
-5
@@ -10,6 +10,7 @@
|
|||||||
// ----------------------------------------------------------------------------- : Includes
|
// ----------------------------------------------------------------------------- : Includes
|
||||||
|
|
||||||
#include <util/prec.hpp>
|
#include <util/prec.hpp>
|
||||||
|
#include <util/reflect.hpp>
|
||||||
#include <util/error.hpp>
|
#include <util/error.hpp>
|
||||||
class Context;
|
class Context;
|
||||||
class Dependency;
|
class Dependency;
|
||||||
@@ -37,7 +38,9 @@ enum ScriptType
|
|||||||
, SCRIPT_COLOR
|
, SCRIPT_COLOR
|
||||||
, SCRIPT_IMAGE
|
, SCRIPT_IMAGE
|
||||||
, SCRIPT_FUNCTION
|
, SCRIPT_FUNCTION
|
||||||
, SCRIPT_OBJECT
|
, SCRIPT_OBJECT // Only ScriptObject
|
||||||
|
, SCRIPT_COLLECTION
|
||||||
|
, SCRIPT_ITERATOR
|
||||||
, SCRIPT_DUMMY
|
, SCRIPT_DUMMY
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -121,7 +124,7 @@ extern ScriptValueP dependency_dummy; ///< Dummy value used during dependency an
|
|||||||
|
|
||||||
// Iterator over a collection
|
// Iterator over a collection
|
||||||
struct ScriptIterator : public ScriptValue {
|
struct ScriptIterator : public ScriptValue {
|
||||||
virtual ScriptType type() const;// { return SCRIPT_OBJECT; }
|
virtual ScriptType type() const;// { return SCRIPT_ITERATOR; }
|
||||||
virtual String typeName() const;// { return "iterator"; }
|
virtual String typeName() const;// { return "iterator"; }
|
||||||
|
|
||||||
/// Return the next item for this iterator, or ScriptValueP() if there is no such item
|
/// Return the next item for this iterator, or ScriptValueP() if there is no such item
|
||||||
@@ -155,7 +158,7 @@ template <typename Collection>
|
|||||||
class ScriptCollection : public ScriptValue {
|
class ScriptCollection : public ScriptValue {
|
||||||
public:
|
public:
|
||||||
inline ScriptCollection(const Collection* v) : value(v) {}
|
inline ScriptCollection(const Collection* v) : value(v) {}
|
||||||
virtual ScriptType type() const { return SCRIPT_OBJECT; }
|
virtual ScriptType type() const { return SCRIPT_COLLECTION; }
|
||||||
virtual String typeName() const { return _("collection"); }
|
virtual String typeName() const { return _("collection"); }
|
||||||
virtual ScriptValueP getMember(const String& name) const {
|
virtual ScriptValueP getMember(const String& name) const {
|
||||||
long index;
|
long index;
|
||||||
@@ -201,7 +204,7 @@ template <typename Collection>
|
|||||||
class ScriptMap : public ScriptValue {
|
class ScriptMap : public ScriptValue {
|
||||||
public:
|
public:
|
||||||
inline ScriptMap(const Collection* v) : value(v) {}
|
inline ScriptMap(const Collection* v) : value(v) {}
|
||||||
virtual ScriptType type() const { return SCRIPT_OBJECT; }
|
virtual ScriptType type() const { return SCRIPT_COLLECTION; }
|
||||||
virtual String typeName() const { return _("collection"); }
|
virtual String typeName() const { return _("collection"); }
|
||||||
virtual ScriptValueP getMember(const String& name) const {
|
virtual ScriptValueP getMember(const String& name) const {
|
||||||
return get_member(*value, name);
|
return get_member(*value, name);
|
||||||
@@ -219,6 +222,11 @@ template <typename T>
|
|||||||
int item_count(const T& v) {
|
int item_count(const T& v) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
/// Return an iterator for some collection, can be overloaded
|
||||||
|
template <typename T>
|
||||||
|
ScriptValueP make_iterator(const T& v) {
|
||||||
|
return ScriptValueP();
|
||||||
|
}
|
||||||
|
|
||||||
/// Mark a dependency on a member of value, can be overloaded
|
/// Mark a dependency on a member of value, can be overloaded
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -253,12 +261,16 @@ class ScriptObject : public ScriptValue {
|
|||||||
mark_dependency_member(value, name, dep);
|
mark_dependency_member(value, name, dep);
|
||||||
return getMember(name);
|
return getMember(name);
|
||||||
}
|
}
|
||||||
|
virtual ScriptValueP makeIterator() const {
|
||||||
|
ScriptValueP it = make_iterator(*value);
|
||||||
|
return it ? it : ScriptValue::makeIterator();
|
||||||
|
}
|
||||||
virtual int itemCount() const {
|
virtual int itemCount() const {
|
||||||
int i = item_count(*value);
|
int i = item_count(*value);
|
||||||
return i >= 0 ? i : ScriptValue::itemCount();
|
return i >= 0 ? i : ScriptValue::itemCount();
|
||||||
}
|
}
|
||||||
/// Get access to the value
|
/// Get access to the value
|
||||||
inline T getValue() { return value; }
|
inline T getValue() const { return value; }
|
||||||
private:
|
private:
|
||||||
T value; ///< The object
|
T value; ///< The object
|
||||||
ScriptValueP getDefault() const {
|
ScriptValueP getDefault() const {
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
//+----------------------------------------------------------------------------+
|
||||||
|
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
|
||||||
|
//| Copyright: (C) 2001 - 2006 Twan van Laarhoven |
|
||||||
|
//| License: GNU General Public License 2 or later (see file COPYING) |
|
||||||
|
//+----------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
#ifndef HEADER_UTIL_ORDER_CACHE
|
||||||
|
#define HEADER_UTIL_ORDER_CACHE
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Includes
|
||||||
|
|
||||||
|
#include <util/prec.hpp>
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : OrderCache
|
||||||
|
|
||||||
|
/// Object that cashes an ordered version of a list of items, for finding the position of objects
|
||||||
|
/** Can be used as a map "void* -> int" for finding the position of an object */
|
||||||
|
template <typename T>
|
||||||
|
class OrderCache {
|
||||||
|
public:
|
||||||
|
/// Initialize the order cache, ordering the keys by their string values from the other vector
|
||||||
|
/** @pre keys.size() == values.size() */
|
||||||
|
OrderCache(const vector<T>& keys, const vector<String>& values);
|
||||||
|
|
||||||
|
/// Find the position of the given key in the cache, returns -1 if not found
|
||||||
|
int find(const T& key) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct CompareKeys;
|
||||||
|
struct CompareValues;
|
||||||
|
typedef pair<void*,int> KV;
|
||||||
|
vector<KV> positions;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : Implementation
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct OrderCache<T>::CompareKeys {
|
||||||
|
inline bool operator () (const KV& a, void* b) { return a.first < b; }
|
||||||
|
inline bool operator () (const KV& a, const KV& b) { return a.first < b.first; }
|
||||||
|
inline bool operator () (void* a, const KV& b) { return a < b.first; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct OrderCache<T>::CompareValues {
|
||||||
|
const vector<String>& values;
|
||||||
|
CompareValues(const vector<String>& values) : values(values) {}
|
||||||
|
|
||||||
|
inline bool operator () (const KV& a, const KV& b) {
|
||||||
|
return values[a.second] < values[b.second];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
OrderCache<T>::OrderCache(const vector<T>& keys, const vector<String>& values) {
|
||||||
|
assert(keys.size() == values.size());
|
||||||
|
// initialize positions, use pos to point back to the values vector
|
||||||
|
positions.reserve(keys.size());
|
||||||
|
int i = 0;
|
||||||
|
for (vector<T>::const_iterator it = keys.begin() ; it != keys.end() ; ++it, ++i) {
|
||||||
|
positions.push_back(KV(&**it, i));
|
||||||
|
}
|
||||||
|
// sort the KVs by the values
|
||||||
|
sort(positions.begin(), positions.end(), CompareValues(values));
|
||||||
|
// update positions, to point to sorted list
|
||||||
|
i = 0;
|
||||||
|
for (vector<KV>::iterator it = positions.begin() ; it != positions.end() ; ++it, ++i) {
|
||||||
|
it->second = i;
|
||||||
|
}
|
||||||
|
// sort the KVs by the keys
|
||||||
|
sort(positions.begin(), positions.end(), CompareKeys());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
int OrderCache<T>::find(const T& key) const {
|
||||||
|
vector<KV>::const_iterator it = lower_bound(positions.begin(), positions.end(), &*key, CompareKeys());
|
||||||
|
if (it == positions.end() || it->first != &*key) return -1;
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------- : EOF
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user