import Vue from 'vue/dist/vue.esm.js';
export default function() {
const rptParser = new Vue({
el: '#rpt-parser',
data: {
processing: false,
removeDuplicates: true,
showExplaination: true,
rptLines: [],
errors: [],
startOfError: /error in expression/i,
errorPosition: /error position: <(.*)$/i,
errorReason: /error\s(.*)$/i,
errorInfos: [
/file\s*.*,\s*line\s*\d+/i,
/callextension.*could not be found/i
],
genericMessages: [
//CallExtension 'updatearmalog' could not be found
/callextension .* could not be found$/i,
//Warning Message: File mpmissions\__cur_mp.Lythium\description.ext, line 100: .CfgNetworkMessages: Member already defined.
/warning message: .* member already defined\.$/i,
//Warning Message: File mpmissions\Exile.Chernarus_winter\description.ext, line 193: /CfgInteractionMenus/: Missing '}'
/warning message: .* missing '}'/i,
// File mpmissions\__cur_mp.Lythium\config.cpp, line 2238: '/CfgExileArsenal/srifle_LRR_camo_F.price': Missing ';' prior '}'
/file .*: missing .*/i
],
reasons: [
{
regex: /foreign error: unknown enum value: (.*)/gi,
reason: "The enum value '$1' is not a valid value for this command.<br>Double check spelling or the biki for the proper enum values for this command"
},
{
regex: /missing ;/gi,
reason: `
You are missing a <code>;</code> or you have an extra one on or before this line of code.<br>Unfortunately, Arma decides to throw this error if you are missing or have extras of any of the following: <code>()</code>, <code>{}</code>, <code>[]</code><br>We suggest looking around this line for anything out of the ordinary and double check everything!`
},
{
regex: /invalid number in expression/gi,
reason: "A variable or part of this command is expecting a number, but it isn't valid.<br>Follow the code and make sure the value sent to this is indeed a number"
},
{
regex: /generic error in expression/gi,
reason: "This is BIS's way of saying, <i>We don't know what went wrong, it's just wrong</i><br>This is one of the hardest errors to troubleshoot. We suggest making sure the code on or around the reported file line is valid syntax"
},
{
regex: /callextension '(.*)' could not be found/i,
reason: "Make sure <code>$1.dll</code> or <code>$1_x64.dll</code> in the mod or server folder and <code>$1</code> is the correct spelling of the DLL."
},
{
// Warning Message: File mpmissions\__cur_mp.Lythium\description.ext, line 100: .CfgNetworkMessages: Member already defined.
regex: /warning message: (.*): \.(.*): member already defined\.$/i,
reason: "In <code>$1</code>, around that line there is <code>class $2</code>. Somewhere in this file, this class already exists.<br>Be careful, sometimes files are included by <code>#include</code>. Make sure to check these files as well for this duplicated class."
},
{
regex: /warning message: (.*) missing '}'/i,
reason: "In <code>$1</code>, around that line (either before, on, or after), you are missing OR have an extra <code>}</code>.<br>Often times this will throw because you have an extra <code>};</code>"
},
{
// Undefined variable in expression: _export
regex: /undefined variable in expression: (.*)/i,
reason: `<code>$1</code> has not been defined/initialized by the engine. This could happen for a number of reasons:<ul class="uk-list uk-list-bullet"><li>It was never initialized correctly</li><li>The variable was assigned <code>nil</code></li><li>The variable was a parameter for the script and was not passed a value</li></ul>`
},
{
// File mpmissions\__cur_mp.Lythium\config.cpp, line 2238: '/CfgExileArsenal/srifle_LRR_camo_F.price': Missing ';' prior '}'
regex: /File (.*), line (.*): '(.*)': missing '(.*)' prior '(.*)'/i,
reason: "In file <code>$1</code>, around line <code>$2</code>, there is a config for <code>$3</code>. That config is missing or has an extra <code>$4</code> before <code>$5</code>."
}
]
},
methods: {
updateFileName: function() {
if ($("#uploader").prop("files").length > 0) {
$("#file-name").text($("#uploader").prop("files")[0].name);
}
},
start: function() {
let that = this;
this.rptLines = [];
this.errors = [];
this.processing = true;
if ($("#uploader").prop("files").length > 0) {
let file = $("#uploader").prop("files")[0];
let reader = new FileReader();
reader.onload = (event) => {
let file = event.target.result;
file.split(/\r\n|\n/).map((line) => {
that.rptLines.push(line);
});
that.startParse();
};
reader.onerror = (evt) => {
Toaster.error(evt.target.error.name);
};
reader.readAsText(file);
$("#btnParse").addClass("uk-disabled");
} else {
return Toaster.warn("Please select a RPT to parse");
}
},
startParse: function() {
if (this.rptLines.length === 0) return Toaster.error("Fail to read RPT");
this.parseRPT();
if (this.removeDuplicates) {
this.filterErrors();
}
if (this.showExplaination) {
this.addExplainations();
}
if (_.isEmpty(this.errors)) {
Toaster.success("No errors found", "Parsing completed");
} else {
Toaster.warn(`Found ${this.errors.length} errors`, "Parsing completed");
}
this.processing = false;
$("#btnParse").removeClass("uk-disabled");
},
parseRPT: function() {
let inError = false,
currentError = {
code: "",
reason: "",
info: "",
rptLine: 0,
explaination: ""
},
lineCount = 0;
for (let i = 0; i < this.rptLines.length; i++)
{
let line = this.rptLines[i];
lineCount++;
if (!inError) {
for (let message of this.genericMessages) {
var match = message.exec(line);
if (match !== null) {
currentError = {
code: "",
reason: "",
info: match,
rptLine: i,
explaination: ""
};
this.errors.push(currentError);
}
}
}
if (!inError && this.startOfError.test(line)) {
currentError = {
code: "",
reason: "",
info: "",
rptLine: i,
explaination: ""
};
inError = true;
lineCount = 0;
continue;
}
if (inError) {
if (lineCount >= 30) {
this.errors.push(currentError);
inError = false;
continue;
}
let positionMatch = this.errorPosition.exec(line);
if (positionMatch !== null) {
currentError["code"] = positionMatch[1];
continue;
}
let reasonMatch = this.errorReason.exec(line);
if (reasonMatch !== null) {
currentError["info"] = reasonMatch[1];
continue;
}
for (let regex of this.errorInfos) {
let match = regex.exec(line);
if (match !== null) {
currentError["reason"] = match[0];
this.errors.push(currentError);
inError = false;
break;
}
}
}
}
},
filterErrors: function() {
if (this.errors.length === 0) return;
let filtered = [];
for (let error of this.errors)
{
if (filtered.length === 0) {
filtered.push(error);
continue;
}
let found = false;
for (let obj of filtered)
{
if (
(obj.code !== "" && obj.code === error.code)
&& (obj.info !== "" && obj.info === error.info)
&& (obj.reason !== "" && obj.reason === error.reason)
) {
found = true;
break;
};
}
if (found) continue;
filtered.push(error);
}
this.errors = _.cloneDeep(filtered);
},
addExplainations: function() {
if (_.isEmpty(this.errors)) return;
for (let error of this.errors) {
for (let reason of this.reasons) {
let reasonRegex = reason.regex;
let reasonText = reason.reason;
let match = reasonRegex.exec(error.info);
if (match !== null) {
if (_.isArray(match)) {
reasonText = match[0].replace(reasonRegex, reasonText);
}
error.explaination = reasonText;
break;
}
}
}
}
}
});
}