How to dequeueCell in a CCTableView with multiple custom CCTableViewCell’s? - c++

I have a CCTableView that i would like to use multiple custom CCTableViewCells, but it seems that dequeueCell treats all cells as if they were the same. The other option is to have a different cell for each row but this is not performant.
Oh and this is cocos2dx v2.2

I actually came up with a decent solution but it requires adding this member to CCTableView
CCTableViewCell *CCTableView::dequeueCellWithTag(int nTag)
{
CCTableViewCell *cell = NULL;
for (int i = 0, len = m_pCellsFreed->count(); i < len; i++) {
CCTableViewCell *tempCell = (CCTableViewCell*)m_pCellsFreed->objectAtIndex(i);
if (tempCell->getTag() == nTag) {
cell = tempCell;
cell->retain();
m_pCellsFreed->removeObjectAtIndex(i);
cell->autorelease();
break;
}
}
return cell;
}
Basically you do cell->setTag(tagId) on your cell after you create it and then you tableView->dequeueCellWithTag(tagId). Hopefully this could be built in because its pretty standard.
If anyone knows a better way i'm open to suggestions!

Related

CouchDB view reduce one doc per key

I'm trying to solve what seems like a fairly simple problem with a couchDb view, but I'm not even getting close to the target with my result set.
Rather than updating documents, I'm creating a new document every time as my versioning strategy, and tying those documents together with a versioning field called ver. The very first document in a version chain will see the ver field and the _id field having the same value. All subsequent documents in the chain will have the same ver field as previous docs in the chain, but will have a unique _id field. These documents also have a createdTime field which is my way of knowing which document is the latest.
Here's my documents:
{
"_id": "abcd-1234-efgh-9876",
"ver": "abcd-1234-efgh-9876",
"createdTime": "2020-01-12 01:15:00 PM -0600",
...
},
{
"_id": "uopa-3849-pmdi-1935",
"ver": "abcd-1234-efgh-9876",
"createdTime": "2020-02-16 02:39:00 PM -0600",
...
}
Here's my map function:
function (doc) {
emit(doc.ver, doc);
}
Here's my reduce function:
function(keys, values, rereduce) {
var latestVersions = {};
for (var i = 0; i < keys.length; i++) {
var found = latestVersions[keys[i][0]];
if (!found || found.createdTime < values[i].createdTime) {
latestVersions[keys[i][0]] = values[i];
}
}
return latestVersions;
}
And finally, here's my desired output from the view (just the doc that I want):
{
"_id": "uopa-3849-pmdi-1935",
"ver": "abcd-1234-efgh-9876",
"createdTime": "2020-02-16 02:39:00 PM -0600",
...
}
What am I missing here? The reduce function is returning both records, which is not what I want. Is what I'm trying to achieve possible or is there a better way to go about this?
Update
I was able to get this to work when a single key is used to access the view, which is one of my use cases.
function (keys, values, rereduce) {
var toReturn = values[0];
for (var i = 1; i < values.length; i++) {
if (values[i].createdTime > toReturn.createdTime) {
toReturn = values[i];
}
}
return toReturn;
}
I have another use case that will be returning all of the data in the view, however. The desired result there is the same as above, but the function I'm using for single keys will only ever return one result. How do I filter multiple values with a shared key such that 1 "shared" key:n values -> 1 key:1 value.
I was finally able to resolve this when I stumbled upon this couchbase article. It was much more articulate than some of the other dry computer-science documentation.
I still do not understand why certain items are grouped in a reduce method and other ones are not. For example, reduce was called 5 times for 6 items that shared an identical key; only one of the keys had actually grouped anything -- an array of two documents. It probably has something to do with those dry computer-science B-tree documents I glossed over.
Anyway, I was able to determine that all I needed to do was group the values by the ver field in both scenarios (the only difference being that rereduce had a 2 dimensional array). Here's what my reduce function ended up looking like:
function (keys, values, rereduce) {
var toValues = function(myMap) {
return Object.keys(myMap).map(function(key) {
return myMap[key];
});
}
if (rereduce) {
// values should look like [[{...}, {...}], [{...}]]
var outputMap = {};
for (var i = 0; i < values.length; i++) {
for (var j = 0; j < values[i].length; j++) {
var currentEl = values[i][j];
var found = outputMap[currentEl.ver];
if ((found && found.createdDate < currentEl.createdDate) || !found) {
outputMap[currentEl.ver] = currentEl;
}
}
}
return toValues(outputMap);
} else {
var outputMap = {};
for (var i = 0; i < values.length; i++) {
var found = outputMap[values[i].ver];
if ((found && found.createdDate < values[i].createdDate) || !found) {
outputMap[values[i].ver] = values[i];
}
}
return toValues(outputMap);
}
}

