diff options
Diffstat (limited to 'src/bin/cli')
| -rw-r--r-- | src/bin/cli/CMakeLists.txt | 63 | ||||
| -rw-r--r-- | src/bin/cli/cli.pri | 2 | ||||
| -rw-r--r-- | src/bin/cli/cmds.txt | 56 | ||||
| -rw-r--r-- | src/bin/cli/dice.qrc | 0 | ||||
| -rw-r--r-- | src/bin/cli/displaytoolbox.cpp | 168 | ||||
| -rw-r--r-- | src/bin/cli/displaytoolbox.h | 29 | ||||
| -rw-r--r-- | src/bin/cli/i18n/dice_en.ts | 74 | ||||
| -rw-r--r-- | src/bin/cli/i18n/dice_fr.ts | 75 | ||||
| -rw-r--r-- | src/bin/cli/main.cpp | 621 |
9 files changed, 1088 insertions, 0 deletions
diff --git a/src/bin/cli/CMakeLists.txt b/src/bin/cli/CMakeLists.txt new file mode 100644 index 0000000..07d080f --- /dev/null +++ b/src/bin/cli/CMakeLists.txt @@ -0,0 +1,63 @@ +cmake_minimum_required(VERSION 3.16) + +option(UPDATE_TRANSLATIONS "update Translation" OFF) +option(NO_PAINTER_OPERATOR "No PAINTING" OFF) +MESSAGE(STATUS "UPDATE TRANSLATIONS: ${UPDATE_TRANSLATIONS}") + +project(dice) + +# Find includes in corresponding build directories +set(CMAKE_INCLUDE_CURRENT_DIR ON) +# Instruct CMake to run moc automatically when needed. +set(CMAKE_AUTOMOC ON) +set(EXECUTABLE_OUTPUT_PATH bin/) + +# Find the QtWidgets library +set(QT_REQUIRED_VERSION "6.2.0") + +IF(NO_PAINTER_OPERATOR) + find_package(Qt6 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS Core Svg LinguistTools) +else() + MESSAGE(STATUS "Compilation of operator Paint") + find_package(Qt6 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS Core Gui Svg LinguistTools) + add_definitions(-DPAINTER_OP) +endif() + +set(MODE "cli") + +set(dice_RESOURCES diceparser.qrc) +find_package(Qt6LinguistTools) +find_package(Qt6Svg) + +IF(UPDATE_TRANSLATIONS) + MESSAGE( update Translation ) + FILE(GLOB_RECURSE translate_dice_SRCS ../*.cpp ../*.h) + SET(translate_SRCS ${translate_dice_SRCS}) + SET(dice_TS "${CMAKE_CURRENT_SOURCE_DIR}/i18n/dice_en.ts" "${CMAKE_CURRENT_SOURCE_DIR}/i18n/dice_fr.ts") +ELSE() + MESSAGE( NO updates for translations) + FILE(GLOB dice_TS "${CMAKE_CURRENT_SOURCE_DIR}/i18n/*.ts") +ENDIF(UPDATE_TRANSLATIONS) + +if(Qt6Core_FOUND) + MESSAGE(status "find" ${dice_TS} ${translate_SRCS} ) + QT_ADD_RESOURCES(dice_RESOURCES_RCC ${dice_RESOURCES}) + set(QT_PLUGINS_DIR "${Qt6Core_DIR}/../../../plugins") + get_target_property(QT_LIBRARY_DIR Qt6::Core LOCATION) + get_filename_component(QT_LIBRARY_DIR ${QT_LIBRARY_DIR} PATH) +endif() + +SET( cli_sources + main.cpp + displaytoolbox.cpp +) + +add_executable( dice ${cli_sources} ${dice_QM}) +set(diceparser_shared_INCLUDE_DIRS "../diceparser") +link_directories(BEFORE ${CMAKE_BINARY_DIR}) +IF(NO_PAINTER_OPERATOR) + target_link_libraries(dice PUBLIC Qt6::Core Qt6::Svg PRIVATE diceparser_shared) +ELSE() + target_link_libraries(dice PUBLIC Qt6::Core Qt6::Gui Qt6::Svg PRIVATE diceparser_shared) +ENDIF() +INSTALL_TARGETS(/bin dice) diff --git a/src/bin/cli/cli.pri b/src/bin/cli/cli.pri new file mode 100644 index 0000000..69aa44f --- /dev/null +++ b/src/bin/cli/cli.pri @@ -0,0 +1,2 @@ +SOURCES += \ + $$PWD/main.cpp diff --git a/src/bin/cli/cmds.txt b/src/bin/cli/cmds.txt new file mode 100644 index 0000000..f5c7e1e --- /dev/null +++ b/src/bin/cli/cmds.txt @@ -0,0 +1,56 @@ +1L[cheminée,chocolat,épée,arc,chute_de_pierre] +10d10c[>=6]-@c[=1] +10d10c[>=6]-@c[=1]-@c[=1] +10d10c[>6]+@c[=10] +1+1D10 +3d10c[>=5] +1+(4*3)D10 +2+4/4 +2D10*2D20*8 +1+(4*3)D10 +(4D6)D10 +1D100a[>=95]a[>=96]a[>=97]a[>=98]a[>=99]e[>=100] +3D100 +4k3 +10D10e[>=6]sc[>=6] +10D10e10s +10D10s +15D10e10c[8-10] +10d10e11 +1D8+2D6+7 +D25 +1L[tete[10],ventre[50],jambe[40]] +2d6c[%2=0] +D25+D10 +D25;D10 +8+8+8 +1D20-88 +100*1D20*2D6 +100/28*3 +100/8 +100*3*8 +help +la +10D10c[<2|>7] +1L[tete,bras_droit,bras_gauche,jambe_droite,jambe_gauche,ventre[6-7],buste[8-10]] +10D6c[=2|=4|=6] +10D10e[=1|=10]k4 +10+10s +1d6e6;1d4e4mk1 +1d6e6;1d4e4mk1 +1d100e[>=95]i[<5]{-1d100e95} +100*3*8 +1d100i[<70]{1d10i[=10]{1d100i[<70]{1d10e10}}} +10d[-8--1] +4d6p[4:black]c[>=4]+1d6p[1:white]c6-@c1+1d6p[1:red]c[>=4]+@c6-@c1 +10d[0-9] +10d10g10 +1d100 #Comment +1d6;1d8mk1 +1d20;1d10;$1-$2 +1d100i[<50]{"success %1"}{"fail %1"} +2d100i:[<201]{"success %2"}{"fail %2"} +3d100i*[<101]{"Success"}{"Fail"} +3d100i.[%2=0]{"%1 is even"}{"%1 is odd"} +d100+3;d20+8 + diff --git a/src/bin/cli/dice.qrc b/src/bin/cli/dice.qrc new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/bin/cli/dice.qrc diff --git a/src/bin/cli/displaytoolbox.cpp b/src/bin/cli/displaytoolbox.cpp new file mode 100644 index 0000000..1709d18 --- /dev/null +++ b/src/bin/cli/displaytoolbox.cpp @@ -0,0 +1,168 @@ +#include "displaytoolbox.h" +#include <QBuffer> +#include <QJsonArray> +#include <QJsonObject> + +#ifdef PAINTER_OP +#include <QFont> +#include <QFontMetrics> +#include <QPainter> +#include <QSvgRenderer> +#endif + +#include <QDebug> + +#define LINE_SPACING 5 + +DisplayToolBox::DisplayToolBox() {} +#ifdef PAINTER_OP +QString DisplayToolBox::makeImage(QByteArray svgCode) +{ + QSvgRenderer svg(svgCode); + + QImage image(500, 60, QImage::Format_ARGB32); + image.fill(QColor(255, 255, 255, 100)); // partly transparent red-ish background + + // Get QPainter that paints to the image + QPainter painter(&image); + svg.render(&painter); + QByteArray ba; + QBuffer buffer(&ba); + buffer.open(QIODevice::WriteOnly); + image.save(&buffer, "PNG"); + return ba.toBase64(); +} +#endif + +QString DisplayToolBox::colorToIntCode(QString str) +{ + if(str.isEmpty() || str == QStringLiteral("black")) + { + return QStringLiteral("0;31"); + } + else if(str == QStringLiteral("white")) + { + return QStringLiteral("97"); + } + else if(str == QStringLiteral("blue")) + { + return QStringLiteral("34"); + } + else if(str == QStringLiteral("red")) + { + return QStringLiteral("31"); + } + else if(str == QStringLiteral("black")) + { + return QStringLiteral("30"); + } + else if(str == QStringLiteral("green")) + { + return QStringLiteral("32"); + } + else if(str == QStringLiteral("yellow")) + { + return QStringLiteral("33"); + } + else if(str == QStringLiteral("cyan")) + { + return QStringLiteral("36"); + } + else if(str == QStringLiteral("reset")) + { + return QStringLiteral("0"); + } + return {}; +} + +QString DisplayToolBox::colorToTermCode(QString str) +{ + return QStringLiteral("\e[").append(DisplayToolBox::colorToIntCode(str)).append("m"); +} + +QString DisplayToolBox::diceToSvg(QJsonArray array, bool withColor, bool allSameColor, bool allSameFaceCount) +{ + Q_UNUSED(allSameColor) + if(allSameFaceCount) + { + QStringList result; + for(auto item : array) + { + QStringList subResult; + auto obj= item.toObject(); + auto values= obj["values"].toArray(); + for(auto valRef : values) + { + subResult.append(diceResultToString(valRef.toObject(), Output::Svg, withColor)); + } + result.append(subResult.join(',')); + } + return result.join(""); + } + else + { + QStringList result; + for(auto item : array) + { + QStringList subResult; + auto obj= item.toObject(); + auto values= obj["values"].toArray(); + + for(auto valRef : values) + { + subResult.append(diceResultToString(valRef.toObject(), Output::Svg, withColor)); + } + result.append(QStringLiteral("d%1:(").arg(obj["face"].toInt())); + if(withColor) + { + result.append(QStringLiteral("<tspan fill=\"%1\">").arg(obj["color"].toString())); + } + result.append(subResult.join(',')); + if(withColor) + { + result.append(QStringLiteral("</tspan>)")); + } + else + { + result.append(QStringLiteral(")")); + } + } + return result.join(""); + } +} +#include <QVariantList> + +QString DisplayToolBox::diceResultToString(QJsonObject val, Output type, bool hasColor) +{ + auto total= QString::number(val["total"].toDouble()); + auto color= val["color"].toString(); + auto subvalues= val["subvalues"].toArray(); + QStringList subStr; + + for(auto subval : subvalues) + { + subStr << QString::number(subval.toDouble()); + } + if(!subStr.isEmpty()) + { + total.append(QStringLiteral(" [%1]").arg(subStr.join(','))); + } + if(hasColor && !color.isEmpty()) + { + if(type == Output::Terminal) + { + total= QStringLiteral("%1%2%3") + .arg(DisplayToolBox::colorToTermCode(color)) + .arg(total) + .arg(DisplayToolBox::colorToTermCode(QStringLiteral("reset"))); + } + else if(type == Output::Svg) + { + total= QStringLiteral("%1%2%3") + .arg(QStringLiteral("<tspan fill=\"%1\">").arg(color)) + .arg(total) + .arg(QStringLiteral("</tspan>")); + } + } + return total; +} diff --git a/src/bin/cli/displaytoolbox.h b/src/bin/cli/displaytoolbox.h new file mode 100644 index 0000000..5a22b0f --- /dev/null +++ b/src/bin/cli/displaytoolbox.h @@ -0,0 +1,29 @@ +#ifndef GENERATEIMAGE_H +#define GENERATEIMAGE_H + +#include <QJsonArray> +#include <QString> + +#include "diceparser/diceparser.h" + +class DisplayToolBox +{ +public: + enum class Output + { + Svg, + Terminal, + Json, + Image + }; + DisplayToolBox(); +#ifdef PAINTER_OP + static QString makeImage(QByteArray svgCode); +#endif + static QString colorToIntCode(QString str); + static QString colorToTermCode(QString str); + static QString diceToSvg(QJsonArray array, bool withColor, bool allSameColor, bool allSameFaceCount); + static QString diceResultToString(QJsonObject val, Output type, bool hasColor); +}; + +#endif // GENERATEIMAGE_H diff --git a/src/bin/cli/i18n/dice_en.ts b/src/bin/cli/i18n/dice_en.ts new file mode 100644 index 0000000..3efc610 --- /dev/null +++ b/src/bin/cli/i18n/dice_en.ts @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="en_US"> +<context> + <name>QObject</name> + <message> + <location filename="../../diceparser.cpp" line="186"/> + <source>Nothing was understood</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../diceparser.cpp" line="603"/> + <source>Dice with %1 face(s) does not exist. Please, put a value higher than 0</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../diceparser.cpp" line="648"/> + <source>List is missing after the L operator. Please, add it (e.g : 1L[sword,spear,gun,arrow])</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../diceparser.cpp" line="905"/> + <source>Validator is missing after the c operator. Please, change it</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../diceparser.cpp" line="931"/> + <source>Validator is missing after the %1 operator. Please, change it</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../diceparser.cpp" line="943"/> + <source>This condition %1 introduces an endless loop. Please, change it</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../diceparser.cpp" line="954"/> + <source>Validator is missing after the e operator. Please, change it</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../node/keepdiceexecnode.cpp" line="48"/> + <source> You ask to keep %1 dice but the result only has %2</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../node/listaliasnode.cpp" line="55"/> + <source>List of Alias: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../node/helpnode.cpp" line="37"/> + <source>Rolisteam Dice Parser: +Full documentation at: %1</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../node/jumpbackwardnode.cpp" line="75"/> + <source> The @ operator expects dice result. Please check the documentation to fix your command.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../node/dicerollernode.cpp" line="30"/> + <source>No dice to roll</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../../node/scalaroperatornode.cpp" line="128"/> + <source>Division by zero</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/src/bin/cli/i18n/dice_fr.ts b/src/bin/cli/i18n/dice_fr.ts new file mode 100644 index 0000000..438e99b --- /dev/null +++ b/src/bin/cli/i18n/dice_fr.ts @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="fr_FR"> +<context> + <name>QObject</name> + <message> + <location filename="../../diceparser.cpp" line="186"/> + <source>Nothing was understood</source> + <translation>Rien n'a été compris</translation> + </message> + <message> + <location filename="../../diceparser.cpp" line="603"/> + <source>Dice with %1 face(s) does not exist. Please, put a value higher than 0</source> + <translation>Dés avec %1 face(s) n'existe pas. Si vous plait, demander une valeur supérieure à 0</translation> + </message> + <message> + <location filename="../../diceparser.cpp" line="648"/> + <source>List is missing after the L operator. Please, add it (e.g : 1L[sword,spear,gun,arrow])</source> + <translation>Liste manquante après l'operateur L. Veuillez l'ajouter (e.g : 1L[épée,lance,flingue,flèche]) </translation> + </message> + <message> + <location filename="../../diceparser.cpp" line="905"/> + <source>Validator is missing after the c operator. Please, change it</source> + <translation>Validateur est manquant après l'opérateur c, veuillez le définir</translation> + </message> + <message> + <location filename="../../diceparser.cpp" line="931"/> + <source>Validator is missing after the %1 operator. Please, change it</source> + <translation>Validateur est manquant après l'opérateur %1, veuillez le définir</translation> + </message> + <message> + <location filename="../../diceparser.cpp" line="943"/> + <source>This condition %1 introduces an endless loop. Please, change it</source> + <translation>La condition %1 introduit une boucle infinie. Veuillez la changer</translation> + </message> + <message> + <location filename="../../diceparser.cpp" line="954"/> + <source>Validator is missing after the e operator. Please, change it</source> + <translation>Validateur est manquant après l'opérateur e, veuillez le définir</translation> + </message> + <message> + <location filename="../../node/keepdiceexecnode.cpp" line="48"/> + <source> You ask to keep %1 dice but the result only has %2</source> + <translation>Vous souhaitez garder %1 dés mais le resultat n'a seulement que %2 dés</translation> + </message> + <message> + <location filename="../../node/listaliasnode.cpp" line="55"/> + <source>List of Alias: +</source> + <translation>Liste d'alias:</translation> + </message> + <message> + <location filename="../../node/helpnode.cpp" line="37"/> + <source>Rolisteam Dice Parser: +Full documentation at: %1</source> + <translation>Rolisteam Dice Parser: +Documentation complète sur: %1</translation> + </message> + <message> + <location filename="../../node/jumpbackwardnode.cpp" line="75"/> + <source> The @ operator expects dice result. Please check the documentation to fix your command.</source> + <translation>L'opérateur @ attend un résultat de dés. Veuillez vérifier la documentation pour réparer votre commande.</translation> + </message> + <message> + <location filename="../../node/dicerollernode.cpp" line="30"/> + <source>No dice to roll</source> + <translation>Aucun dé à lancer</translation> + </message> + <message> + <location filename="../../node/scalaroperatornode.cpp" line="128"/> + <source>Division by zero</source> + <translation>Division par zéro</translation> + </message> +</context> +</TS> diff --git a/src/bin/cli/main.cpp b/src/bin/cli/main.cpp new file mode 100644 index 0000000..0420ac3 --- /dev/null +++ b/src/bin/cli/main.cpp @@ -0,0 +1,621 @@ +/*************************************************************************** + * Copyright (C) 2014 by Renaud Guezennec * + * http://www.rolisteam.org/contact * + * * + * This file is part of DiceParser * + * * + * DiceParser is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include <QCommandLineOption> +#include <QCommandLineParser> +#include <QDebug> +#include <QFile> +#include <QJsonArray> +#include <QJsonDocument> +#include <QJsonObject> +#include <QRegularExpression> +#include <QSettings> +#include <QStringList> +#include <QTextStream> +#include <set> + +#ifdef PAINTER_OP +#include <QGuiApplication> +#else +#include <QCoreApplication> +#endif + +#include "diceparser/dicealias.h" +#include "diceparser/diceparser.h" +#include "diceparser/highlightdice.h" +#include "diceparser/parsingtoolbox.h" +#include "displaytoolbox.h" + +/** + * @page Dice + * The cli for DiceParser the new dice system from rolisteam. + * @section Build and install + * To build this program, type these command: + * - mkdir build + * - cd build + * - cmake ../ + * - make + * - make install + * @return + */ + +QTextStream out(stdout, QIODevice::WriteOnly); +QTextStream err(stderr, QIODevice::WriteOnly); +bool markdown= false; +constexpr char const* colorkey= {"dicecolor"}; +#ifdef PAINTER_OP +enum EXPORTFORMAT +{ + TERMINAL, + SVG, + IMAGE, + MARKDOWN, + JSON, + BOT, + TEXT +}; +#else +enum EXPORTFORMAT +{ + TERMINAL, + SVG, + MARKDOWN, + JSON, + BOT, + TEXT +}; +#endif +int returnValue= 0; + +void displayJSon(QString json) +{ + out << json << "\n"; +} +void displayMarkdown(QString json) +{ + QJsonDocument doc= QJsonDocument::fromJson(json.toUtf8()); + auto obj= doc.object(); + auto error= obj["error"].toString(); + auto warning= obj["warning"].toString(); + auto comment= obj["comment"].toString(); + auto arrayInst= obj["instructions"].toArray(); + QStringList diceResults; + for(auto inst : arrayInst) + { + auto obj= inst.toObject(); + auto diceVals= obj["diceval"].toArray(); + for(auto diceval : diceVals) + { + auto objval= diceval.toObject(); + auto resultStr= QString::number(objval["value"].toDouble()); + + auto subvalues= objval["subvalues"].toArray(); + QStringList subValueStr; + for(auto sub : subvalues) + { + subValueStr << QString::number(sub.toDouble()); + } + diceResults << resultStr; + if(!subValueStr.isEmpty()) + diceResults << QString("[%1]").arg(subValueStr.join(" ")); + } + } + auto diceList= diceResults.join(" "); + auto resultStr= obj["string"].toString(); + auto scalarText= obj["scalar"].toString(); + auto cmd= obj["command"].toString(); + + QString str("```Markdown\n"); + if(!error.isEmpty()) + { + str.append(QStringLiteral("Error: %1\n").arg(error)); + } + else + { + if(!warning.isEmpty()) + str.append(QStringLiteral("Warning: %1\n").arg(warning)); + + if(!comment.isEmpty()) + { + str.prepend(QStringLiteral("%1\n").arg(comment)); + } + if(!resultStr.isEmpty() && resultStr != scalarText) + { + // resultStr.replace("%2", diceList.trimmed()); + str.append(QStringLiteral("%1\n").arg(resultStr)); + } + else + { + str.append(QStringLiteral("# %1\nDetails:[%3 (%2)]\n").arg(scalarText).arg(diceList).arg(cmd)); + } + } + str.append(QStringLiteral("```")); + out << str; +} +QString displaySVG(QString json, bool withColor) +{ + QJsonDocument doc= QJsonDocument::fromJson(json.toUtf8()); + auto obj= doc.object(); + auto error= obj["error"].toString(); + auto warning= obj["warning"].toString(); + auto comment= obj["warning"].toString(); + auto arrayInst= obj["instructions"].toArray(); + QStringList diceResults; + for(auto inst : arrayInst) + { + auto obj= inst.toObject(); + auto diceVals= obj["diceval"].toArray(); + for(auto diceval : diceVals) + { + auto objval= diceval.toObject(); + auto resultStr= objval["string"].toString(); + diceResults << resultStr; + } + } + auto diceList= diceResults.join(","); + auto resultStr= obj["string"].toString(); + auto scalarText= obj["scalar"].toString(); + auto cmd= obj["command"].toString(); + + QString str("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<svg version=\"1.1\" " + "xmlns=\"http://www.w3.org/2000/svg\" " + "xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n"); + if(!error.isEmpty()) + { + str.append(QStringLiteral("<text font-size=\"16\" x=\"0\" y=\"20\"><tspan " + "fill=\"red\">%1</tspan></text>") + .arg(error)); + } + else + { + if(!warning.isEmpty()) + str.append(QStringLiteral("<text font-size=\"16\" x=\"0\" y=\"20\"><tspan " + "fill=\"orange\">%1</tspan></text>") + .arg(warning)); + + int y= 20; + if(!comment.isEmpty()) + { + str.append(QStringLiteral("<text font-size=\"16\" x=\"0\" y=\"%2\"><tspan " + "fill=\"blue\">%1</tspan></text>") + .arg(comment) + .arg(y)); + y+= 20; + } + // auto diceList= DisplayToolBox::diceToSvg(array, withColor, allSameColor, allSameFaceCount); + if(!resultStr.isEmpty() && resultStr != scalarText) + { + resultStr.replace("%2", diceList.trimmed()); + str.append(QStringLiteral("<text font-size=\"16\" x=\"0\" y=\"%2\">%1</text>").arg(resultStr).arg(y)); + } + else + { + if(withColor) + str.append(QStringLiteral("<text font-size=\"16\" x=\"0\" y=\"%4\"><tspan " + "fill=\"red\">%1</tspan>\n" + "<tspan x=\"0\" y=\"%5\">details:</tspan>[%3 (%2)]</text>") + .arg(scalarText) + .arg(diceList) + .arg(cmd) + .arg(y) + .arg(y * 2)); + else + str.append(QStringLiteral("<text font-size=\"16\" x=\"0\" y=\"%4\"><tspan>%1</tspan>\n" + "<tspan x=\"0\" y=\"%5\">details:</tspan>[%3 (%2)]</text>") + .arg(scalarText) + .arg(diceList) + .arg(cmd) + .arg(y) + .arg(y * 2)); + } + } + str.append(QStringLiteral("</svg>\n")); + return str; +} + +#ifdef PAINTER_OP +void displayImage(QString json, bool withColor) +{ + auto svg= displaySVG(json, withColor); + out << DisplayToolBox::makeImage(svg.toUtf8()); +} +#endif + +void displayCommandResult(QString json, bool withColor, QString color) +{ + QJsonDocument doc= QJsonDocument::fromJson(json.toUtf8()); + auto obj= doc.object(); + auto error= obj["error"].toString(); + auto warning= obj["warning"].toString(); + auto comment= obj["comment"].toString(); + auto arrayInst= obj["instructions"].toArray(); + QStringList diceResults; + for(const auto& inst : qAsConst(arrayInst)) + { + auto obj= inst.toObject(); + auto diceVals= obj["diceval"].toArray(); + for(const auto& diceval : qAsConst(diceVals)) + { + auto objval= diceval.toObject(); + auto resultStr= objval["string"].toString(); + diceResults << resultStr; + } + } + auto diceList= diceResults.join(","); + auto scalarText= obj["scalar"].toString(); + auto cmd= obj["command"].toString(); + auto resultStr= obj["string"].toString(); + + if(!error.isEmpty()) + { + err << "Error" << error << "\n"; + return; + } + + if(!warning.isEmpty()) + err << "Warning: " << warning << "\n"; + + QString str; + + if(withColor) + str= QString("Result: \e[0;%4;1m%1\e[0m - details:[%3 (%2)]") + .arg(scalarText, diceList, cmd, DisplayToolBox::colorToIntCode(color)); + else + str= QString("Result: %1 - details:[%3 (%2)]").arg(scalarText, diceList, cmd); + + if(!resultStr.isEmpty() && resultStr != scalarText) + { + resultStr.replace("%2", diceList.trimmed()); + str= resultStr; + } + + if(!comment.isEmpty()) + { + if(withColor) + out << "\033[1m" << comment << "\033[0m\n"; + else + out << comment << " "; + } + out << str << "\n"; +} + +int startDiceParsing(QStringList& cmds, bool withColor, QString baseColor, EXPORTFORMAT format, QJsonArray array, + const QString& filePath) +{ + DiceParser parser; + parser.insertAlias(new DiceAlias("L5R5R", QStringLiteral("L[-,⨀,⨀⬢,❂⬢,❁,❁⬢]")), 0); + parser.insertAlias(new DiceAlias("L5R5S", QStringLiteral("L[-,-,⨀,⨀,⨀❁,⨀⬢,⨀⬢,❂,❂⬢,❁,❁,❁]")), 1); + int i= 2; + for(auto alias : array) + { + auto objAlias= alias.toObject(); + parser.insertAlias(new DiceAlias(objAlias["pattern"].toString(), objAlias["cmd"].toString(), + objAlias["comment"].toString(), !objAlias["regexp"].toBool()), + i++); + } + + int rt= 0; + bool in_markdown= true; + + for(QString cmd : cmds) + { + if(cmd.startsWith('&') && format == BOT) + { + cmd= cmd.remove(0, 1); + in_markdown= false; + } + + if(parser.parseLine(cmd)) + { + parser.start(); + + std::set<EXPORTFORMAT> svgFormat({SVG, IMAGE, BOT}); + QString json; + bool allSameColor= true; + if(svgFormat.find(format) != svgFormat.end()) + { + allSameColor= true; + QString colorP; + json= parser.resultAsJSon( + [&colorP, &allSameColor](const QString& value, const QString& color, bool) { + if(colorP.isNull()) + colorP= color; + else if(colorP != color) + allSameColor= false; + + return value; + }, + true); + + if(!allSameColor) + { + json= parser.resultAsJSon([](const QString& value, const QString& color, bool highlight) { + QString result= value; + bool hasColor= !color.isEmpty(); + QString style; + if(hasColor) + { + style+= QStringLiteral("fill=\"%1\" ").arg(color); + } + if(highlight) + { + if(style.isEmpty()) + style+= QStringLiteral("fill=\"%1\" ") + .arg("red"); // default color must get the value from the setting object + style+= QStringLiteral("font-weight=\"bold\" "); + } + if(!style.isEmpty()) + result= QString("<tspan %2>%1</tspan>").arg(value).arg(style); + return result; + }); + } + } + else if(TERMINAL == format) + { + allSameColor= true; + QString colorP; + json= parser.resultAsJSon( + [&colorP, &allSameColor, &baseColor](const QString& result, const QString& color, bool hightlight) { + auto trueColor= color; + if(color.isEmpty()) + trueColor= baseColor; + + if(colorP.isEmpty()) + colorP= trueColor; + else if(colorP != trueColor) + allSameColor= false; + + auto front= DisplayToolBox::colorToTermCode(trueColor); + auto end= front.isEmpty() ? "" : DisplayToolBox::colorToTermCode("reset"); + return hightlight ? QString("%1%2%3").arg(front).arg(result).arg(end) : result; + }); + } + else + { + allSameColor= true; + json= parser.resultAsJSon([](const QString& result, const QString&, bool) { return result; }); + } + + if(format == BOT) + { + if(allSameColor) + { + format= in_markdown ? MARKDOWN : TEXT; + } + else + { +#ifdef PAINTER_OP + format= IMAGE; +#else + format= MARKDOWN; +#endif + } + if(!parser.humanReadableError().isEmpty()) + { + format= MARKDOWN; + } + } + if(!withColor && format == TERMINAL) + format= TEXT; + + // qDebug().noquote() << json << format; + + switch(format) + { + case TERMINAL: + displayCommandResult(json, withColor, baseColor); + break; + case SVG: + out << displaySVG(json, withColor) << "\n"; + break; + case BOT: + case MARKDOWN: + displayMarkdown(json); + break; + case TEXT: + displayCommandResult(json, false, baseColor); + break; + case JSON: + displayJSon(json); + break; +#ifdef PAINTER_OP + case IMAGE: + displayImage(json, withColor); + break; +#endif + } + if(!filePath.isEmpty()) + { + parser.writeDownDotTree(filePath); + } + } + else + rt= 1; + } + return rt; +} + +int main(int argc, char* argv[]) +{ +#ifdef PAINTER_OP + QGuiApplication a(argc, argv); +#else + QCoreApplication a(argc, argv); +#endif + + QStringList commands; + QString cmd; + QString dotFileStr; + bool colorb= true; + QSettings settings("rolisteam", "diceparser"); + QString formatColor; + EXPORTFORMAT format= TERMINAL; + + QCommandLineParser optionParser; + QCommandLineOption color(QStringList() << "c" + << "color-off", + "Disable color to highlight result"); + QCommandLineOption version(QStringList() << "v" + << "version", + "Show the version and quit."); + QCommandLineOption reset(QStringList() << "reset-settings", "Erase the settings and use the default parameters"); + QCommandLineOption alias(QStringList() << "a" + << "alias", + "path to alias json files: <aliasfile>", "aliasfile"); + + QCommandLineOption aliasData(QStringList() << "alias-data", "alias in json data <aliasdata>", "aliasdata"); + + QCommandLineOption character(QStringList() << "s" + << "charactersheet", + "set Parameters to simulate character sheet: <sheetfile>", "sheetfile"); + QCommandLineOption markdown(QStringList() << "m" + << "markdown", + "The output is formatted in markdown."); + QCommandLineOption bot(QStringList() << "b" + << "bot", + "Discord bot."); + QCommandLineOption svg(QStringList() << "g" + << "svg", + "The output is formatted in svg."); + QCommandLineOption outColor(QStringList() << "C" + << "color", + "Use color for result: <color>", "color"); + QCommandLineOption json(QStringList() << "j" + << "json", + "The output is formatted in json."); + QCommandLineOption line(QStringList() << "l" + << "line", + "The output is in one line [default]."); + QCommandLineOption dotFile(QStringList() << "d" + << "dot-file", + "Instead of rolling dice, generate the execution tree and write it in " + "<dotfile>", + "dotfile"); + QCommandLineOption translation(QStringList() << "t" + << "translation", + "path to the translation file: <translationfile>", "translationfile"); + QCommandLineOption help(QStringList() << "h" + << "help", + "Display this help"); + + optionParser.addOption(color); + optionParser.addOption(version); + optionParser.addOption(reset); + optionParser.addOption(dotFile); + optionParser.addOption(alias); + optionParser.addOption(aliasData); + optionParser.addOption(character); + optionParser.addOption(line); + optionParser.addOption(markdown); + optionParser.addOption(bot); + optionParser.addOption(svg); + optionParser.addOption(outColor); + optionParser.addOption(json); + optionParser.addOption(translation); + optionParser.addOption(help); + for(int i= 0; i < argc; ++i) + { + commands << QString::fromUtf8(argv[i]); + } + + optionParser.process(commands); + + if(optionParser.isSet(color)) + { + commands.removeAt(0); + colorb= false; + } + else if(optionParser.isSet(version)) + { + out << "Rolisteam DiceParser v1.0.0" + << "\n"; + out << "More Details: www.rolisteam.org" + << "\n"; + return 0; + } + else if(optionParser.isSet(reset)) + { + return 0; + } + else if(optionParser.isSet(dotFile)) + { + dotFileStr= optionParser.value(dotFile); + } + if(optionParser.isSet(markdown)) + { + format= MARKDOWN; + } + else if(optionParser.isSet(bot)) + { + format= BOT; + } + else if(optionParser.isSet(svg)) + { + format= SVG; + } + else if(optionParser.isSet(json)) + { + format= JSON; + } + else if(optionParser.isSet(line)) + { + format= TEXT; + } + if(optionParser.isSet(outColor)) + { + settings.setValue(colorkey, optionParser.value(outColor)); + } + + if(optionParser.isSet(help)) + { + cmd= "help"; + } + QStringList cmdList= optionParser.positionalArguments(); + + QJsonArray aliases; + if(optionParser.isSet(alias)) + { + auto aliasstr= optionParser.value(alias); + + QFile file(aliasstr); + + if(file.open(QIODevice::ReadOnly)) + { + QJsonDocument doc= QJsonDocument::fromJson(file.readAll()); + aliases= doc.array(); + } + } + else if(optionParser.isSet(aliasData)) + { + auto aliasstr= optionParser.value(aliasData); + QJsonDocument doc= QJsonDocument::fromJson(aliasstr.toUtf8()); + aliases= doc.array(); + } + + formatColor= settings.value(colorkey, "red").value<QString>(); + returnValue= startDiceParsing(cmdList, colorb, formatColor, format, aliases, dotFileStr); + if(optionParser.isSet(help)) + { + out << optionParser.helpText(); + } + return returnValue; +} |