diff --git a/src/app/lang.ts b/src/app/lang.ts index 5fa6896..4b1f2d1 100644 --- a/src/app/lang.ts +++ b/src/app/lang.ts @@ -4,32 +4,98 @@ export default function text(lang: string, input: string): string { switch (input) { case "header_title": return "OR-Tool"; - case "header_subtitle": - return "von Spaceholder Programming"; - case "boxObjTitle": - return "Ziel"; - case "boxObjDesc": - return "Gib hier dein Ziel ein. Es ist nur ein Ziel erlaubt. Verwende eine Zeile dafür (kein \"Return\"!). Erlaubte Symbole sind 0-9, a-z, A-Z und <>=.\nBeispiel:\nx + y\n-786433 x1 + 655361 x2"; - case "boxSubjTitle": - return "Nebenbedingungen"; - case "boxSubjDesc": - return "Gib hier dein Nebenbedingungen ein. Eines pro Zeile (trenne mit der 'Return'-Taste). Erlaubte Symbole sind 0-9, a-z, A-Z und <>=.\nBeispiel:\n+1 x + 2 y <= 15\n524321 x14 + 524305 x15 <= 4194303.5"; - case "boxBoundsTitle": - return "Grenzen"; - case "boxBoundsDesc": - return "Gib hier deine Grenzen ein. Eine pro Zeile (trenne mit der 'Return'-Taste). Erlaubte Symbole sind 0-9, a-z, A-Z und <>=.\nBeispiel:\nx >= 0\nx > 0\n0 <= x1 <= 1"; - case "boxVarsTitle": - return "Variablen"; - case "boxVarsDesc": - return "Liste alle deine Variablen auf. Eine pro Zeile (trenne mit der 'Return'-Taste). Erlaubte Symbole sind a-z, A-Z.\nBeispiel:\nx\ny"; - case "boxExportLP": - return "Exportieren als LP"; - case "boxOut": - return "Geben Sie ein Problem und eine Aktionstaste ein, um die Ausgabe anzuzeigen..."; - case "buttonCalc": - return "Berechnen"; + case "header_subtitle": + return "von Spaceholder Programming"; + case "boxObjTitle": + return "Ziel"; + case "boxObjDesc": + return "Geben Sie Ihr Ziel hier ein. Es ist nur ein Ziel erlaubt. Verwenden Sie eine Zeile dafür (kein 'Enter'!). Erlaubte Symbole sind 0-9, a-z, A-Z und <>=.\nBeispiel:\nx + y\n-786433 x1 + 655361 x2"; + case "boxSubjTitle": + return "Nebenbedingungen"; + case "boxSubjDesc": + return "Geben Sie Ihre Nebenbedingungen hier ein. Eine pro Zeile (mit der 'Enter'-Taste trennen). Erlaubte Symbole sind 0-9, a-z, A-Z und <>=.\nBeispiel:\n+1 x + 2 y <= 15\n524321 x14 + 524305 x15 <= 4194303.5"; + case "boxBoundsTitle": + return "Grenzen"; + case "boxBoundsDesc": + return "Geben Sie Ihre Grenzen hier ein. Eine pro Zeile (mit der 'Enter'-Taste trennen). Erlaubte Symbole sind 0-9, a-z, A-Z und <>=.\nBeispiel:\nx >= 0\nx > 0\n0 <= x1 <= 1"; + case "boxVarsTitle": + return "Variablen"; + case "boxVarsDesc": + return "Listen Sie alle Ihre Variablen auf. Eine pro Zeile (mit der 'Enter'-Taste trennen). Erlaubte Symbole sind a-z, A-Z.\nBeispiel:\nx\ny"; + case "boxExportLP": + return "Als LP exportieren"; + case "boxOut": + return "Geben Sie ein Problem ein und drücken Sie eine Aktionstaste, um die Ausgabe anzuzeigen..."; + case "buttonCalc": + return "Berechnen"; + case "etime": + return "Berechnungsdauer"; + case "seconds": + return "Sekunden"; + case "err_invalidInput": + return "Fehler: Ungültige Eingabe in"; + case "err_nullInput": + return "Fehler: NULL- oder undefinierte Eingabe in"; + case "err_invalidInput": + return "Fehler: Ungültige Eingabe oder fehlendes Zeichen in"; + case "input_checks_successful": + return "Alle Eingabeprüfungen erfolgreich."; + case "input_checks_start": + return "Starte Eingabeprüfungen..."; + case "obj_box": + return "Zielfeld"; + case "subj_box": + return "Bedingungsfeld"; + case "bounds_box": + return "Grenzenfeld"; + case "vars_box": + return "Variablenfeld"; + case "err_emptyBox": + return "Fehler: Leeres Textfeld."; + case "calculating": + return "Berechne..."; + case "maximize": + return "Maximieren"; + case "minimize": + return "Minimieren"; + case "run_optimization": + return "Optimierung mit Eingaben wird ausgeführt"; + case "startProblemSetup": + return "Starte Problemerstellung..."; + case "succProblemSetup": + return "Problem erstellt."; + case "startScaling": + return "Skalieren des Problems..."; + case "succScaling": + return "Skalierung erfolgreich."; + case "startOptimizationSimplex": + return "Starte Simplex-Optimierung..."; + case "succOptimizationSimplex": + return "Simplex-Optimierung abgeschlossen."; + case "startOptimizationInteger": + return "Starte Ganzzahloptimierung..."; + case "succOptimizationInteger": + return "Ganzzahloptimierung abgeschlossen."; + case "finalObjValue": + return "Endgültiger Zielfunktionswert"; + case "varsValues": + return "Wert jeder Variable"; + case "dualValues": + return "Dualwerte der Einschränkungen"; + case "downloadPrepFileString": + return "Dateiinhalt wird vorbereitet..."; + case "downloadPrepFile": + return "Datei wird vorbereitet..."; + case "downloadStart": + return "Download wird gestartet."; + case "downloadPrep": + return "Download wird vorbereitet..."; + case "downloadFetchInput": + return "Eingaben werden geladen..."; + case "importing": + return "Importiere..."; default: - return "Fehler: Übersetzung nicht gefunden"; + return input; } } @@ -63,8 +129,74 @@ export default function text(lang: string, input: string): string { return "Input a problem and an action button to display output..."; case "buttonCalc": return "Calculate"; + case "etime": + return "Elapsed time"; + case "seconds": + return "seconds"; + case "err_invalidInput": + return "Error: Invalid input in"; + case "err_nullInput": + return "Error: NULL or undefined input in"; + case "err_invalidInput": + return "Error: Invalid input or missing character in"; + case "input_checks_successful": + return "All input checks successful." + case "input_checks_start": + return "Starting input checks..."; + case "obj_box": + return "object box"; + case "subj_box": + return "subject box"; + case "bounds_box": + return "bounds box"; + case "vars_box": + return "variables box"; + case "err_emptyBox": + return "Error: Empty text box."; + case "calculating": + return "Calculating..."; + case "maximize": + return "Maximize"; + case "minimize": + return "Minimize"; + case "run_optimization": + return "Running optimization with input"; + case "startProblemSetup": + return "Starting problem setup..."; + case "succProblemSetup": + return "Problem created."; + case "startScaling": + return "Scaling problem..."; + case "succScaling": + return "Scaling successful."; + case "startOptimizationSimplex": + return "Starting simplex optimization..."; + case "succOptimizationSimplex": + return "Simplex optimization complete."; + case "startOptimizationInteger": + return "Starting integer optimization..."; + case "succOptimizationInteger": + return "Integer optimization complete."; + case "finalObjValue": + return "Final objective value"; + case "varsValues": + return "Value of each variable"; + case "dualValues": + return "Dual values of constraints"; + case "downloadPrepFileString": + return "Preparing file content string..."; + case "downloadPrepFile": + return "Preparing file..."; + case "downloadStart": + return "Starting download."; + case "downloadPrep": + return "Preparing download..."; + case "downloadFetchInput": + return "Fetching input..."; + case "importing": + return "Importing..."; default: - return "Error: Translation Not Found"; + return input; } } diff --git a/src/app/scripts.ts b/src/app/scripts.ts index 144adcd..81b86da 100644 --- a/src/app/scripts.ts +++ b/src/app/scripts.ts @@ -9,8 +9,6 @@ import text from "./lang" // custom log so we can append the output dynamically function customLog(input: string) { - - // get language const lang = (document.getElementById('language_current') as HTMLSelectElement)?.value; @@ -34,6 +32,14 @@ function customLogClear() { } } +function getTranslation(input: string) { + // get language + const lang = (document.getElementById('language_current') as HTMLSelectElement)?.value; + + // return translation + return text(lang, input); +} + function walltimeStopAndPrint(startpoint: number) { // calculating elapsed time as timestamp let duration = Date.now() - startpoint; @@ -46,7 +52,8 @@ function walltimeStopAndPrint(startpoint: number) { const durationFormatted = seconds + (milliseconds >= 0 ? "." : ".") + Math.abs(milliseconds).toFixed(3).slice(2); // Printing elapsed time - customLog("Elapsed time: " + durationFormatted + " seconds
"); + customLog(getTranslation("etime") + ": " + durationFormatted + " " + getTranslation("seconds")); + customLog(""); // return durationFormatted; } @@ -56,11 +63,11 @@ function walltimeStart() { } function isInputValidRegex(obj: string | undefined, subj: string | undefined, bounds: string | undefined, vars: string | undefined): boolean { - customLog("Starting input checks..."); - + customLog("input_checks_start"); + // standard case: input is undefined - invalid - if (obj === undefined || obj === null || subj === undefined || subj === null || bounds === undefined || bounds === null || vars === undefined || vars === null) { - customLog("Error: Function isInputValidRegex received undefined or null input."); + if (obj === undefined || obj === null || subj === undefined || subj === null || bounds === undefined || bounds === null || vars === undefined || vars === null) { + customLog(getTranslation("err_nullInput") + "function isInputValidRegex."); return false; } @@ -68,54 +75,54 @@ function isInputValidRegex(obj: string | undefined, subj: string | undefined, bo let regex = /^[ (\n)]*[\+-]? *((\d+(.\d+)? )?[a-zA-Z][a-zA-Z0-9]*)( *[\+-] *((\d+(.\d+)? )?[a-zA-Z][a-zA-Z0-9]*))*[ (\n)]*$/g; let isValid = regex.test(obj); if (!isValid) { - customLog("Error: Invalid or missing character in object box."); - return false; + customLog(getTranslation("err_invalidInput") + " " + getTranslation("obj_box") + "."); + return false; } // RegEx check for subject regex = /^([ (\n)]*[\+-]* *(\d+(.\d+)? )?[a-zA-Z][a-zA-Z0-9]*( *[\+-] *(\d+(.\d+)? )?[a-zA-Z][a-zA-Z0-9]*)* *((<=?)|(>=?)|=) *[\+-]? *\d+(.\d+)?[ (\n)]*)+$/g; isValid = regex.test(subj); if (!isValid) { - customLog("Error: Invalid or missing character in subject box."); - return false; + customLog(getTranslation("err_invalidInput") + " " + getTranslation("subj_box") + "."); + return false; } -// RegEx check for subject -regex = /[ (\n)]*(([a-zA-Z][a-zA-Z0-9]* *((<=?)|(>=?)|=) *\d(.\d+)?)|((\d(.\d+)?) *<=? *[a-zA-Z][a-zA-Z0-9]* *<= *(\d(.\d+)?)))[ (\n)]*/g; -isValid = regex.test(bounds); -if (!isValid) { - customLog("Error: Invalid or missing character in bounds box."); + // RegEx check for subject + regex = /[ (\n)]*(([a-zA-Z][a-zA-Z0-9]* *((<=?)|(>=?)|=) *\d(.\d+)?)|((\d(.\d+)?) *<=? *[a-zA-Z][a-zA-Z0-9]* *<= *(\d(.\d+)?)))[ (\n)]*/g; + isValid = regex.test(bounds); + if (!isValid) { + customLog(getTranslation("err_invalidInput") + " " + getTranslation("bounds_box") + "."); return false; -} + } // RegEx check for variables regex = /^ *([a-zA-Z][a-zA-Z0-9]*(\n)* *)+$/g; isValid = regex.test(vars); if (!isValid) { - customLog("Error: Invalid or missing character in variables box."); + customLog(getTranslation("err_invalidInput") + " " + getTranslation("vars_box") + "."); return false; } - customLog("All input checks successful."); + customLog("input_checks_successful"); customLog(""); return true; } function isInputFilled(obj: string | undefined, subj: string | undefined, bounds: string | undefined, vars: string | undefined) { if (obj == "" || obj == null || obj == undefined) { - customLog("Error: Empty input field."); + customLog("err_emptyBox"); return false; } if (subj == "" || subj == null || subj == undefined) { - customLog("Error: Empty input field."); + customLog("err_emptyBox"); return false; } if (bounds == "" || bounds == null || bounds == undefined) { - customLog("Error: Empty input field."); + customLog("err_emptyBox"); return false; } if (vars == "" || vars == null || vars == undefined) { - customLog("Error: Empty input field."); + customLog("err_emptyBox"); return false; } return true; @@ -124,7 +131,8 @@ function isInputFilled(obj: string | undefined, subj: string | undefined, bounds export function calculate_click() { customLogClear(); const timer = walltimeStart(); - customLog("Calculating...
"); + customLog("calculating"); + customLog(""); let objective: string | undefined; const objectiveElement = document.getElementById('objective'); @@ -199,7 +207,7 @@ export function calculate_click() { // console.log(parseFunction(decider)); - + // catch error: empty input field(s) if (!isInputFilled(objective, subject, bounds, variables)) return; @@ -207,59 +215,66 @@ export function calculate_click() { if (!isInputValidRegex(objective, subject, bounds, variables)) return; let wholeText: string = "Maximize\n obj: " + objective - + "\nSubject To \n" + subject - + "\nBounds \n" + bounds - + "\nGenerals \n" + variables - + "\nEnd"; + + "\nSubject To \n" + subject + + "\nBounds \n" + bounds + + "\nGenerals \n" + variables + + "\nEnd"; // customLog("

