Added read Osai tool manager file

Added Siemens file list & WIP file info
This commit is contained in:
Lucio Maranta
2018-08-24 11:37:30 +00:00
parent 943dba9e02
commit a48ab8217d
10 changed files with 295 additions and 131 deletions
+8 -4
View File
@@ -132,6 +132,10 @@ namespace CMS_CORE_Application
SetError(Lines, cmsError);
}
N.TOOLS_RStoredData();
InfoFile f = new InfoFile();
N.FILES_RGetFileInfo("",ref f);
Dictionary<int, byte> statu = new Dictionary<int, byte>();
Dictionary<int, uint> lives = new Dictionary<int, uint>();
N.TOOLS_RUpdatedToolsData(ref statu, ref lives);
@@ -371,8 +375,8 @@ namespace CMS_CORE_Application
{
List<NcToolModel> obj = new List<NcToolModel>()
{
new NcToolModel() { Id = 22, FamilyId = 1, OffsetId1 = 1, OffsetId2 = 2, OffsetId3 = 3, OffsetLength = 4, ResidualLife = 5, ResidualRevive = 6, ShankId = 7 },
new NcToolModel() { Id = 22, FamilyId = 1, OffsetId1 = 1, OffsetId2 = 2, OffsetId3 = 3, OffsetLength = 4, ResidualLife = 5, ResidualRevive = 6, ShankId = 7 }
new NcToolModel() { ToolId = 22, FamilyId = 1, OffsetId1 = 1, OffsetId2 = 2, OffsetId3 = 3, OffsetLength = 4, ResidualLife = 5, ResidualRevive = 6, ShankId = 7 },
new NcToolModel() { ToolId = 22, FamilyId = 1, OffsetId1 = 1, OffsetId2 = 2, OffsetId3 = 3, OffsetLength = 4, ResidualLife = 5, ResidualRevive = 6, ShankId = 7 }
};
CmsError cms = N.TOOLS_WUpdateTools(obj);
if (cms.IsError())
@@ -402,8 +406,8 @@ namespace CMS_CORE_Application
{
List<NcToolModel> obj = new List<NcToolModel>()
{
new NcToolModel() { Id = 22, FamilyId = 1, OffsetId1 = 1, OffsetId2 = 2, OffsetId3 = 3, OffsetLength = 4, ResidualLife = 5, ResidualRevive = 6, ShankId = 7 },
new NcToolModel() { Id = 22, FamilyId = 1, OffsetId1 = 1, OffsetId2 = 2, OffsetId3 = 3, OffsetLength = 4, ResidualLife = 5, ResidualRevive = 6, ShankId = 7 }
new NcToolModel() { ToolId = 22, FamilyId = 1, OffsetId1 = 1, OffsetId2 = 2, OffsetId3 = 3, OffsetLength = 4, ResidualLife = 5, ResidualRevive = 6, ShankId = 7 },
new NcToolModel() { ToolId = 22, FamilyId = 1, OffsetId1 = 1, OffsetId2 = 2, OffsetId3 = 3, OffsetLength = 4, ResidualLife = 5, ResidualRevive = 6, ShankId = 7 }
};
N.TOOLS_WUpdateTools(obj);
}
+64 -63
View File
@@ -753,34 +753,11 @@ namespace CMS_CORE_Library
public double WearRadius { get; set; }
}
public class NcToolModel
{
public ushort Id { get; set; }
public int FamilyId { get; set; }
public int ShankId { get; set; }
public byte Status { get; set; }
public ushort OffsetLength { get; set; }
public ushort ResidualLife { get; set; }
public int OffsetId1 { get; set; }
public int OffsetId2 { get; set; }
public int OffsetId3 { get; set; }
public ushort ResidualRevive { get; set; }
}
public class NcShankModel
{
public int Id { get; set; }
public int ShankId { get; set; }
public ushort Balluf { get; set; }
public int Balluf { get; set; }
public byte MagazinePositionType { get; set; }
@@ -789,49 +766,73 @@ namespace CMS_CORE_Library
public byte PositionId { get; set; }
}
public class NcToolModel
{
public int ToolId { get; set; }
public int OffsetLength { get; set; }
public int ResidualLife { get; set; }
public int ResidualRevive { get; set; }
public byte Status { get; set; }
public int FamilyId { get; set; }
public int ShankId { get; set; }
public int OffsetId1 { get; set; }
public int OffsetId2 { get; set; }
public int OffsetId3 { get; set; }
}
public class NcFamilyModel
{
public ushort Id { get; set; }
public int FamilyId { get; set; }
public byte Type { get; set; }
public byte ToolType { get; set; }
public byte TcpTable { get; set; }
public byte Gamma { get; set; }
public byte RotationType { get; set; }
public byte CoolingByte { get; set; }
public ushort MaxSpeed { get; set; }
public byte MaxLoad { get; set; }
public byte MinLoadPctAutoload { get; set; }
public byte MaxLoadPctAutoload { get; set; }
public ushort DynamicCompensation { get; set; }
public byte MinLoadDynamicCompensation { get; set; }
public byte MaxLoadDynamicCompensation { get; set; }
public byte LifeType { get; set; }
public int NominalLife { get; set; }
public ushort ReviveDelta { get; set; }
public byte RightSize { get; set; }
public byte LeftSize { get; set; }
public byte TcpTable { get; set; }
public byte Gamma { get; set; }
public byte RotationType { get; set; }
public byte CoolingByte { get; set; }
public ushort MaxSpeed { get; set; }
public byte MaxLoad { get; set; }
public byte MinLoadPctAutoload { get; set; }
public byte MaxLoadPctAutoload { get; set; }
public byte DynamicCompensation { get; set; }
public byte MinLoadDynamicCompensation { get; set; }
public byte MaxLoadDynamicCompensation { get; set; }
public byte LifeType { get; set; }
public uint NominalLife { get; set; }
public ushort ReviveDelta { get; set; }
}
internal class NcFamilyFileModel
{
public ushort Id { get; set; }
public byte Type { get; set; }
public int Id { get; set; }
public byte ToolType { get; set; }
public byte TcpTable { get; set; }
public byte Gamma { get; set; }
public byte RotationType { get; set; }
@@ -840,19 +841,19 @@ namespace CMS_CORE_Library
public byte MaxLoad { get; set; }
public byte MinLoadPctAutoload { get; set; }
public byte MaxLoadPctAutoload { get; set; }
public byte DynamicCompensation { get; set; }
public ushort DynamicCompensation { get; set; }
public byte MinLoadDynamicCompensation { get; set; }
public byte MaxLoadDynamicCompensation { get; set; }
public byte LifeType { get; set; }
public uint NominalLife { get; set; }
public int NominalLife { get; set; }
public ushort ReviveDelta { get; set; }
public static explicit operator NcFamilyFileModel(NcFamilyModel obj)
{
return new NcFamilyFileModel()
{
Id = obj.Id,
Type = obj.Type,
Id = obj.FamilyId,
ToolType = obj.ToolType,
TcpTable = obj.TcpTable,
Gamma = obj.Gamma,
RotationType = obj.RotationType,
@@ -873,7 +874,7 @@ namespace CMS_CORE_Library
internal class NcFamilySizeFileModel
{
public ushort Id { get; set; }
public int Id { get; set; }
public byte RightSize { get; set; }
public byte LeftSize { get; set; }
@@ -881,7 +882,7 @@ namespace CMS_CORE_Library
{
return new NcFamilySizeFileModel()
{
Id = obj.Id,
Id = obj.FamilyId,
RightSize = obj.RightSize,
LeftSize = obj.LeftSize
};
+49 -22
View File
@@ -1158,8 +1158,10 @@ namespace CMS_CORE.Demo
// Write case: write bit
else
{
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel();
binaryMemoryModel.boolean = Value;
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel
{
boolean = Value
};
serverService.PutBoolean(MemIndex.ToString(), MemBit.ToString(), binaryMemoryModel);
}
}
@@ -1187,8 +1189,10 @@ namespace CMS_CORE.Demo
}
else // Write case
{
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel();
binaryMemoryModel.binary = Value;
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel
{
binary = Value
};
serverService.PutByte(MemIndex.ToString(), binaryMemoryModel);
}
}
@@ -1216,8 +1220,10 @@ namespace CMS_CORE.Demo
}
else // Write case
{
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel();
binaryMemoryModel.uWord = Value;
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel
{
uWord = Value
};
serverService.PutWord(MemIndex.ToString(), binaryMemoryModel);
}
}
@@ -1245,8 +1251,10 @@ namespace CMS_CORE.Demo
}
else // Write case
{
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel();
binaryMemoryModel.word = Value;
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel
{
word = Value
};
serverService.PutShort(MemIndex.ToString(), binaryMemoryModel);
}
}
@@ -1274,8 +1282,10 @@ namespace CMS_CORE.Demo
}
else // Write case
{
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel();
binaryMemoryModel.dWord = Value;
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel
{
dWord = Value
};
serverService.PutDWord(MemIndex.ToString(), binaryMemoryModel);
}
}
@@ -1303,8 +1313,10 @@ namespace CMS_CORE.Demo
}
else // Write case
{
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel();
binaryMemoryModel.integer = Value;
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel
{
integer = Value
};
serverService.PutInteger(MemIndex.ToString(), binaryMemoryModel);
}
}
@@ -1396,8 +1408,10 @@ namespace CMS_CORE.Demo
}
else // Write case
{
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel();
binaryMemoryModel.byteList = Value;
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel
{
byteList = Value
};
serverService.PutByteList(MemIndex.ToString(), binaryMemoryModel);
}
}
@@ -1425,8 +1439,10 @@ namespace CMS_CORE.Demo
}
else // Write case
{
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel();
binaryMemoryModel.wordList = Value;
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel
{
wordList = Value
};
serverService.PutWordList(MemIndex.ToString(), binaryMemoryModel);
}
}
@@ -1454,8 +1470,10 @@ namespace CMS_CORE.Demo
}
else // Write case
{
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel();
binaryMemoryModel.shortList = Value;
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel
{
shortList = Value
};
serverService.PutShortList(MemIndex.ToString(), binaryMemoryModel);
}
}
@@ -1483,8 +1501,10 @@ namespace CMS_CORE.Demo
}
else // Write case
{
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel();
binaryMemoryModel.integerList = Value;
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel
{
integerList = Value
};
serverService.PutIntegerList(MemIndex.ToString(), binaryMemoryModel);
}
}
@@ -1512,8 +1532,10 @@ namespace CMS_CORE.Demo
}
else // Write case
{
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel();
binaryMemoryModel.dWordList = Value;
BinaryMemoryModel binaryMemoryModel = new BinaryMemoryModel
{
dWordList = Value
};
serverService.PutDWordList(MemIndex.ToString(), binaryMemoryModel);
}
}
@@ -2569,6 +2591,11 @@ namespace CMS_CORE.Demo
}
}
public override CmsError TOOLS_RStoredData()
{
return NO_ERROR;
}
#endregion ToolTable
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+5
View File
@@ -1890,6 +1890,11 @@ namespace CMS_CORE.Fanuc
return NO_ERROR;
}
public override CmsError TOOLS_RStoredData()
{
return NO_ERROR;
}
#endregion Nc Tool Manager
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+3 -1
View File
@@ -1679,10 +1679,12 @@ namespace CMS_CORE
public abstract CmsError TOOLS_RUpdatedToolsData(ref Dictionary<int, byte> updatedStatus, ref Dictionary<int, uint> updatedLives);
public abstract CmsError TOOLS_RStoredData();
#endregion Nc Tool Manager
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#region CONSTANTS (Struct and Enum are Static for definition)
// Read Write type
+88 -38
View File
@@ -2930,6 +2930,91 @@ namespace CMS_CORE.Osai
return NO_ERROR;
}
public override CmsError TOOLS_RStoredData()
{
CmsError cmsError = CreateBackup();
if (cmsError.IsError())
return cmsError;
string backupFilePath = TOOL_MANAGER_BACKUP_DIRECTORY_PATH + "{0}.csv";
List<NcFamilyFileModel> families = File.ReadAllLines(string.Format(backupFilePath, FAMILIES_FILE_NAME)) // Read file
.Where(x => x != String.Empty)
.Select(x => x.Split(';')) // Split line
.Select(x => new NcFamilyFileModel // Setup new model for each line
{
Id = int.Parse(x[0]),
ToolType = byte.Parse(x[1]),
TcpTable = byte.Parse(x[2]),
Gamma = byte.Parse(x[3]),
RotationType = byte.Parse(x[4]),
CoolingByte = byte.Parse(x[5]),
MaxSpeed = ushort.Parse(x[6]),
MaxLoad = byte.Parse(x[7]),
MinLoadPctAutoload = byte.Parse(x[8]),
MaxLoadPctAutoload = byte.Parse(x[9]),
DynamicCompensation = ushort.Parse(x[10]),
MinLoadDynamicCompensation = byte.Parse(x[11]),
MaxLoadDynamicCompensation = byte.Parse(x[12]),
LifeType = byte.Parse(x[13]),
NominalLife = byte.Parse(x[14]),
ReviveDelta = ushort.Parse(x[15])
}).ToList();
List<NcFamilySizeFileModel> familiesSize = File.ReadAllLines(string.Format(backupFilePath, FAM_SIZE_FILE_NAME)) // Read file
.Where(x => x != String.Empty)
.Select(x => x.Split(';')) // Split line
.Select(x => new NcFamilySizeFileModel // Setup new model for each line
{
Id = ushort.Parse(x[0]),
RightSize = byte.Parse(x[1]),
LeftSize = byte.Parse(x[2]),
}).ToList();
List<NcToolModel> tools = File.ReadAllLines(string.Format(backupFilePath, TOOLS_FILE_NAME))
.Where(x => x != String.Empty)
.Select(x => x.Split(';'))
.Select(x => new NcToolModel
{
ToolId = int.Parse(x[0]),
FamilyId = int.Parse(x[1]),
ShankId = int.Parse(x[2]),
Status = byte.Parse(x[3]),
OffsetLength = ushort.Parse(x[4]),
ResidualLife = byte.Parse(x[5]),
OffsetId1 = ushort.Parse(x[6]),
OffsetId2 = byte.Parse(x[7]),
OffsetId3 = byte.Parse(x[8]),
ResidualRevive = byte.Parse(x[9])
}).ToList();
List<NcShankModel> shanks = File.ReadAllLines(string.Format(backupFilePath, SHANKS_FILE_NAME))
.Where(x => x != String.Empty)
.Select(x => x.Split(';'))
.Select(x => new NcShankModel
{
ShankId = int.Parse(x[0]),
Balluf = int.Parse(x[1]),
MagazineId = byte.Parse(x[2]),
PositionId = byte.Parse(x[3]),
MagazinePositionType = byte.Parse(x[4])
}).ToList();
List<NcMagazinePositionModel> positions = File.ReadAllLines(string.Format(backupFilePath, MAG_POSITION_FILE_NAME))
.Where(x => x != String.Empty)
.Select(x => x.Split(';'))
.Select(x => new NcMagazinePositionModel
{
MagazineId = byte.Parse(x[0]),
PositionId = byte.Parse(x[1]),
Type = byte.Parse(x[2]),
Disabled = byte.Parse(x[3]) > 0 ? (byte)1 : (byte)0
}).ToList();
return NO_ERROR;
}
private CmsError UpdateToolManagerFile<T>(string filePath, List<T> objs) where T : class
{
//Check if the NC is Connected
@@ -2940,7 +3025,7 @@ namespace CMS_CORE.Osai
List<string> lines = new List<string>();
// Convert data in a csv string
string csvContent = GenerateModelCsv(objs);
string csvContent = GenerateCsvStringFromModel(objs);
lines.Add(csvContent);
// Write into local file
@@ -2958,7 +3043,7 @@ namespace CMS_CORE.Osai
return NO_ERROR;
}
public string GenerateModelCsv<T>(List<T> items) where T : class
public string GenerateCsvStringFromModel<T>(List<T> items) where T : class
{
var output = "";
var delimiter = ';';
@@ -2982,6 +3067,7 @@ namespace CMS_CORE.Osai
private CmsError CreateBackup()
{
// Generic path without file name
string filePath = TOOL_MANAGER_DIRECTORY_PATH + "{0}.csv";
string backupFilePath = TOOL_MANAGER_BACKUP_DIRECTORY_PATH + "{0}.csv";
@@ -3014,24 +3100,6 @@ namespace CMS_CORE.Osai
return cmsError;
File.WriteAllText(string.Format(backupFilePath, TOOLS_FILE_NAME), fileContent);
//CmsError cmsError = FILES_CopyProgram(string.Format(filePath, FAMILIES_FILE_NAME), string.Format(backupFilePath, FAMILIES_FILE_NAME), false);
//if (cmsError.IsError())
// return cmsError;
//cmsError = FILES_CopyProgram(string.Format(filePath, FAM_SIZE_FILE_NAME), string.Format(backupFilePath, FAM_SIZE_FILE_NAME), false);
//if (cmsError.IsError())
// return cmsError;
//cmsError = FILES_CopyProgram(string.Format(filePath, MAG_POSITION_FILE_NAME), string.Format(backupFilePath, MAG_POSITION_FILE_NAME), false);
//if (cmsError.IsError())
// return cmsError;
//cmsError = FILES_CopyProgram(string.Format(filePath, SHANKS_FILE_NAME), string.Format(backupFilePath, SHANKS_FILE_NAME), false);
//if (cmsError.IsError())
// return cmsError;
//return FILES_CopyProgram(string.Format(filePath, TOOLS_FILE_NAME), string.Format(backupFilePath, TOOLS_FILE_NAME), false);
return cmsError;
}
@@ -3055,24 +3123,6 @@ namespace CMS_CORE.Osai
File.Delete(string.Format(backupFilePath, TOOLS_FILE_NAME));
return NO_ERROR;
//// Delete tool manager backup file
//CmsError cmsError = FILES_DeleteProgram(TOOL_MANAGER_DIRECTORY_PATH, string.Format(backupFilePath, FAMILIES_FILE_NAME));
//if (cmsError.IsError())
// return cmsError;
//cmsError = FILES_DeleteProgram(TOOL_MANAGER_DIRECTORY_PATH, string.Format(backupFilePath, FAM_SIZE_FILE_NAME));
//if (cmsError.IsError())
// return cmsError;
//cmsError = FILES_DeleteProgram(TOOL_MANAGER_DIRECTORY_PATH, string.Format(backupFilePath, MAG_POSITION_FILE_NAME));
//if (cmsError.IsError())
// return cmsError;
//cmsError = FILES_DeleteProgram(TOOL_MANAGER_DIRECTORY_PATH, string.Format(backupFilePath, SHANKS_FILE_NAME));
//if (cmsError.IsError())
// return cmsError;
//return FILES_DeleteProgram(TOOL_MANAGER_DIRECTORY_PATH, string.Format(backupFilePath, TOOLS_FILE_NAME));
}
#endregion Nc Tool Manager
+59 -1
View File
@@ -110,6 +110,8 @@ namespace CMS_CORE.Siemens
public static uint multitoolsNumber = 0;
public const string BASE_FILE_PATH = "//NC/";
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#region Contructor & global methods
@@ -1845,10 +1847,62 @@ namespace CMS_CORE.Siemens
#region File Management
public override CmsError FILES_RGetFileList(string path, ref List<PreviewFileModel> files)
{
try
{
FileSvc fileSvc = new FileSvc();
// Preapare folder node
Node folderNode = new Node(BASE_FILE_PATH + path);
// Read files in the folder
Node[] nodeArray = fileSvc.List(folderNode);
// Go through the array of file nodes
foreach (Node element in nodeArray)
{
files.Add(new PreviewFileModel()
{
AbsolutePath = path,
IsDirectory = element.IsDirNode,
Name = element.LogicalPath
});
}
}
catch (Exception ex)
{
return ManageException(ex);
}
return NO_ERROR;
}
public override CmsError FILES_RGetFileInfo(string path, ref InfoFile fileInfo)
{
try
{
FileSvc fileSvc = new FileSvc();
//var splittedPath = path.Split('/');
//path = String.Join(@"/", splittedPath.Take(splittedPath.Count() - 1));
// Preapare folder node
Node folderNode = new Node(BASE_FILE_PATH + path);
// Read files in the folder
Node[] nodeArray = fileSvc.List(folderNode);
fileInfo = nodeArray.Where(x => x.Name == "MPF0").Select(x =>
new InfoFile()
{
CreationDate = nodeArray[0].Attributes.LastAccess,
LastModDate = nodeArray[0].Attributes.LastAccess,
Name = nodeArray[0].Name,
Content = new List<string>() { nodeArray[0].LogicalPath },
PreviewBase64 = nodeArray[0].RealPath
}).FirstOrDefault();
}
catch (Exception ex)
{
return ManageException(ex);
}
return NO_ERROR;
}
@@ -3049,9 +3103,13 @@ namespace CMS_CORE.Siemens
public override CmsError TOOLS_RUpdatedToolsData(ref Dictionary<int, byte> updatedStatus, ref Dictionary<int, uint> updatedLives)
{
return NO_ERROR;
return FUNCTION_NOT_ALLOWED_ERROR;
}
public override CmsError TOOLS_RStoredData()
{
return FUNCTION_NOT_ALLOWED_ERROR;
}
#endregion Nc Tool Manager
+2 -2
View File
@@ -264,8 +264,8 @@ namespace CMS_CORE_Library
new FieldsConfiguration{Name = "id", Type = "int", SelectValues = null, Category = "general", ReadOnly = true, MinValue = 0, MaxValue = 0 },
new FieldsConfiguration{Name = "lenght", Type = "double", SelectValues = null, Category = "general", ReadOnly = false, MinValue = 0, MaxValue = uint.MaxValue },
new FieldsConfiguration{Name = "radius", Type = "double", SelectValues = null, Category = "general", ReadOnly = false, MinValue = 0, MaxValue = uint.MaxValue },
new FieldsConfiguration{Name = "wear_length", Type = "double", SelectValues = null, Category = "general", ReadOnly = false, MinValue = 0, MaxValue = uint.MaxValue },
new FieldsConfiguration{Name = "wear_radius", Type = "double", SelectValues = null, Category = "general", ReadOnly = false, MinValue = 0, MaxValue = uint.MaxValue }
new FieldsConfiguration{Name = "wearLength", Type = "double", SelectValues = null, Category = "general", ReadOnly = false, MinValue = 0, MaxValue = uint.MaxValue },
new FieldsConfiguration{Name = "wearRadius", Type = "double", SelectValues = null, Category = "general", ReadOnly = false, MinValue = 0, MaxValue = uint.MaxValue }
},
EdgesAdditionalParamsConfiguration = new Dictionary<int, List<string>>() // Set value runtime, based on NC vendor
};
@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Nc_Demo_Application.Database.Models
{
public class OffsetModel
{
public short Id { get; set; }
public double Length { get; set; }
public double Radius { get; set; }
public double WearLength { get; set; }
public double WearRadius { get; set; }
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB