/// Структура, хранящая операции, которые выполняются над параметрами
struct COMPUTE
{
public:
std::string op; ///< операция, которую выполняют над аргументами
double arg1, arg2; ///< аргументы оператора
int arg1_index, arg2_index; ///< индексы, по которым располагаются в векторе аргументы
public:
COMPUTE(): op(""), arg1(0.0), arg2(0.0), arg1_index(0), arg2_index(0) {}
COMPUTE(const COMPUTE& o): op(o.op), arg1(o.arg1), arg2(o.arg2), arg1_index(o.arg1_index),
arg2_index(o.arg2_index) {}
COMPUTE(const char* o, double ar1, double ar2): op(0), arg1(ar1), arg2(ar2), arg1_index(0), arg2_index(0) {}
bool operator==(const COMPUTE& o) { return op == o.op && arg1 == o.arg1 && arg2 == o.arg2 &&
arg1_index == o.arg1_index && arg2_index == o.arg2_index; }
const COMPUTE& operator=(const COMPUTE& o)
{ op = o.op; arg1 = o.arg1; arg2 = o.arg2; arg1_index = o.arg1_index; arg2_index = o.arg2_index; return *this; }
virtual double GetValue();
};
/// Расширенная структура для выполнения более сложных операций
struct EXCOMPUTE: public COMPUTE
{
public:
int arg_count; ///< количество аргументов функции
double *arg1, *arg2; ///< указатели на аргументы функции
public:
EXCOMPUTE(int count = 4);
EXCOMPUTE(const EXCOMPUTE& o);
EXCOMPUTE(const COMPUTE& o): arg1(0), arg2(0) { op = o.op; arg1_index = o.arg1_index; arg2_index = o.arg2_index;
COMPUTE::arg1 = 0.0; COMPUTE::arg2 = 0.0; }
~EXCOMPUTE() { delete[] arg1; delete[] arg2; }
bool operator==(const EXCOMPUTE& o);
const EXCOMPUTE& operator=(const EXCOMPUTE& o);
const EXCOMPUTE& operator=(const COMPUTE& o) { op = o.op; COMPUTE::arg1 = 0.0; COMPUTE::arg2 = 0.0; return *this; }
double GetValue();
};
/// Класс для вычисления параметра
class ElemFormul
{
protected:
QStringList formul_list; ///< список простых формул, которые следует вычислять
public:
ElemFormul(QStringList e): formul_list(e) {}
~ElemFormul() {}
COMPUTE* calculateFormul(LOGRECORD* record, std::vector<ParamDescr*>* vec);
COMPUTE* calc(LOGRECORD* record, std::vector<ParamDescr*>* vec, QStringList& ls, QList<double>& rs_vl);
int argumentIndex(std::vector<ParamDescr*>* vec, QString arg);
};
/// Класс для описания вычисляемых параметров
class CompParamDescr: public ParamDescr
{
protected:
COMPUTE* op; ///< указатель на операции для вычисления параметров
std::string expression; ///< выражение, которое следует вычислить для получения параметра
QStringList formul_list; ///< список простых формул, которые следует вычислять
unsigned int index; ///< индекс данного элемента
private:
void buildString(QString& expr, QStringList& ls);
QString remove_symbols(const char* op, QString expr);
void determOperation(QString& expr, QStringList& ls, const QRegExp& exp, const QRegExp& d_exp);
void determDifficultOp(QString& expr, QStringList& ls, const QRegExp& df_exp);
public:
CompParamDescr(): expression(""), index(-1), op(0) {}
COMPUTE* opVec() const { return op; }
void opVec(const COMPUTE* v);
std::string Expr() const { return expression; }
void Expr(const std::string e) { expression = e; }
PARAMVALUE GetValue(Uint word);
QStringList formulList() { return formul_list; }
void formuList(const QStringList& l) { formul_list = l; }
void addFormul();
};
/// Добавление в список простейшей вычислимой формулы
void CompParamDescr::addFormul()
{
QRegExp exp(BASE_OPERATIONS);
QString str_expr = expression.c_str(), e = "";
for(int matched = 0, ind = 0; (matched = exp.indexIn(str_expr, matched)) != -1;
++ind, matched += exp.matchedLength())
{
string operation = exp.capturedTexts().at(0).toStdString();
if(operation == ",") { matched += exp.matchedLength(); ++ind; continue; }
if(operation.size() > 2)
{
e = remove_symbols(operation.c_str(), str_expr);
break;
}
else e = str_expr.simplified();
}
buildString(e, formul_list);
}
/// Формирование простейшей разбираемой строки
void CompParamDescr::buildString(QString& expr, QStringList& ls)
{
const char *simple_op_low_priority = "[+-]", *simple_op_high_priority = "[*/]";
QRegExp exp_low(simple_op_low_priority), exp_high(simple_op_high_priority), exp(BASE_OPERATIONS);
QRegExp exp_diff("gethmax|gethaccuratly");
string hs = expr.toStdString();
if(expr.find(")") != -1 && expr.find("(") != -1)
{
QString ex = expr.section(")", 0, 0).simplified(), reserve = expr.section(")", 0, 0).simplified() + ")";
ex = ex.section("(", 1, 1).simplified();
buildString(ex, ls);
expr = expr.replace(reserve, "#val");
if(!expr.isEmpty()) buildString(expr, ls);
}
else if(expr.find(exp_diff) != -1) determDifficultOp(expr, ls, exp_diff);
else if(expr.find(exp_high) != -1) determOperation(expr, ls, exp_high, exp_low);
else if(expr.find(exp_low) != -1) determOperation(expr, ls, exp_low, exp_high);
}
/// Определение выполняемой операции и помощь в формировании строки
void CompParamDescr::determOperation(QString& expr, QStringList& ls, const QRegExp& exp, const QRegExp& d_exp)
{
QString left_expr = "", right_expr = "";
if(d_exp.indexIn(expr, 0) != -1)
{
left_expr = expr.section(d_exp, 0, 0).simplified();
right_expr = expr.section(d_exp, 1, 1).simplified();
if(left_expr.find(exp) != -1 && !left_expr.isEmpty() && ls.indexOf(left_expr) == -1) ls.append(left_expr);
else buildString(left_expr, ls);
if(right_expr.find(exp) != -1 && !right_expr.isEmpty() && ls.indexOf(right_expr) == -1) ls.append(right_expr);
else buildString(right_expr, ls);
if(!left_expr.isEmpty()) expr.replace(left_expr, "#val");
if(!right_expr.isEmpty()) expr.replace(right_expr, "#val");
if(!expr.isEmpty()) buildString(expr, ls);
}
else
{
left_expr = expr.section(exp, 0, 0).simplified();
right_expr = expr.section(exp, 1, 1).simplified();
if(!left_expr.isEmpty() && !right_expr.isEmpty() && right_expr.find(exp) == -1 &&
left_expr.find(exp) == -1)
{
if(ls.indexOf(expr) == -1) ls.append(expr);
expr.clear();
}
else if(!left_expr.isEmpty() && left_expr.find(exp) != -1) buildString(left_expr, ls);
else if(!right_expr.isEmpty() && right_expr.find(exp) != -1) buildString(right_expr, ls);
}
}
/// Определение выполняемой сложной функции и помощь в формировании строки
void CompParamDescr::determDifficultOp(QString& expr, QStringList& ls, const QRegExp& df_exp)
{
QString left_expr = "", right_expr = "", parameters = "";
const char *simple_op_low_priority = "[+-]", *simple_op_high_priority = "[*/]";
QRegExp exp_low(simple_op_low_priority), exp_high(simple_op_high_priority);
parameters = expr.section(df_exp, 1, 1).simplified();;
left_expr = parameters.section(",", 0, 0).simplified();
right_expr = parameters.section(",", 1, 1).simplified();
if(left_expr.find(exp_low) != -1) determOperation(left_expr, ls, exp_low, exp_high);
else if(left_expr.find(exp_high) != -1) determOperation(left_expr, ls, exp_high, exp_low);
if(right_expr.find(exp_low) != -1) determOperation(right_expr, ls, exp_low, exp_high);
else if(right_expr.find(exp_high) != -1) determOperation(right_expr, ls, exp_high, exp_low);
left_expr = parameters.section(",", 0, 0).simplified();
right_expr = parameters.section(",", 1, 1).simplified();
if((expr.find(exp_low) != -1 || expr.find(exp_high) != -1))
{ expr.replace(left_expr, "#val"); expr.replace(right_expr, "#val"); }
if(expr.find(df_exp) != -1) ls.append(expr);
}
/// Удаление скобок
QString CompParamDescr::remove_symbols(const char* op, QString expr)
{
if(strlen(op) < 2) return expr;
QString e = expr;
int pos = e.find("(");
e = e.replace(pos, 1, " ").simplified();
pos = e.lastIndexOf(")");
e = e.remove(pos, 1).simplified();
return e;
}
/// Вычисление большой формулы
COMPUTE* ElemFormul::calculateFormul(LOGRECORD* record, vector<ParamDescr*>* vec)
{
COMPUTE* result = 0;
int size = formul_list.size();
QList<double> result_values;
for(int i=0; i<size; ++i)
result = calc(record, vec, formul_list, result_values);
return result;
}
/// Получение индекса нужного параметра
int ElemFormul::argumentIndex(std::vector<ParamDescr*>* vec, QString arg)
{
int index = -1, i = 0;
if(isNumber(arg)) return index;
string ar = arg.toStdString();
for(paramI iter=vec -> begin(); iter!=vec -> end(); ++iter, ++i)
if((*iter) -> Name() == ar)
{
index = i;
break;
}
return index;
}
/// Вычисление простейших формул
COMPUTE* ElemFormul::calc(LOGRECORD* record, vector<ParamDescr*>* vec, QStringList& ls, QList<double>& rs_vl)
{
if(ls.empty()) return 0;
QString formul = ls.takeFirst();
COMPUTE* result = new COMPUTE();
QRegExp exp(BASE_OPERATIONS);
if(formul.find(exp) != -1)
{
string op = exp.capturedTexts().at(0).toStdString();
result -> op = op;
QString arg1 = "", arg2 = "";
if(op.size() < 2)
{
arg1 = formul.section(op.c_str(), 0, 0).simplified();
arg2 = formul.section(op.c_str(), 1, 1).simplified();
}
else
{
QString parameters = formul.section(op.c_str(), 1, 1).simplified();
arg1 = parameters.section(",", 0, 0).simplified();
arg2 = parameters.section(",", 1, 1).simplified();
}
if(isNumber(arg1)) result -> arg1 = arg1.toDouble();
if(isNumber(arg2)) result -> arg2 = arg2.toDouble();
result -> arg1_index = argumentIndex(vec, arg1);
result -> arg2_index = argumentIndex(vec, arg2);
if(result -> arg1_index != -1) if(record -> params[result -> arg1_index].status == PS_OK)
result -> arg1 = record -> params[result -> arg1_index].value;
if(result -> arg2_index != -1) if(record -> params[result -> arg2_index].status == PS_OK)
result -> arg2 = record -> params[result -> arg2_index].value;
if(arg2.find("#val") != -1 && arg1.find("#val") != -1) rs_vl.append(result -> GetValue());
int sz = rs_vl.size();
if(arg2.find("#val") != -1) result -> arg2 = (!rs_vl.empty()) ? rs_vl.takeFirst() : 1.0;
if(arg1.find("#val") != -1) result -> arg1 = (!rs_vl.empty()) ? rs_vl.takeFirst() : 1.0;
}
if(!ls.empty())
{
string next = ls.first().toStdString();
double vl = result -> GetValue();
if(next.find("#val") != -1) rs_vl.append(vl);
}
return result;
}
////////////////////////////////////////////////////////////////////////////////////////////
// Применение данных разработанных функций
/// Инициализация вычислимых параметров
void IniReader::InitComp(string& rec, vector<ParamDescr*>& rec_descr)
{
CompParamDescr* p = new CompParamDescr();
QString r = rec.c_str();
string name = r.section('=', 0, 0).simplified().toLower().toStdString();
p -> Name(name);
p -> Address(1000);
p -> ParamType("t_comp");
string expression = r.section('=', 1, 1).simplified().toLower().toStdString();
p -> Expr(expression);
p -> addFormul();
rec_descr.push_back(p);
}
/// Заполнение вычислимых параметров
void LogReader::FillCompParams(LOGRECORD& t)
{
int size = rec_descr.size();
for(int i=indexCompParam; i<rec_descr.size(); ++i)
{
CompParamDescr* p = dynamic_cast<CompParamDescr*> (rec_descr[i]);
ElemFormul formul(p -> formulList());
COMPUTE* element = formul.calculateFormul(&t, &rec_descr);
if(element != 0)
{
t.params[i].value = element -> GetValue();
t.params[i].status = PS_OK;
t.params[i].evn = 0;
}
}
}