DEBUGGING

\nfunctions:
" + functions + "

variables:
" + variables + "

DEBUGGING END
"); - customLog("Running optimization with input: \"" + wholeText + "\"
"); + customLog(getTranslation("run_optimization") + ": \"" + wholeText + "\""); + customLog(""); run(wholeText); walltimeStopAndPrint(timer); } function run(text: string) { - customLog("Starting problem setup..."); + customLog("startProblemSetup"); let lp = GLPKAPI.glp_create_prob(); GLPKAPI.glp_read_lp_from_string(lp, null, text); - customLog("Problem created.
"); + customLog("succProblemSetup"); + customLog(""); - customLog("Scaling problem..."); + customLog("startScaling"); GLPKAPI.glp_scale_prob(lp, GLPKAPI.GLP_SF_AUTO); - customLog("Scaling complete.
"); + customLog("succScaling"); + customLog(""); - customLog("Starting simplex optimization..."); + customLog("startOptimizationSimplex"); let smcp = new GLPKAPI.SMCP({ presolve: GLPKAPI.GLP_ON }); GLPKAPI.glp_simplex(lp, smcp); - customLog("Simplex optimization complete.
"); + customLog("succOptimizationSimplex"); + customLog(""); - customLog("Starting integer optimization..."); + customLog("startOptimizationInteger"); let iocp = new GLPKAPI.IOCP({ presolve: GLPKAPI.GLP_ON }); GLPKAPI.glp_intopt(lp, iocp); - customLog("Integer optimization complete.
"); + customLog("succOptimizationInteger"); + customLog(""); // customLog("obj: " + GLPKAPI.glp_mip_obj_val(lp)); - customLog("Final objective value: " + GLPKAPI.glp_mip_obj_val(lp) + "
"); - customLog("Value of each variable:"); - for (let i = 1; i <= GLPKAPI.glp_get_num_cols(lp) - 1; i++) { // "-1" to remove the "End-variable" from logs + customLog("" + getTranslation("finalObjValue") + ": " + GLPKAPI.glp_mip_obj_val(lp) + ""); + customLog(""); + customLog(getTranslation("varsValues") + ":"); + for (let i = 1; i <= GLPKAPI.glp_get_num_cols(lp); i++) { customLog(GLPKAPI.glp_get_col_name(lp, i) + " = " + GLPKAPI.glp_mip_col_val(lp, i)); } customLog(""); - customLog("Dual values of constraints:"); - for (let j = 1; j <= GLPKAPI.glp_get_num_rows(lp); j++) { - const dualValue = GLPKAPI.glp_get_row_dual(lp, j); // fetch dual - const constraintName = GLPKAPI.glp_get_row_name(lp, j); - customLog(constraintName + " dual = " + dualValue); - } + customLog(getTranslation("dualValues") + ":"); + for (let j = 1; j <= GLPKAPI.glp_get_num_rows(lp); j++) { + const dualValue = GLPKAPI.glp_get_row_dual(lp, j); // fetch dual + const constraintName = GLPKAPI.glp_get_row_name(lp, j); + customLog(constraintName + " dual = " + dualValue); + } customLog(""); } function downloadLPFormatting(objective: any, subject: any, bounds: any) { - customLog("Preparing file content string...
"); - + customLog(getTranslation("downloadPrepFileString")); + customLog(""); + // ensure that all vars are strings const formattedObjective = typeof objective === 'string' ? objective : ''; const formattedSubject = typeof subject === 'string' ? subject : ''; @@ -287,19 +302,22 @@ function downloadLPFormatting(objective: any, subject: any, bounds: any) { function downloadProblemDownload(content: string) { - customLog("Preparing file...
") + customLog("downloadPrepFile"); + customLog(""); const blob = new Blob([content], { type: 'text/plain' }); const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = 'problem.txt'; // file name link.click(); // starting download - customLog("Starting download.") + customLog("downloadStart"); } export function downloadLP() { customLogClear(); - customLog("Preparing download...
"); - customLog("Fetching input...
") + customLog("downloadPrep"); + customLog(""); + customLog("downloadFetchInput"); + customLog(""); let objective: string | undefined; const objectiveElement = document.getElementById('objective'); @@ -344,7 +362,7 @@ export function downloadLP() { export function import_click() { - console.log("Importing..."); + console.log("importing"); }