Using enums and a for-loop to create instances of a class

enum { WOOD, BRICK, GRAIN, HEMP, WOOL, RAWMETAL, HONEY, SALT, METALGOODS, MEAD, CLOTH, BEER, STOCKFISH, CLOTHING, CHEESE, PITCH, PELTS, MEAT, WINE, SPICES, TOTALRESOURCES };
// An array of strings for each of the resource names
// As long as these are in the same order as the enum everything should match up
// .: resName[PIGIRON] is "Pig Iron"
string resName[]{ "Wood", "Brick", "Grain", "Hemp", "Wool", "Raw Metal", "Honey", "Salt", "Metal Goods", "Mead", "Cloth", "Beer", "Stockfish", "Clothing", "Cheese", "Pitch", "Pelts", "Meat", "Wine", "Spices" };
enum { Edinburgh, Scarborough, Boston, London, Bruges, Haarlem, Nimwegen, Groningen, Cologne, Minden, Bremen, Erfurt, Hamburg, Lubeck, Rostock, Berlin, Ripen, Flensburg, Aalborg, Naevsted, Bergen, Stavanger, Oslo, Stockholm, Gothenburg, Malmo, Ahus, Visby, Stettin, Posen, Breslau, Danzig, Thorn, Warsaw, Konigsberg, Kaunas, Riga, Reval, Helsinki, Novgorod, TOTALTOWNS};
string townName[]{ "Edinburgh", "Scarborough", "Boston", "London", "Bruges", "Haarlem", "Nimwegen", "Groningen", "Cologne", "Minden", "Bremen", "Erfurt", "Hamburg", "Lubeck", "Rostock", "Berlin", "Ripen", "Flensburg", "Aalborg", "Naevsted", "Bergen", "Stavanger", "Oslo", "Stockholm", "Gothenburg", "Malmo", "Ahus", "Visby", "Stettin", "Posen", "Breslau", "Danzig", "Thorn", "Warsaw", "Konigsberg", "Kaunas", "Riga", "Reval", "Helsinki", "Novgorod"};
class resource
{
public:
float demand, production, businessNeeds, businessProduction;
// This function, called a constructor, is run every time a new resource is created
// In this case, it assigns 0 to everything
resource()
{
demand = 0;
production = 0;
businessNeeds = 0;
businessProduction = 0;
}
float net()
{
return (this->production - this->demand);
}
float businessNet()
{
return (this->businessProduction - this->businessNeeds);
}
};
class town
{
public:
// The array of pointers to each of a our resource objects
resource *resList[TOTALRESOURCES];
// This is the town constructor
town()
{
// Loops through the array and creates a new resource object in each
// the resource constructor assigns the default values of 0.
for (int i = 0; i < TOTALRESOURCES; i = i + 1)
{
resList[i] = new resource();
}
}
~town()
{
// Loops through the array and deletes each resource object
for (int i = 0; i < TOTALRESOURCES; i = i + 1)
{
delete resList[i];
}
};
int main()
{
//What do I do here?
for (int i = 0; i < TOTALTOWNS; i++)
{
town townName[i];
}
system("pause");
return 0;
}
So, I'm a software engineering student and I just switched majors so I decided to take some personal time to learn how to code in c++ a bit better. I decided to build a program that can plan the logistics for a videogame called Patrician IV.
I have put about 5 days worth of work into this project and have found some serious problems with my initial code (hard to add new functionality and change stuff around). So I took a step back and am trying to build my classes in a more succinct manner while also being able to loop through each instance of town later in a loop so I can update the demand, production, businessNeeds, and businessProduction values easily. I was copying and pasting about 6 lines of code 40 times before this.
I want to know:
(A) is it possible to do what I want - i.e. can I use enums and a for-loop to construct instances of town.
(B) how to loop through each of the towns so that I can add values to the resource variables.
(C) a third-grade-level explanation of how to use pointers for similar purposes would also be great.
:) THANK YOU!
In your main function, use the same idea as resList to initialize your town objects, so:
town* townName[TOTALTOWNS]
for (int i = 0; i < TOTALTOWNS; i++)
{
townName[i]= new town();
}
Then, I'm guessing you want to give different values for each of the different resources. Switch statements go along with enums well. So I would recommend something like this:
for (int i = 0; i < TOTALRESOURCES; i = i + 1)
{
switch(i)
{
case WOOD:
townName[EDINBURGH]->resList[WOOD]->demand= yourValue;
break;
case BRICK:
break;
}
}
Or if you're cycling through towns:
for (int i = 0; i < TOTALTOWNS; i = i + 1)
{
switch(i)
{
case EDINBURGH:
break; //etc.
}
}
If you only want to update a single town or resource, depending on how you're organizing everything, you could create something like this. A function that takes your town array and the enum indexes, like this:
updateTownResources(town* (*townName)[TOTALTOWNS], int townEnum, int resourceEnum, int dValue, int pValue )
{
townName[townEnum]->resList[resourceEnum]->demand= dValue;
townName[townEnum]->resList[resourceEnum]->production= pValue;
//etc...
}
int main()
{
std::vector<town*> townArray;
//What do I do here?
for (int i = 0; i < TOTALTOWNS; i++)
{
town* pTown = new(std::nothrow) town;
townArray.push_back (pTown);
}
std::vector<town*>::iterator iter = townArray.begin();
for (;iter != townArray.end(); iter++) {
(*iter); // gives access to individual objects
}
system("pause");
return 0;
}

