Private
Public Access
Implemented single line if statements
This commit is contained in:
1 parent
555de0b62b
commit
affc6d6e53
3 files changed
+222
-194
No files matched your search
@@ -1,4 +1,5 @@
|
|||||||
using Advanced_Software_Engineering.Verbs.Value;
|
using Advanced_Software_Engineering.Verbs.Value;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Advanced_Software_Engineering.Verbs.Flow {
|
namespace Advanced_Software_Engineering.Verbs.Flow {
|
||||||
public class IfChunk : VerbChunk, IVerb {
|
public class IfChunk : VerbChunk, IVerb {
|
||||||
@@ -9,6 +10,10 @@ namespace Advanced_Software_Engineering.Verbs.Flow {
|
|||||||
this.conditional = conditional;
|
this.conditional = conditional;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IfChunk(IValue conditional, IVerb oneLineVerb) : base(new List<IVerb> { oneLineVerb }) {
|
||||||
|
this.conditional = conditional;
|
||||||
|
}
|
||||||
|
|
||||||
public new void ExecuteVerb() {
|
public new void ExecuteVerb() {
|
||||||
if (conditional.ToBool()) base.ExecuteVerb();
|
if (conditional.ToBool()) base.ExecuteVerb();
|
||||||
}
|
}
|
||||||
|
|||||||
+61
-60
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using Advanced_Software_Engineering.Verbs.Value.ValueTypes;
|
||||||
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
|
||||||
namespace Advanced_Software_Engineering.Verbs.Value {
|
namespace Advanced_Software_Engineering.Verbs.Value {
|
||||||
@@ -122,77 +123,77 @@ namespace Advanced_Software_Engineering.Verbs.Value {
|
|||||||
|
|
||||||
public static IValue ConvertToIValue(string text, ValueStorage storage = null) {
|
public static IValue ConvertToIValue(string text, ValueStorage storage = null) {
|
||||||
text = HelperFunctions.Strip(text);
|
text = HelperFunctions.Strip(text);
|
||||||
|
string value = text;
|
||||||
|
//seperate assignment characters from everything else TODO FIX
|
||||||
|
foreach (string op in new string[] { "=", "+", "-", "*", "/", "<", ">", "!" }) {
|
||||||
|
value = value.Replace(op, " " + op + " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
value = HelperFunctions.Strip(value);
|
||||||
|
if (value[0] == "="[0]) {
|
||||||
|
value = value.Substring(1);
|
||||||
|
}
|
||||||
|
// now will definitly look like this:
|
||||||
|
// 10 + i or i
|
||||||
|
|
||||||
|
string[] assignmentStrings = HelperFunctions.StripStringArray(value.Split(" "[0])).ToArray();
|
||||||
|
|
||||||
//No assignmnet
|
//No assignmnet
|
||||||
if (!text.Contains("=")) {
|
|
||||||
if (!text.Contains("#")) {
|
|
||||||
//Check if string is a number
|
|
||||||
if (!text.Contains(".")) {
|
|
||||||
try {
|
|
||||||
return ValueFactory.CreateValue(text, "int");
|
|
||||||
} catch (Exception) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check if string is a double
|
if (!text.Contains("#")) {
|
||||||
else {
|
//Check if string is a number
|
||||||
try {
|
if (!text.Contains(".")) {
|
||||||
return ValueFactory.CreateValue(text, "double");
|
|
||||||
} catch (Exception) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check if color
|
|
||||||
try {
|
try {
|
||||||
return ValueFactory.CreateValue(text, "color");
|
return ValueFactory.CreateValue(text, "int");
|
||||||
} catch (Exception) { }
|
} catch (Exception) { }
|
||||||
|
}
|
||||||
|
|
||||||
//check for expression
|
//Check if string is a double
|
||||||
if (storage != null) {
|
else {
|
||||||
try {
|
|
||||||
string value = text;
|
|
||||||
//seperate assignment characters from everything else
|
|
||||||
foreach (string op in new string[] { "=", "+", "-", "*", "/" }) {
|
|
||||||
value = value.Replace(op, " " + op + " ");
|
|
||||||
}
|
|
||||||
|
|
||||||
value = HelperFunctions.Strip(value);
|
|
||||||
if (value[0] == "="[0]) {
|
|
||||||
value = value.Substring(1);
|
|
||||||
}
|
|
||||||
// now will definitly look like this:
|
|
||||||
// 10 + i or i
|
|
||||||
|
|
||||||
string[] assignmentStrings = HelperFunctions.StripStringArray(value.Split(" "[0])).ToArray();
|
|
||||||
|
|
||||||
// assignmentStrings will look something like this:
|
|
||||||
// ["i"] or ["10", "+", "i"]
|
|
||||||
if (assignmentStrings.Length == 1) return ValueFactory.CreateValue(storage, assignmentStrings[0]);
|
|
||||||
else if (assignmentStrings.Length == 3) {
|
|
||||||
// assignmentStrings looks like this => ["10", "+", "i"]
|
|
||||||
IValue value1 = ValueFactory.CreateValue(storage, assignmentStrings[0]);
|
|
||||||
string op = assignmentStrings[1];
|
|
||||||
IValue value2 = ValueFactory.CreateValue(storage, assignmentStrings[2]);
|
|
||||||
return new ExpressionValue(value1, value2, op);
|
|
||||||
}
|
|
||||||
} catch (Exception) { }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//Check if color
|
|
||||||
try {
|
try {
|
||||||
return ValueFactory.CreateValue(text, "color");
|
return ValueFactory.CreateValue(text, "double");
|
||||||
|
} catch (Exception) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if color
|
||||||
|
try {
|
||||||
|
return ValueFactory.CreateValue(text, "color");
|
||||||
|
} catch (Exception) { }
|
||||||
|
|
||||||
|
//check for expression
|
||||||
|
if (storage != null) {
|
||||||
|
try {
|
||||||
|
// assignmentStrings will look something like this:
|
||||||
|
// ["i"] or ["10", "+", "i"]
|
||||||
|
if (assignmentStrings.Length == 1) return ValueFactory.CreateValue(storage, assignmentStrings[0]);
|
||||||
|
else if (assignmentStrings.Length == 3) {
|
||||||
|
// assignmentStrings looks like this => ["10", "+", "i"]
|
||||||
|
IValue value1 = ValueFactory.CreateValue(storage, assignmentStrings[0]);
|
||||||
|
string op = assignmentStrings[1];
|
||||||
|
IValue value2 = ValueFactory.CreateValue(storage, assignmentStrings[2]);
|
||||||
|
return new ExpressionValue(value1, value2, op);
|
||||||
|
}
|
||||||
} catch (Exception) { }
|
} catch (Exception) { }
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//Check if string is a bool
|
//Check if color
|
||||||
|
try {
|
||||||
|
return ValueFactory.CreateValue(text, "color");
|
||||||
|
} catch (Exception) { }
|
||||||
|
}
|
||||||
|
|
||||||
//Check if expression
|
if (storage != null) {
|
||||||
if (storage != null) {
|
// Check if string is a comparison
|
||||||
string value = text;
|
// assignmentStrings will look something like this:
|
||||||
value = HelperFunctions.Strip(value);
|
// ["i"] or ["10", "=", "i"]
|
||||||
if (value[0] == "="[0]) {
|
if (assignmentStrings.Length == 3) {
|
||||||
value = value.Substring(1);
|
IValue value1 = ValueFactory.CreateValue(storage, assignmentStrings[0]);
|
||||||
}
|
string op = assignmentStrings[1];
|
||||||
return ConvertToIValue(value, storage);
|
IValue value2 = ValueFactory.CreateValue(storage, assignmentStrings[2]);
|
||||||
|
return new ComparisonValue(value1, value2, op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception("Could not convert " + text + " to any type");
|
throw new Exception("Could not convert " + text + " to any type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+156
-134
@@ -46,7 +46,8 @@ namespace Advanced_Software_Engineering {
|
|||||||
string[] commandParameters = result.getParameters();
|
string[] commandParameters = result.getParameters();
|
||||||
if (command == null) throw new Exception("There is no command to process");
|
if (command == null) throw new Exception("There is no command to process");
|
||||||
|
|
||||||
IVerb tmpVerb;
|
IVerb tmpVerb = null;
|
||||||
|
bool parsed = false;
|
||||||
|
|
||||||
//check for names in directory
|
//check for names in directory
|
||||||
if (rootValueStorage.CheckVariableExists(command)) {
|
if (rootValueStorage.CheckVariableExists(command)) {
|
||||||
@@ -59,7 +60,7 @@ namespace Advanced_Software_Engineering {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//process declarations
|
//process declarations
|
||||||
if (!(commandParameters == null))
|
if (!(commandParameters == null) && !parsed) {
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case "var":
|
case "var":
|
||||||
if (commandParameters.Length == 1) {
|
if (commandParameters.Length == 1) {
|
||||||
@@ -80,159 +81,180 @@ namespace Advanced_Software_Engineering {
|
|||||||
return new NoOp();
|
return new NoOp();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<IValue> parameters = new List<IValue>();
|
|
||||||
if (!(commandParameters == null)) foreach (string parameter in commandParameters) {
|
|
||||||
parameters.Add(ValueFactory.CreateValue(rootValueStorage, parameter));
|
|
||||||
}
|
|
||||||
int parameterLength = parameters.Count;
|
|
||||||
|
|
||||||
|
//Parse flow verbs
|
||||||
|
|
||||||
//process drawing commands and extras
|
|
||||||
switch (command) {
|
switch (command) {
|
||||||
//Drawing commands
|
case "if":
|
||||||
case "move":
|
if (commandParameters.Length == 1) {
|
||||||
case "moveto":
|
verbChunks.Add(new IfChunk(ValueFactory.CreateValue(rootValueStorage, commandParameters[0])));
|
||||||
//Check parameters
|
chunkDepth = verbChunks.Count - 1;
|
||||||
if (parameterLength == 2) {
|
currentChunk = verbChunks[chunkDepth];
|
||||||
tmpVerb = new MoveTo(drawer, new PointValue(parameters[0], parameters[1]));
|
parsed = true;
|
||||||
|
tmpVerb = new NoOp();
|
||||||
|
} else if(commandParameters.Length >= 2) {
|
||||||
|
string commandAfterIf = fullCommand.Substring(fullCommand.IndexOf(",") + 1); // find the first ,
|
||||||
|
IValue conditional = ValueFactory.CreateValue(rootValueStorage, commandParameters[0]); //make the conditional
|
||||||
|
IVerb AfterIf = MakeVerb(drawer, commandAfterIf); //make the following command
|
||||||
|
tmpVerb = new IfChunk(conditional, AfterIf); //Create the chunk
|
||||||
|
parsed = true;
|
||||||
} else throw new Exception(command + " has an incorrect number of parameters");
|
} else throw new Exception(command + " has an incorrect number of parameters");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case "drawto":
|
if (!parsed) {
|
||||||
case "line":
|
List<IValue> parameters = new List<IValue>();
|
||||||
case "lineto":
|
if (!(commandParameters == null)) foreach (string parameter in commandParameters) {
|
||||||
//Check parameters
|
parameters.Add(ValueFactory.CreateValue(rootValueStorage, parameter));
|
||||||
if (parameterLength == 2) {
|
}
|
||||||
tmpVerb = new DrawTo(drawer, new PointValue(parameters[0], parameters[1]));
|
int parameterLength = parameters.Count;
|
||||||
} else throw new Exception(command + " has an incorrect number of parameters");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "regularpolygon":
|
//process drawing commands and extras
|
||||||
case "rp":
|
switch (command) {
|
||||||
//Check parameters
|
//Drawing commands
|
||||||
if (parameterLength == 2) {
|
case "move":
|
||||||
tmpVerb = new RegularPolygon(drawer, parameters[0], parameters[1], new IntValue(0), new BoolValue(true));
|
case "moveto":
|
||||||
} else if (parameterLength == 3) {
|
//Check parameters
|
||||||
tmpVerb = new RegularPolygon(drawer, parameters[0], parameters[1], parameters[2], new BoolValue(true));
|
if (parameterLength == 2) {
|
||||||
} else throw new Exception(command + " has an incorrect number of parameters");
|
tmpVerb = new MoveTo(drawer, new PointValue(parameters[0], parameters[1]));
|
||||||
break;
|
} else throw new Exception(command + " has an incorrect number of parameters");
|
||||||
|
break;
|
||||||
|
|
||||||
case "square":
|
case "drawto":
|
||||||
//Check parameters
|
case "line":
|
||||||
if (parameterLength == 1) {
|
case "lineto":
|
||||||
tmpVerb = new
|
//Check parameters
|
||||||
Square(drawer, parameters[0]);
|
if (parameterLength == 2) {
|
||||||
} else if (parameterLength == 2) {
|
tmpVerb = new DrawTo(drawer, new PointValue(parameters[0], parameters[1]));
|
||||||
tmpVerb = new Square(drawer, parameters[0], parameters[1]);
|
} else throw new Exception(command + " has an incorrect number of parameters");
|
||||||
} else throw new Exception(command + " has an incorrect number of parameters");
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case "quadrilateral":
|
case "regularpolygon":
|
||||||
//Check parameters
|
case "rp":
|
||||||
if (parameterLength == 8) {
|
//Check parameters
|
||||||
tmpVerb = new Quadrilateral(drawer,
|
if (parameterLength == 2) {
|
||||||
new PointValue(parameters[0], parameters[1]),
|
tmpVerb = new RegularPolygon(drawer, parameters[0], parameters[1], new IntValue(0), new BoolValue(true));
|
||||||
new PointValue(parameters[2], parameters[3]),
|
} else if (parameterLength == 3) {
|
||||||
new PointValue(parameters[4], parameters[5]),
|
tmpVerb = new RegularPolygon(drawer, parameters[0], parameters[1], parameters[2], new BoolValue(true));
|
||||||
new PointValue(parameters[6], parameters[7])
|
} else throw new Exception(command + " has an incorrect number of parameters");
|
||||||
);
|
break;
|
||||||
} else throw new Exception(command + " has an incorrect number of parameters");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "rectangle":
|
case "square":
|
||||||
//Check parameters
|
//Check parameters
|
||||||
if (parameterLength == 2) {
|
if (parameterLength == 1) {
|
||||||
tmpVerb = new Rectangle(drawer, parameters[0], parameters[1]);
|
tmpVerb = new
|
||||||
} else if (parameterLength == 8) {
|
Square(drawer, parameters[0]);
|
||||||
return new Quadrilateral(drawer,
|
} else if (parameterLength == 2) {
|
||||||
new PointValue(parameters[0], parameters[1]),
|
tmpVerb = new Square(drawer, parameters[0], parameters[1]);
|
||||||
new PointValue(parameters[2], parameters[3]),
|
} else throw new Exception(command + " has an incorrect number of parameters");
|
||||||
new PointValue(parameters[4], parameters[5]),
|
break;
|
||||||
new PointValue(parameters[6], parameters[7])
|
|
||||||
);
|
|
||||||
} else throw new Exception(command + " has an incorrect number of parameters");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "circle":
|
case "quadrilateral":
|
||||||
//Check parameters
|
//Check parameters
|
||||||
if (parameterLength == 1) {
|
if (parameterLength == 8) {
|
||||||
tmpVerb = new Circle(drawer, parameters[0]);
|
tmpVerb = new Quadrilateral(drawer,
|
||||||
} else throw new Exception(command + " has an incorrect number of parameters");
|
new PointValue(parameters[0], parameters[1]),
|
||||||
break;
|
new PointValue(parameters[2], parameters[3]),
|
||||||
|
new PointValue(parameters[4], parameters[5]),
|
||||||
|
new PointValue(parameters[6], parameters[7])
|
||||||
|
);
|
||||||
|
} else throw new Exception(command + " has an incorrect number of parameters");
|
||||||
|
break;
|
||||||
|
|
||||||
case "triangle":
|
case "rectangle":
|
||||||
//Check parameters
|
//Check parameters
|
||||||
if (parameterLength == 1) {
|
if (parameterLength == 2) {
|
||||||
tmpVerb = new
|
tmpVerb = new Rectangle(drawer, parameters[0], parameters[1]);
|
||||||
Triangle(drawer, parameters[0]);
|
} else if (parameterLength == 8) {
|
||||||
} else if (parameterLength == 2) {
|
tmpVerb = new Quadrilateral(drawer,
|
||||||
tmpVerb = new
|
new PointValue(parameters[0], parameters[1]),
|
||||||
Triangle(drawer, parameters[0], parameters[1]);
|
new PointValue(parameters[2], parameters[3]),
|
||||||
} else if (parameterLength == 6) {
|
new PointValue(parameters[4], parameters[5]),
|
||||||
tmpVerb = new Triangle(drawer,
|
new PointValue(parameters[6], parameters[7])
|
||||||
new PointValue(parameters[0], parameters[1]),
|
);
|
||||||
new PointValue(parameters[2], parameters[3]),
|
} else throw new Exception(command + " has an incorrect number of parameters");
|
||||||
new PointValue(parameters[4], parameters[5])
|
break;
|
||||||
);
|
|
||||||
} else throw new Exception(command + " has an incorrect number of parameters");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "dot":
|
case "circle":
|
||||||
if (parameterLength == 0) {
|
//Check parameters
|
||||||
tmpVerb = new Dot(drawer);
|
if (parameterLength == 1) {
|
||||||
} else throw new Exception(command + " doesn't take parameters");
|
tmpVerb = new Circle(drawer, parameters[0]);
|
||||||
break;
|
} else throw new Exception(command + " has an incorrect number of parameters");
|
||||||
|
break;
|
||||||
|
|
||||||
case "clear":
|
case "triangle":
|
||||||
if (parameterLength == 0) {
|
//Check parameters
|
||||||
tmpVerb = new Clear(drawer);
|
if (parameterLength == 1) {
|
||||||
} else throw new Exception(command + " doesn't take parameters");
|
tmpVerb = new
|
||||||
break;
|
Triangle(drawer, parameters[0]);
|
||||||
|
} else if (parameterLength == 2) {
|
||||||
|
tmpVerb = new
|
||||||
|
Triangle(drawer, parameters[0], parameters[1]);
|
||||||
|
} else if (parameterLength == 6) {
|
||||||
|
tmpVerb = new Triangle(drawer,
|
||||||
|
new PointValue(parameters[0], parameters[1]),
|
||||||
|
new PointValue(parameters[2], parameters[3]),
|
||||||
|
new PointValue(parameters[4], parameters[5])
|
||||||
|
);
|
||||||
|
} else throw new Exception(command + " has an incorrect number of parameters");
|
||||||
|
break;
|
||||||
|
|
||||||
case "reset":
|
case "dot":
|
||||||
case "resetpen":
|
if (parameterLength == 0) {
|
||||||
if (parameterLength == 0) {
|
tmpVerb = new Dot(drawer);
|
||||||
tmpVerb = new ResetPen(drawer);
|
} else throw new Exception(command + " doesn't take parameters");
|
||||||
} else throw new Exception(command + " doesn't take parameters");
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case "fillon":
|
case "clear":
|
||||||
if (parameterLength == 0) {
|
if (parameterLength == 0) {
|
||||||
tmpVerb = new Fill(drawer, true);
|
tmpVerb = new Clear(drawer);
|
||||||
} else throw new Exception(command + " doesn't take parameters");
|
} else throw new Exception(command + " doesn't take parameters");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "filloff":
|
case "reset":
|
||||||
if (parameterLength == 0) {
|
case "resetpen":
|
||||||
tmpVerb = new Fill(drawer, false);
|
if (parameterLength == 0) {
|
||||||
} else throw new Exception(command + " doesn't take parameters");
|
tmpVerb = new ResetPen(drawer);
|
||||||
break;
|
} else throw new Exception(command + " doesn't take parameters");
|
||||||
|
break;
|
||||||
|
|
||||||
case "pen":
|
case "fillon":
|
||||||
if (parameterLength == 1) {
|
if (parameterLength == 0) {
|
||||||
tmpVerb = new PenColor(drawer, parameters[0]);
|
tmpVerb = new Fill(drawer, true);
|
||||||
} else if (parameterLength == 3) {
|
} else throw new Exception(command + " doesn't take parameters");
|
||||||
tmpVerb = new PenColor(drawer, new ColorValue(parameters[0], parameters[1], parameters[2]));
|
break;
|
||||||
} else if (parameterLength == 4) {
|
|
||||||
tmpVerb = new PenColor(drawer, new ColorValue(parameters[0], parameters[1], parameters[2], parameters[3]));
|
|
||||||
} else throw new Exception(command + " has an incorrect number of parameters");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "fill":
|
case "filloff":
|
||||||
if (parameterLength == 1) {
|
if (parameterLength == 0) {
|
||||||
tmpVerb = new FillColor(drawer, parameters[0]);
|
tmpVerb = new Fill(drawer, false);
|
||||||
} else if (parameterLength == 3) {
|
} else throw new Exception(command + " doesn't take parameters");
|
||||||
tmpVerb = new FillColor(drawer, new ColorValue(parameters[0], parameters[1], parameters[2], new IntValue(255)));
|
break;
|
||||||
} else if (parameterLength == 4) {
|
|
||||||
tmpVerb = new FillColor(drawer, new ColorValue(parameters[0], parameters[1], parameters[2], parameters[3]));
|
|
||||||
} else throw new Exception(command + " has an incorrect number of parameters");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
case "pen":
|
||||||
throw new Exception("Unknown command or cannot parse");
|
if (parameterLength == 1) {
|
||||||
|
tmpVerb = new PenColor(drawer, parameters[0]);
|
||||||
|
} else if (parameterLength == 3) {
|
||||||
|
tmpVerb = new PenColor(drawer, new ColorValue(parameters[0], parameters[1], parameters[2]));
|
||||||
|
} else if (parameterLength == 4) {
|
||||||
|
tmpVerb = new PenColor(drawer, new ColorValue(parameters[0], parameters[1], parameters[2], parameters[3]));
|
||||||
|
} else throw new Exception(command + " has an incorrect number of parameters");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "fill":
|
||||||
|
if (parameterLength == 1) {
|
||||||
|
tmpVerb = new FillColor(drawer, parameters[0]);
|
||||||
|
} else if (parameterLength == 3) {
|
||||||
|
tmpVerb = new FillColor(drawer, new ColorValue(parameters[0], parameters[1], parameters[2], new IntValue(255)));
|
||||||
|
} else if (parameterLength == 4) {
|
||||||
|
tmpVerb = new FillColor(drawer, new ColorValue(parameters[0], parameters[1], parameters[2], parameters[3]));
|
||||||
|
} else throw new Exception(command + " has an incorrect number of parameters");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Exception("Unknown command or cannot parse");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chunkDepth == 0) return tmpVerb;
|
if (chunkDepth == 0) return tmpVerb;
|
||||||
|
|||||||
Reference in new issue
Block a user