#include "RecipieIngredient.h" #include #include #include #include "Globals.h" RecipieIngredientElement::RecipieIngredientElement() : Framework::UIMLElement() {} LogicTree* RecipieIngredientElement::parse(Framework::XML::Element* zElement) { if (zElement->getName().istGleich("anyItem")) { return new LogicTree(LogicalOperator::OR, new RequirementSet()); } else if (zElement->getName().istGleich("attribute")) { AttributeOperator op = AttributeOperator::Equals; if (zElement->getAttributeValue("operator").istGleich("!=")) { op = AttributeOperator::NotEquals; } else if (zElement->getAttributeValue("operator").istGleich(">")) { op = AttributeOperator::GreaterThan; } else if (zElement->getAttributeValue("operator").istGleich(">=")) { op = AttributeOperator::GreaterThanOrEquals; } else if (zElement->getAttributeValue("operator").istGleich("<")) { op = AttributeOperator::LessThan; } else if (zElement->getAttributeValue("operator").istGleich("<=")) { op = AttributeOperator::LessThanOrEquals; } Requirement* req = new Requirement(zElement->getAttributeValue("name"), zElement->getAttributeValue("value"), op); RequirementSet* set = new RequirementSet(); set->addRequirement(req); req->release(); return new LogicTree(LogicalOperator::OR, set); } else if (zElement->getName().istGleich("operator")) { bool result0_0 = (bool)(int)zElement->getAttributeValue("result_0_0"); bool result0_1 = (bool)(int)zElement->getAttributeValue("result_0_1"); bool result1_0 = (bool)(int)zElement->getAttributeValue("result_1_0"); bool result1_1 = (bool)(int)zElement->getAttributeValue("result_1_1"); if (!result0_0 && !result0_1 && !result1_0 && !result1_1) { // none match RequirementSet* set = new RequirementSet(); Requirement* req = new Requirement("_x", "0", AttributeOperator::Equals); set->addRequirement(req); req->release(); req = new Requirement("_x", "1", AttributeOperator::Equals); set->addRequirement(req); req->release(); return new LogicTree(LogicalOperator::OR, set); } if (result0_0 && result0_1 && result1_0 && result1_1) { // any match return new LogicTree(LogicalOperator::OR, new RequirementSet()); } auto iterator = zElement->getChilds(); LogicTree* left = parse(iterator.val()); if (!result0_0 && !result0_1 && result1_0 && result1_1) { return left; } if (result0_0 && result0_1 && !result1_0 && !result1_1) { left->negate(); return left; } LogicTree* right = 0; iterator++; right = parse(iterator.val()); if (!result0_0 && result0_1 && !result1_0 && result1_1) { left->release(); return right; } if (result0_0 && !result0_1 && result1_0 && !result1_1) { left->release(); right->negate(); return right; } if (!result0_0 && !result0_1 && !result1_0 && result1_1) { LogicTree* result = new LogicTree(LogicalOperator::AND, 0); result->addChildren(left); result->addChildren(right); return result; } if (!result0_0 && result0_1 && result1_0 && result1_1) { LogicTree* result = new LogicTree(LogicalOperator::OR, 0); result->addChildren(left); result->addChildren(right); return result; } if (result0_0 && result0_1 && result1_0 && !result1_1) { left->negate(); right->negate(); LogicTree* result = new LogicTree(LogicalOperator::OR, 0); result->addChildren(left); result->addChildren(right); return result; } if (result0_0 && !result0_1 && !result1_0 && !result1_1) { left->negate(); right->negate(); LogicTree* result = new LogicTree(LogicalOperator::AND, 0); result->addChildren(left); result->addChildren(right); return result; } if (!result0_0 && !result0_1 && result1_0 && !result1_1) { right->negate(); LogicTree* result = new LogicTree(LogicalOperator::AND, 0); result->addChildren(left); result->addChildren(right); return result; } if (!result0_0 && result0_1 && !result1_0 && !result1_1) { left->negate(); LogicTree* result = new LogicTree(LogicalOperator::AND, 0); result->addChildren(left); result->addChildren(right); return result; } if (!result0_0 && result0_1 && result1_0 && !result1_1) { LogicTree* orT = new LogicTree(LogicalOperator::OR, 0); orT->addChildren(left); orT->addChildren(right); LogicTree* notLeft = left->clone(); notLeft->negate(); LogicTree* notRight = right->clone(); notRight->negate(); LogicTree* notOr = new LogicTree(LogicalOperator::OR, 0); notOr->addChildren(notLeft); notOr->addChildren(notRight); LogicTree* result = new LogicTree(LogicalOperator::AND, 0); result->addChildren(orT); result->addChildren(notOr); return result; } if (result0_0 && !result0_1 && !result1_0 && result1_1) { LogicTree* andT = new LogicTree(LogicalOperator::AND, 0); andT->addChildren(left); andT->addChildren(right); LogicTree* notLeft = left->clone(); notLeft->negate(); LogicTree* notRight = right->clone(); notRight->negate(); LogicTree* notAnd = new LogicTree(LogicalOperator::AND, 0); notAnd->addChildren(notLeft); notAnd->addChildren(notRight); LogicTree* result = new LogicTree(LogicalOperator::OR, 0); result->addChildren(andT); result->addChildren(notAnd); return result; } if (result0_0 && !result0_1 && result1_0 && result1_1) { right->negate(); LogicTree* result = new LogicTree(LogicalOperator::OR, 0); result->addChildren(left); result->addChildren(right); return result; } if (result0_0 && result0_1 && !result1_0 && result1_1) { left->negate(); LogicTree* result = new LogicTree(LogicalOperator::OR, 0); result->addChildren(left); result->addChildren(right); return result; } } return 0; } //! prüft, ob dieses UIML Element für ein bestimmtes xml Element zuständig //! ist bool RecipieIngredientElement::isApplicableFor(Framework::XML::Element& element) { return element.getName().istGleich("ingredient"); } //! erstellt eine neue Zeichnung zu einem gegebenen xml Element Framework::Zeichnung* RecipieIngredientElement::parseElement( Framework::XML::Element& element, Framework::UIMLContainer& generalFactory) { int amount = (int)element.getAttributeValue("amount"); RecipieIngredient* result = new RecipieIngredient(amount); Framework::XML::Editor logicSelector = element.selectChildsByName("logic"); if (logicSelector.exists()) { LogicTree* logic = new LogicTree(LogicalOperator::OR, 0); logicSelector.selectChildren().forEach( [this, logic](Framework::XML::Element* zElement) { logic->addChildren(parse(zElement)); }); Framework::RCArray* requirements = logic->resolve(); logic->release(); for (RequirementSet* set : *requirements) { result->addPossibleItem(set->getIcon(), new Text(set->renderToTooltip()), set->getItemType()); } requirements->release(); } return result; } bool RecipieIngredientElement::updateElement(Framework::XML::Element& element, Framework::Zeichnung& z, Framework::UIMLContainer& generalFactory) { return false; } //! wendet die layout parameter zu einer Zeichnung an void RecipieIngredientElement::layout(Framework::XML::Element& element, Framework::Zeichnung& z, int pWidth, int pHeight, Framework::UIMLContainer& generalLayouter) { UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter); z.setWidth(50); z.setHeight(50); } RecipieIngredient::RecipieIngredient(int amount) : Framework::ZeichnungHintergrund(), currentIconIndex(0), timtUntilNextIcon(2.0), amount(amount) { setStyle(Framework::Zeichnung::Style::Erlaubt | Framework::Zeichnung::Style::Sichtbar); Framework::ToolTip* tip = new Framework::ToolTip(window->zBildschirm()); tip->addStyle(Framework::ZeichnungHintergrund::Style::Hintergrund | Framework::ZeichnungHintergrund::Style::HAlpha | Framework::ZeichnungHintergrund::Style::Rahmen | Framework::ZeichnungHintergrund::Style::Sichtbar); tip->setHintergrundFarbe(0xA0000000); tip->setRahmenFarbe(0xFFFFFFFF); tip->setRahmenBreite(1); toolTip = uiFactory.createTextFeld(uiFactory.initParam); toolTip->setText(""); toolTip->setSize(0, 0); toolTip->addStyle(Framework::TextFeld::Style::Mehrzeilig); tip->addMember(toolTip); tip->setWarten(0.5); setToolTipZ(tip); } void RecipieIngredient::addPossibleItem( Framework::Bild* icon, Framework::Text* toolTip, int typeId) { icons.add(icon); toolTips.add(toolTip); itemTypes.add(typeId); if (toolTips.getEintragAnzahl() == 1) { this->toolTip->setText(toolTips.z(0)->getText()); this->toolTip->setSize( this->toolTip->getNeededWidth(), this->toolTip->getNeededHeight()); } } bool RecipieIngredient::tick(double tickVal) { if (!zToolTip()->isVisible()) { timtUntilNextIcon -= tickVal; if (timtUntilNextIcon <= 0) { timtUntilNextIcon = 2.0; currentIconIndex++; if (currentIconIndex >= icons.getEintragAnzahl()) { currentIconIndex = 0; } if (toolTips.getEintragAnzahl() > 0) { toolTip->setText(toolTips.z(currentIconIndex)->getText()); toolTip->setSize( toolTip->getNeededWidth(), toolTip->getNeededHeight()); rend = 1; } } } return ZeichnungHintergrund::tick(tickVal); } void RecipieIngredient::render(Framework::Bild& rObj) { ZeichnungHintergrund::render(rObj); if (!rObj.setDrawOptions(pos.x, pos.y, gr.x, gr.y)) return; TextRenderer tr; tr.setSchriftZ( dynamic_cast(uiFactory.initParam.schrift->getThis())); tr.setSchriftSize(12); rObj.fillRegion(0, 0, 50, 50, 0xFF222222); if (icons.getEintragAnzahl() > 0) rObj.alphaBild(0, 0, 50, 50, *icons.z(currentIconIndex)); const char* units[] = {"", "K", "M", "G", "T", "P"}; int i = 0; int tmpCount = amount; for (; i < 6 && tmpCount > 1024; i++) tmpCount = tmpCount / 1024; Text count = tmpCount; count += units[i]; tr.renderText(45 - tr.getTextBreite(count), 45 - tr.getTextHeight(count), count, rObj, 0xFFFFFFFF); rObj.releaseDrawOptions(); } void RecipieIngredient::doMausEreignis( Framework::MausEreignis& me, bool userRet) { if (me.id == ME_RLinks) { if (itemTypes.getEintragAnzahl() > currentIconIndex) { World::INSTANCE->zClient()->craftingUIMLRequest( itemTypes.get(currentIconIndex)); } } ZeichnungHintergrund::doMausEreignis(me, userRet); } Requirement::Requirement( Framework::Text attribute, Framework::Text value, AttributeOperator op) : Framework::ReferenceCounter(), attribute(attribute), value(value), op(op) {} void Requirement::negate() { switch (op) { case AttributeOperator::Equals: op = AttributeOperator::NotEquals; break; case AttributeOperator::NotEquals: op = AttributeOperator::Equals; break; case AttributeOperator::GreaterThan: op = AttributeOperator::LessThanOrEquals; break; case AttributeOperator::GreaterThanOrEquals: op = AttributeOperator::LessThan; break; case AttributeOperator::LessThan: op = AttributeOperator::GreaterThanOrEquals; break; case AttributeOperator::LessThanOrEquals: op = AttributeOperator::GreaterThan; break; } } Requirement* Requirement::clone() { return new Requirement(attribute, value, op); } bool Requirement::contradicts(Requirement* zOther) { if (zOther->attribute.istGleich(attribute.getText())) { if (zOther->value.istGleich(value)) { if (op == AttributeOperator::Equals && zOther->op == AttributeOperator::NotEquals) { return 1; } if (op == AttributeOperator::NotEquals && zOther->op == AttributeOperator::Equals) { return 1; } if (op == AttributeOperator::GreaterThan && zOther->op == AttributeOperator::LessThan) { return 1; } if (op == AttributeOperator::LessThan && zOther->op == AttributeOperator::GreaterThan) { return 1; } } if (op == AttributeOperator::LessThan || op == AttributeOperator::LessThanOrEquals || op == AttributeOperator::GreaterThan || op == AttributeOperator::GreaterThanOrEquals) { double v1 = (double)value; double v2 = (double)zOther->value; if (op == AttributeOperator::LessThan || op == AttributeOperator::LessThanOrEquals) { if (v1 < v2) { if (zOther->op == AttributeOperator::GreaterThan || zOther->op == AttributeOperator::GreaterThanOrEquals || zOther->op == AttributeOperator::Equals) { return 1; } } } else if (op == AttributeOperator::GreaterThan || op == AttributeOperator::GreaterThanOrEquals) { if (v1 > v2) { if (zOther->op == AttributeOperator::LessThan || zOther->op == AttributeOperator::LessThanOrEquals || zOther->op == AttributeOperator::Equals) { return 1; } } } } if (zOther->op == AttributeOperator::LessThan || zOther->op == AttributeOperator::LessThanOrEquals || zOther->op == AttributeOperator::GreaterThan || zOther->op == AttributeOperator::GreaterThanOrEquals) { double v1 = (double)zOther->value; double v2 = (double)value; if (zOther->op == AttributeOperator::LessThan || zOther->op == AttributeOperator::LessThanOrEquals) { if (v1 < v2) { if (op == AttributeOperator::GreaterThan || op == AttributeOperator::GreaterThanOrEquals || op == AttributeOperator::Equals) { return 1; } } } else if (zOther->op == AttributeOperator::GreaterThan || zOther->op == AttributeOperator::GreaterThanOrEquals) { if (v1 > v2) { if (op == AttributeOperator::LessThan || op == AttributeOperator::LessThanOrEquals || op == AttributeOperator::Equals) { return 1; } } } } } return 0; } bool Requirement::merge(Requirement* zOther) { if (zOther->attribute.istGleich(attribute.getText())) { if (zOther->value.istGleich(value)) { if (op == zOther->op) { return 1; } } else { if (op == AttributeOperator::Equals && zOther->op == AttributeOperator::NotEquals) { return 1; } if (op == AttributeOperator::NotEquals && zOther->op == AttributeOperator::Equals) { op = AttributeOperator::Equals; value = zOther->value; return 1; } } if (op == AttributeOperator::LessThan || op == AttributeOperator::LessThanOrEquals || op == AttributeOperator::GreaterThan || op == AttributeOperator::GreaterThanOrEquals) { double v1 = (double)value; double v2 = (double)zOther->value; if (op == AttributeOperator::LessThan || op == AttributeOperator::LessThanOrEquals) { if (zOther->op == AttributeOperator::LessThan || zOther->op == AttributeOperator::LessThanOrEquals) { if (v1 > v2 || (v1 == v2 && op == AttributeOperator::LessThanOrEquals)) { op = zOther->op; value = zOther->value; } return 1; } if (zOther->op == AttributeOperator::Equals) { if (v2 < v1 || (v2 == v1 && op == AttributeOperator::LessThanOrEquals)) { op = zOther->op; value = zOther->value; return 1; } } if (zOther->op == AttributeOperator::NotEquals) { if (v2 > v1 || (v2 == v1 && op == AttributeOperator::LessThan)) { return 1; } } } else if (op == AttributeOperator::GreaterThan || op == AttributeOperator::GreaterThanOrEquals) { if (zOther->op == AttributeOperator::GreaterThan || zOther->op == AttributeOperator::GreaterThanOrEquals) { if (v1 < v2 || (v1 == v2 && op == AttributeOperator::GreaterThanOrEquals)) { op = zOther->op; value = zOther->value; } return 1; } if (zOther->op == AttributeOperator::Equals) { if (v2 > v1 || (v2 == v1 && op == AttributeOperator::GreaterThanOrEquals)) { op = zOther->op; value = zOther->value; return 1; } } if (zOther->op == AttributeOperator::NotEquals) { if (v2 < v1 || (v2 == v1 && op == AttributeOperator::GreaterThan)) { return 1; } } } } if (zOther->op == AttributeOperator::LessThan || zOther->op == AttributeOperator::LessThanOrEquals || zOther->op == AttributeOperator::GreaterThan || zOther->op == AttributeOperator::GreaterThanOrEquals) { double v1 = (double)zOther->value; double v2 = (double)value; if (zOther->op == AttributeOperator::LessThan || zOther->op == AttributeOperator::LessThanOrEquals) { if (op == AttributeOperator::Equals) { if (v2 < v1 || (v2 == v1 && zOther->op == AttributeOperator::LessThanOrEquals)) { return 1; } } if (op == AttributeOperator::NotEquals) { if (v2 > v1 || (v2 == v1 && zOther->op == AttributeOperator::LessThan)) { op = zOther->op; value = zOther->value; return 1; } } } else if (zOther->op == AttributeOperator::GreaterThan || zOther->op == AttributeOperator::GreaterThanOrEquals) { if (op == AttributeOperator::Equals) { if (v2 > v1 || (v2 == v1 && zOther->op == AttributeOperator::GreaterThanOrEquals)) { return 1; } } if (op == AttributeOperator::NotEquals) { if (v2 < v1 || (v2 == v1 && zOther->op == AttributeOperator::GreaterThan)) { op = zOther->op; value = zOther->value; return 1; } } } } } return 0; } int Requirement::getItemType() { if (attribute.istGleich("Type") && op == AttributeOperator::Equals) { return (int)value; } return -1; } Framework::Text Requirement::getDescription() { Framework::Text result = attribute; result += " "; switch (op) { case AttributeOperator::Equals: result += "is"; break; case AttributeOperator::NotEquals: result += "is not"; break; case AttributeOperator::LessThan: result += "is less than"; break; case AttributeOperator::LessThanOrEquals: result += "is less than or equal to"; break; case AttributeOperator::GreaterThan: result += "is greater than"; break; case AttributeOperator::GreaterThanOrEquals: result += "is greater than or equal to"; break; } result += " "; result += value; return result; } RequirementSet::RequirementSet() : Framework::ReferenceCounter() {} void RequirementSet::addRequirement(Requirement* zReq) { for (Requirement* req : requirements) { if (req->merge(zReq)) return; } requirements.add(zReq->clone()); } RequirementSet* RequirementSet::clone() { RequirementSet* result = new RequirementSet(); for (Requirement* req : requirements) { result->requirements.add(req->clone()); } return result; } void RequirementSet::addRequirements(RequirementSet* zOther) { for (Requirement* req : zOther->requirements) { addRequirement(req); } } void RequirementSet::negate(LogicTree* zNode) { for (Requirement* req : requirements) { Requirement* negate = req->clone(); negate->negate(); RequirementSet* set = new RequirementSet(); set->addRequirement(negate); negate->release(); zNode->addChildren(new LogicTree(LogicalOperator::OR, set)); } } bool RequirementSet::isNoneMatch() const { for (Requirement* req : requirements) { for (Requirement* req2 : requirements) { if (req != req2) { if (req->contradicts(req2)) { return 1; } } } } return 0; } bool RequirementSet::isAnyMatch() const { return requirements.getEintragAnzahl() == 0; } Framework::Text RequirementSet::renderToTooltip() const { int itemType = -1; for (Requirement* req : requirements) { int rT = req->getItemType(); if (rT != -1) { if (itemType == -1) { itemType = rT; } else if (itemType != rT) { itemType = -2; } } } Framework::Text result = ""; if (itemType == -2) { return "No Item matches this filter"; } else if (itemType == -1) { result += "Any Item"; } else { result += zItemType(itemType)->getName(); } if (requirements.getEintragAnzahl() > 0) { bool first = 1; for (Requirement* req : requirements) { if (req->getItemType() == -1) { if (first) { result += ":\n"; first = 0; } result += " "; result += req->getDescription(); result += "\n"; } } } return result; } Framework::Bild* RequirementSet::getIcon() const { int itemType = -1; for (Requirement* req : requirements) { int rT = req->getItemType(); if (rT != -1) { if (itemType == -1) { itemType = rT; } else if (itemType != rT) { itemType = -2; } } } if (itemType == -2) { LTDBDatei dat; dat.setDatei(new Text("data/images/gui_icons.ltdb")); dat.leseDaten(0); return dat.laden(0, new Text("noitem.png")); } else if (itemType == -1) { LTDBDatei dat; dat.setDatei(new Text("data/images/gui_icons.ltdb")); dat.leseDaten(0); return dat.laden(0, new Text("anyitem.png")); } else { return dynamic_cast( zItemType(itemType)->zIcon()->getThis()); } } int RequirementSet::getItemType() const { int itemType = -1; for (Requirement* req : requirements) { int rT = req->getItemType(); if (rT != -1) { if (itemType == -1) { itemType = rT; } else if (itemType != rT) { itemType = -2; } } } return itemType; } LogicTree::LogicTree(LogicalOperator op, RequirementSet* set) : Framework::ReferenceCounter(), op(op), requirementSet(set) {} LogicTree::~LogicTree() { if (requirementSet) requirementSet->release(); } Framework::RCArray* LogicTree::multiply( Framework::RCArray* a, Framework::RCArray* b) { Framework::RCArray* result = new Framework::RCArray(); for (RequirementSet* aSet : *a) { for (RequirementSet* bSet : *b) { RequirementSet* set = aSet->clone(); set->addRequirements(bSet); if (!set->isNoneMatch()) { if (set->isAnyMatch()) { result->leeren(); result->add(set); a->release(); b->release(); return result; } else { result->add(set); } } else { set->release(); } } } return result; } void LogicTree::addChildren(LogicTree* tree) { children.add(tree); } LogicTree* LogicTree::clone() { LogicTree* result = new LogicTree(op, requirementSet->clone()); for (LogicTree* child : children) { result->children.add(child->clone()); } return result; } void LogicTree::negate() { if (requirementSet != 0) { requirementSet->negate(this); requirementSet->release(); requirementSet = 0; } else { if (op == LogicalOperator::AND) { op = LogicalOperator::OR; } else if (op == LogicalOperator::OR) { op = LogicalOperator::AND; } for (LogicTree* child : children) { child->negate(); } } } Framework::RCArray* LogicTree::resolve() { if (requirementSet != 0) { Framework::RCArray* result = new Framework::RCArray(); result->add(dynamic_cast(requirementSet->getThis())); return result; } else { Framework::RCArray* result = 0; if (op == LogicalOperator::OR) { result = new Framework::RCArray(); for (LogicTree* child : children) { Framework::RCArray* childSet = child->resolve(); for (RequirementSet* set : *childSet) { result->add(dynamic_cast(set->getThis())); } childSet->release(); } } else if (op == LogicalOperator::AND) { result = children.z(0)->resolve(); for (int i = 1; i < children.getEintragAnzahl(); i++) { Framework::RCArray* childSet = children.z(i)->resolve(); result = multiply(result, childSet); } } if (result != 0) { for (int i = 0; i < result->getEintragAnzahl(); i++) { if (result->z(i)->isNoneMatch()) { result->remove(i); i--; } else if (result->z(i)->isAnyMatch()) { Framework::RCArray* anyMatch = new Framework::RCArray(); anyMatch->add(result->get(i)); result->release(); return anyMatch; } } } return result; } }