How to switch between diffrent for loops, and would such a mechanism make any sense?

This is more a, I'm kind of curious to know if it would make sense question, than a, I have a real problem question, I'm interessted in your opinion. If there are any syntax errors, I use pseudo-code to illustrate what intent to describe.
I have a program that uses a for-loop.
for (frame_pos = 0; frame_pos < frame_size; frame_pos++) {
ABC...
}
Now I want to add another possible way to iterate through my program.
for (frame_pos = framelist.first; framlist.hasNext; frame_pos = framelist.getNext) {
ABC...
}
So I wrote an if statement
if(a == true){
for (frame_pos = 1; frame_pos <= frame_size; frame_pos++) {
ABC...
}
}else{
for (frame_pos = framelist.first; framlist.hasNext; frame_pos = framelist.getNext) {
ABC...
}
}
But somehow I didn't like it beacause I had duplicated my code.
ABC...
Of course I could move everything from within my loops to a method and only invoke that method. But I was wondering, if something like
switch(a){
case(true):
for (frame_pos = 1; frame_pos <= frame_size; frame_pos++) {
break;
default:
for (frame_pos = framelist.first; framlist.hasNext; frame_pos = framelist.getNext) {
break;
}
would be possible and, if possible, usefull and make sense, because I would have used it here. It, of course, doesn't necessarily has to be a switch-case it could be some other mechanism. But my intention was/is to split the, from my point of view, atomic
for( ; ; ) {
...
}
body and recombine it.
Make ABC a function (extract method) and call that.
If you do not want to switch between both method during run-time, you could solve this on pre-processor level:
#define _USENEXT /* Comment out this line to use the "counter" approach. */
...
for (
#ifdef _USENEXT
frame_pos = framelist.first; framlist.hasNext; frame_pos = framelist.getNext
#else
frame_pos = 1; frame_pos <= frame_size; frame_pos++
#endif
)
{
<some code>
}
As an alternative to #defineing _USENEXT in the code as by my example, one could specify it as option when compiling. For gcc this would be -D _USENEXT.
Some languages have mechanisms to easily make such patterns reusable. C# for example, would let you write something like the following:
IEnumerable<Frame> Frames1() {
for (frame_pos = 0; frame_pos < frame_size; frame_pos++) {
yield return framelist[framepos];
}
}
IEnumerable<Frame> Frames2() {
for (frame_pos = framelist.first; framlist.hasNext; frame_pos = framelist.getNext) {
yield return framelist[framepos];
}
}
And then you can use treat these iteration patterns as first class objects like any other.
foreach(var frame in a? Frames1() : Frames2()) {
ABC...
}
With such a feature you can avoid implementation details like those silly boilerplatey low-level error-prone primitive for loops from C.
C++ doesn't have such a syntactic feature, but it also has a similar established mechanism for reusing iteration patterns: iterators. Writing an iterator isn't as dead simple as in C#, though :(
But standard containers already provide suitable iterators. You can then reuse any of the many existing iteration patterns provided in the standard library.
std::vector<int> v = ...;
std::set<int> s = ...;
auto are_equal = std::equal(v.begin(), v.end(), s.begin(), s.end());
Good C++ libraries will similarly provide suitable iterators too. (Yeah, good luck with that; it seems a large portion of people writing "C++ libraries" doesn't know C++)
If you really don't want to make ABC a function an then switch between two different for loops you could instead write three functions:
int initFramepos( int a )
{
return( a ? 1 : framelist.first );
}
int checkFramepos( int frame_pos, int a )
{
return( a ? frame_pos < frame_size ? framelist.hasNext );
}
int incrFramepos( int frame_pos, int a )
{
return( a ? frame_pos+1 ? framelist.getNext );
}
Then your for-loop could look like this:
for( frame_pos = initFramepos( a ); checkFramepos( frame_pos, a ); frame_pos = incrFramepos( frame_pos, a ) )
{
ABC
}
The clean solution (for C++ code - this will not work for C) would be to write an iterator class implementation for your specific case. Then, you could write your client code in terms of an iterator, and decide what iteration means independent of how it is implemented (you will be able to decide what iteration means for you at any point, without changing client code at all).
If you do this and specialize std::begin and std::end, you will be able to use the entire iterators algorithms library in std as a bonus: (sort, copy, find/find_if, for_each, all_of, any_if, transform and accumulate are the most useful, out of the top of my head).
Regarding other solutions, do not use a macro: it results in brittle code with many difficult to see caveats. As a rule of thumb, using a macro in C++ should be (close to) the last considered solution for anything.
What you describing here is exactly the problem that strategy pattern was meant to solve.
Basically, what you need to do here is to make each loop as a method within a class, and then set one of them as your strategy. And of course you can switch between strategies whenever you want.
it will look like this:
class Strategy {
virtual void func () = 0;
};
.
class StrategyA : public Strategy {
virtual void func () {
for (frame_pos = 0; frame_pos < frame_size; frame_pos++) {
ABC...
}
}
};
.
class StrategyB : public Strategy {
virtual void func () {
for (frame_pos = framelist.first; framlist.hasNext; frame_pos = framelist.getNext) {
//ABC...
}
}
};
.
class StrategyToTake {
private:
Strategy* strategy;
public:
void execute () {strategy->func();}
void setStrategy (Strategy* newStrategy) {this.strategy = newStrategy;}
};
.

Weka XRFFSaver including missing sparse values

I'm using the XRFFSaver class in the current weka dev version. I'm using xrff rather than arff as I have extremely sparse data and the specs here indicate that sparse instances are handled nicely and efficiently (i.e. not included in output).
However using XRFFSaver they are included in the output like this:
<value index="1" missing="yes"/>
<value index="2" missing="yes"/>
...
Which defeats the purpose of the whole exercise. Anyone know if this is operator error or will I need to write my own saver?
I had a quick look at the source and I could not find any way of toggling this behaviour in either XRFFSaver or XMLInstances, however it was a quick look.
tnx
I quickly hacked up a solution to this:
Note: This is in C# (I use weka through ikvm). However, this should be very simple for anyone to convert to Java.
Note2: The only important line is this one: if (sparse) continue which I also highlighted below with comments. Everything else is a straight copy of the weka source which I found through grepcode and google. Not even sure if its the latest version I copied so please use with discretion.
I also tested to ensure that the standard XRFFLoader handles this correctly and it appears it does.
Tnx
// Usage
var saver = new EfficientXRFFSaver();
saver.setCompressOutput(file.EndsWith(".gz"));
saver.setInstances(Instances);
saver.setFile(new java.io.File(file));
saver.writeBatch();
// Implementation
public class EfficientXRFFSaver : XRFFSaver
{
public override void resetOptions() {
base.resetOptions();
setFileExtension(getCompressOutput() ? XRFFLoader.FILE_EXTENSION_COMPRESSED : XRFFLoader.FILE_EXTENSION);
try { m_XMLInstances = new EfficientXMLInstances(); }
catch { m_XMLInstances = null; }
}
}
public class EfficientXMLInstances : XMLInstances
{
protected override void addInstance(Element parent, Instance inst) {
var node = m_Document.createElement(TAG_INSTANCE);
parent.appendChild(node);
var sparse = inst is SparseInstance;
if (sparse) { node.setAttribute(ATT_TYPE, VAL_SPARSE); }
if (inst.weight() != 1.0) { node.setAttribute(ATT_WEIGHT, Utils.doubleToString(inst.weight(), m_Precision)); }
for (var i = 0; i < inst.numValues(); i++) {
var index = inst.index(i);
var value = m_Document.createElement(TAG_VALUE);
if (inst.isMissing(index)) {
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!!!!!!!!! IMPORTANT !!!!!!!!!!!!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// This line will not add this element if its missing and sparse.
if (sparse) continue;
value.setAttribute(ATT_MISSING, VAL_YES);
} else {
if (inst.attribute(index).isRelationValued()) {
var child = m_Document.createElement(TAG_INSTANCES);
value.appendChild(child);
for (var n = 0; n < inst.relationalValue(i).numInstances(); n++) {
addInstance(child, inst.relationalValue(i).instance(n));
}
} else {
value.appendChild(inst.attribute(index).type() == weka.core.Attribute.NUMERIC ?
m_Document.createTextNode(Utils.doubleToString(inst.value(index), m_Precision)) :
m_Document.createTextNode(validContent(inst.stringValue(index))));
}
}
node.appendChild(value);
if (sparse) { value.setAttribute(ATT_INDEX, "" + (index + 1)); }
}
}
}

Can Allegro update the number of joysticks at runtime?

Is there a way to update the number of joysticks plugged in at run-time other than constantly calling remove_joystick() then install_joystick? This proves to be extremely slow (goes from 60 FPS to around 5).
Allegro 4.2 answers only please...
void Joystick::Update() {
//If joystick input was lost, attempt to reacquire.
if(GetNumJoysticks() == 0) {
throw InputNotAvailableException("Joystick");
}
//If all joysticks were deleted remove input and do nothing.
if(_numjoysticks == 0) {
remove_joystick();
return;
}
//Update state information
if(poll_joystick() < 0) {
throw InputNotAvailableException("Joystick");
}
for(int i = 0; i < _numButtons; ++i) {
_prevButtons[i].b = _curButtons[i].b;
_prevButtons[i].name = _curButtons[i].name;
_curButtons[i].b = joy[_joyNumber].button[i].b;
_curButtons[i].name = joy[_joyNumber].button[i].name;
}
for(int i = 0; i < _numSticks; ++i) {
for(int j = 0; j < joy[_joyNumber].stick[i].num_axis; ++j) {
_prevSticks[i].axis[j].name = _curSticks[i].axis[j].name;
_prevSticks[i].axis[j].pos = _curSticks[i].axis[j].pos;
_prevSticks[i].axis[j].d1 = _curSticks[i].axis[j].d1;
_prevSticks[i].axis[j].d2 = _curSticks[i].axis[j].d2;
_curSticks[i].axis[j].name = joy[_joyNumber].stick[i].axis[j].name;
_curSticks[i].axis[j].pos = joy[_joyNumber].stick[i].axis[j].pos;
_curSticks[i].axis[j].d1 = joy[_joyNumber].stick[i].axis[j].d1;
_curSticks[i].axis[j].d2 = joy[_joyNumber].stick[i].axis[j].d2;
}
_prevSticks[i].flags = _curSticks[i].flags;
_prevSticks[i].name = _curSticks[i].name;
_curSticks[i].flags = joy[_joyNumber].stick[i].flags;
_curSticks[i].name = joy[_joyNumber].stick[i].name;
}
}
int Joystick::GetNumJoysticks() {
remove_joystick();
if(install_joystick(JOY_TYPE_DIRECTX)) {
return 0;
}
return (num_joysticks);
}
The 4.x series does not. The 5.x series does.
You'll have to either listen for native OS events using custom platform specific code (assuming such things exist) and only call the Allegro deinit/init functions when a change is detected, or require the user to initiate joystick refresh manually.
Under Linux, you could inotify_add_watch() /dev/input to check for changes. Looking at the 4.4 Allegro code, looks like you'd want to call the Win32 functions joyGetNumDevs() and joyGetPos(). Something like:
int WIN_MAX_JOYSTICKS = joyGetNumDevs(); // this should never change
JOYINFO ji;
int pluggedin_count = 0;
for (int i = 0; i < WIN_MAX_JOYSTICKS; ++i)
if (joyGetPos(i, &ji) == JOYERR_NOERROR) ++pluggedin_count;
if (pluggedin_count != last_pluggedin_count) /* reinit Allegro */
You'd have to do that every N seconds.
Those joy* functions are Windows functions, so read MSDN docs to learn how to use them.