Getting path of ArrayList<image> that is already set and convert to string - image

My program creates a "Deck" of cards in a List, I want to be able to get the image, find the path to parse it to get the information that is in the image name.
For this, I am using an ArrayList to store the cards.
List<Image> mainDeck = new ArrayList<Image>();
To load the image, I am using this code
public List load(List<Image> newDeck) {
count = 0;
for (int i = 0; i < 4; i++) {
for (int k = 0; k < 10; k++) {
newDeck.add(new Image("images/" + prefix.get(i) + "" + (k + 1) + ".png"));
count++;
}// end number card for loop
for (int l = 0; l < 3; l++) {
newDeck.add(new Image("images/" + prefix.get(l) + "" + prefixFace.get(l) + ".png"));
count++;
}// end face card for loop
}// end deck for loop
it then gets called and populated with images that work perfectly, I would like to create a matching array filled with Strings that hold the path for the matching Image array.
The names of images are "c1.png", "c2.png", etc, and I just need the number in the pathname
Once I get the array I should be able to parse the data to get the numbers.
Any help would be much appreciated.
when using get url, I am getting an error, here is that code
for (Image card : mainDeck){
String path = card.getUrl();
String name = path.substring(path.lastIndexOf("/")+1, path.lastIndexOf("."));
nameData.put(card, name);
it is not recognizing card.getUrl();

you don't have to create another arrayList for the paths cause the path data is already saved with the images.
if you want to retrieve the path of an image after creating it then you might use the method getUrl() in the Image class, calling getUrl() from an Image object will return the path that you used to create the image when you called the constructor, note that it will only work if you called the Image constructor using a String as the path for the image, it will not work if you used an inputStream to initialize your image, and also that it was defined in java 9, after getting the path you might split it to get the useful data you want, something like
Image image = new Image("file:/C:/Users/zinou/Desktop/edit.png");
String path = image.getUrl();
String name = path.substring(path.lastIndexOf("/") + 1, path.lastIndexOf("."));
System.out.println(name);
and if i were to associate every card with its path, i would use a hashMap as in
List<Image> mainDeck = new ArrayList<Image>();
//population of the list
HashMap<Image, String> nameData = new HashMap<Image, String>();
for (Image card : mainDeck) {
String path = card.getUrl();
String name = path.substring(path.lastIndexOf("/") + 1, path.lastIndexOf("."));
nameData.put(card, name);
}
If you have java 8
you can create a class that extends the Image class and give it an additional attribute (the URL), and add a getter for the URL so you can access it, but then your cards will be instances of the new class you created, so you can get the URL for them, the new class may look like this
public class MyImage extends javafx.scene.image.Image{
String url;
public MyImage(String arg0) {
super(arg0);
url = arg0;
}
public String geturl() {
return url;
}
}

Related

File data not being read processing

I am absolutely stuck, my file data is not being read in processing using loadStrings();. I have tried everything. Here is my code:
Main Class
Student[] studentList;
String[] fileData;
void loadFileData(){
fileData = loadStrings("StudentData.txt");
}
void setup(){
loadFileData();
studentList = new Student[fileData.length/3];
for(int i = 0; i < fileData.length/3; i++){
studentList[i].studentName = fileData[i];
studentList[i].studentAddress = fileData[i+1];
studentList[i].studentNumber = parseInt(fileData[i+3]);
}
printArray(fileData);
}
Student Class
class Student{
String studentName;
String studentAddress;
int studentNumber;
Student(String name, String address, int number){
studentName = name;
studentAddress = address;
studentNumber = number;
}
}
My file directory is exactly as follows:
>Processing
>data
>StudentData.txt
>student
>studentSearch
All of the data is formatted in lines, name, address, number, repeat
Thank you!
I copied your code and ran it here in Processing.
I get a NullPointerException on this line:
studentList[i].studentName = fileData[i];
But it's not being caused by the fileData array. You can see this if you print the array immediately after it's loaded. The data is there:
fileData = loadStrings("StudentData.txt");
printArray(fileData);
You get an error because you're trying to access a Student object that doesn't exist. You create an array to hold the objects, but you don't actually put any objects in it before trying to access them in your loop. So studentList[i] is null.
You can pass the data directly to your Student constructor when you create the object:
studentList[i] = new Student(fileData[i], fileData[i+1], parseInt(fileData[i+3]));

LINQ way to change my inefficient program

Please consider the following records
I'm trying to flatten and group the data by Robot Name then by date + Left Factory time then group the address(es) for that date and time. Notice that some of the Left Factory times are identical.
I wrote the code below and it works. It gives me the output that I want. I was a Perl developer so what you see below is from that mentality. I'm sure there is a better way of doing it in LINQ. A little help please.
static void Main(string[] args)
{
if (args.Length < 0){
Console.WriteLine("Input file name is required");
return;
}
List<string> rawlst = File.ReadAllLines(args[0]).ToList<string>();
Dictionary<string, Dictionary<DateTime, List<string>>> dicDriver = new Dictionary<string, Dictionary<DateTime, List<string>>>();
foreach (string ln in rawlst)
{
try
{
List<string> parts = new List<string>();
parts = ln.Split(',').ToList<string>();
string[] dtparts = parts[1].Split('/');
string[] dttime = parts[15].Split(':');
DateTime dtrow = new DateTime(
int.Parse(dtparts[2]), int.Parse(dtparts[0]), int.Parse(dtparts[1]),
int.Parse(dttime[0]), int.Parse(dttime[1]), int.Parse(dttime[2]));
string rowAddress = parts[7] + " " + parts[9] + " " + parts[10] + " " + parts[11];
if (!dicDriver.Keys.Contains(parts[3]))
{
Dictionary<DateTime, List<string>> thisRec = new Dictionary<DateTime, List<string>>();
thisRec.Add(dtrow, new List<string>() { rowAddress });
dicDriver.Add(parts[3], thisRec);
}
else
{
Dictionary<DateTime, List<string>> thisDriver = new Dictionary<DateTime, List<string>>();
thisDriver = dicDriver[parts[3]];
if (!thisDriver.Keys.Contains(dtrow))
{
dicDriver[parts[3]].Add(dtrow, new List<string>() { rowAddress });
}
else
{
dicDriver[parts[3]][dtrow].Add(rowAddress);
}
}
}
catch (Exception e)
{
Console.WriteLine("ERROR:" + ln);
}
}
//output
string filename = DateTime.Now.Ticks.ToString() + ".out";
foreach (var name in dicDriver.Keys)
{
foreach (var dd in dicDriver[name])
{
Console.Write(name + "," + dd.Key + ",");
File.AppendAllText(filename, name + "," + dd.Key + Environment.NewLine);
foreach (var addr in dd.Value)
{
Console.Write("\t\t" + addr + Environment.NewLine);
File.AppendAllText(filename, "\t" + addr + Environment.NewLine);
}
}
Console.Write(Environment.NewLine);
File.AppendAllText(filename, Environment.NewLine);
}
Console.ReadLine();
}
You should separate your concerns: separate your input from the processing and from the output.
For example: suppose you would have to read your input from a database instead from a CSV file? Would that seriously change the way your process your fetched data? In your design, fetching the data is mixed with processing: although you know that the data that you want to process contains something like FactoryProcesses, you decide to present eache FactoryProcess as a string. A FactoryProcess is not a string. It describes how and when and who processed something in your factory. That is not a string, is it? However, it might be represented internally as a string, but the outside world should not know this. This way, if you change your FactoryProcess from being read by a CSV-file, to something provided by a database, the users of your FactoryProcess won't see any difference.
Separation of concerns makes your code easier to understand, easier to test, easier to change, and better to re-use.
So let's separate!
IEnumerable<FactoryProcess> ReadFactoryProcesses(string fileName)
{
// TODO: check fileName not null, file exists
using (var fileReader = new StreamReader(fileName))
{
// read the file Line by Line and split each line into one FactoryProcess object
string line = fileReader.ReadLine();
while (line != null)
{
// one line read, convert to FactoryProcess and yield return:
FactoryProcess factoryProcess = this.ToFactoryProcess(line);
yield return factoryProcess;
// read next line:
line = fileReader.ReadLine();
}
}
}
I'll leave the conversion of a read line into a FactoryProcess up to you. Tip: if the items in your lines are separated by a comma, or something similar, consider using Nuget Package CSVHelper. It makes if easier to convert a file into a sequence of FactoryProcesses.
I want to group the data by Robot Name then by date + Left Factory time then group the address(es) for that date and time.
First of all: make sure that the FactoryProcess class has the properties you actually need. Separate this representation from what it is in a file. Apparently you want to tread date + left factory as one item that represents the Date and Time that it left the factory. So Let's create a DateTime property for this.
class FactoryProcess
{
public int Id {get; set}
public int PartNo {get; set;}
public string RobotName {get; set;} // or if desired: use a unique RobotId
...
// DateTimes: ArrivalTime, OutOfFactoryTime, LeftFactoryTime
public DateTime ArrivalTime {get; set;}
public DateTime OutOfFactoryTime {get; set;}
public DateTime LeftFactoryTime {get; set;}
}
The reason that I put Date and Time into one DateTime, is because it will solve problems if an item arrives on 23:55 and leaves on 00:05 next day.
A procedure that converts a read CSV-line to a FactoryProcess should interpret your dates and times as strings and convert to FactoryProcess. You can create a constrcuctor for this, or a special Factory class
public FactoryProcess InterpretReadLine(string line)
{
// TODO: separate the parts, such that you've got the strings dateTxt, arrivalTimeTxt, ...
DateTime date = DateTime.Parse(dateTxt);
TimeSpan arrivalTime = TimeSpan.Parse(arrivalTimeTxt);
TimeSpan outOfFactoryTime = TimeSpan.Parse(outOfFactoryTimeTxt);
TimeSpan leftFactoryTime = TimeSpan.Parse(leftFactoryTimeTxt);
return new FactoryProces
{
Id = ...
PartNo = ..
RobotName = ...
// The DateTimes:
ArrivalTime = date + arrivalTime,
OutOfFactoryTime = date + outOfFactoryTime,
LeftFactoryTime = date + leftFactoryTime,
};
}
Now that you've created a proper method to convert your CSV-file into a sequence of FactoryProcesses, let's process them
I want to group the data by Robot Name then by date + Left Factory time then group the address(es) for that date and time.
var result = fetchedFactoryProcesses.GroupBy(
// parameter KeySelector: make groups of FactoryProcesses with same RobotName:
factoryProcess => factoryProcess.RobotName,
// parameter ResultSelector: from every group of FactoryProcesses with this RobotName
// make one new Object:
(robotName, processesWithThisRobotName) => new
{
RobotName = robotName,
// Group all processes with this RobotName into groups with same LeftFactoryTime:
LeftFactory = processesWithThisRobotName.GroupBy(
// KeySelector: make groups with same LeftFactoryTime
process => process.LeftFactoryTime,
// ResultSelector: from each group of factory processes with the same LeftFactoryTime
(leftFactoryTime, processesWithThisLeftFactoryTime) => new
{
LeftFactoryTime = leftFactoryTime,
FactoryProcesses = processesWithThisLeftFactoryTime,
// or even better: select only the properties you actually plan to use
FactoryProcesses = processesWithThisLeftFactoryTime.Select(process => new
{
Id = process.Id,
PartNo = process.PartNo,
...
// not needed: you know the value, because it is in this group
// RobotName = process.RobotName,
// LeftFactoryTime = process.LeftFactoryTime,
}),
})
});
For completeness: grouping your code together:
void ProcessData(string fileName)
{
var fetchedFactoryProcesses = ReadFactoryProcess(fileName); // fetch the data
var groups = fetchFactoryProcesses.ToGroups(); // put into groups
this.Display(groups); // output result;
}
Because I separated the input from the conversion of strings to FactoryProcesses, and separated this conversion from the grouping, it will be easy to test the classes separately:
your CSV-reader should return any file that is divided into lines, even if it does not contain FactoryProcesses
your conversion from read line to FactoryProcess should convert any string that is in the proper format, whether it is read from a file or gathered any other way
your grouping should group any sequence of FactoryProcesses, whether they come from a CSV-file or from a database or List<FactoryProcess>, which is very convenient, because in your tests it is way easier to create a test list, than a test CSV-file.
If in future you decide to change the source of your sequence of FactoryProcesses, for instance it comes from a database instead of a CSV-file, your grouping won't change. Or if you decide to support entering and leaving factories on different dates (multiple date values) only the conversion changes. If you decide to display the results in a tree-like fashion, or decide to write the groups in a database, your reading, conversion, grouping, etc won't change: what a high degree or re-usability!
Separating your concerns made it much easier to understand how to solve your grouping problem, without the hassle of splitting your read lines and converting Date + LeftFactory into one value.

get workflow malfunction exception with java api

Does anyone know how to get a workflow malfunction error message using the java pe api? I am running the QueueSample java code provided by IBM and it is not clear to me how to do this. Any help would be appreciated!
I found the malfunction error message for my workflow in the VWParticipantHistory.getLogFields() array. I modified the example code from the Developing Applications with IBM FileNet P8 APIs redbook:
// Create session object and log onto Process Engine
...
// Get the specific work item
...
// Get VWProcess object from work object
VWProcess process = stepElement.fetchProcess();
// Get workflow definitions from the VWProcess
VWWorkflowDefinition workflowDefinition =
process.fetchWorkflowDefinition(false);
// Get maps for each workflow definition
VWMapDefinition[] workflowMaps = workflowDefinition.getMaps();
// Iterate through each map in the workflow Definition
for (int i = 0; i < workflowMaps.length; i++) {
// Get map ID and map name for each map definition
int mapID = workflowMaps[i].getMapId();
String mapName = workflowMaps[i].getName();
// Get workflow history information for each map
VWWorkflowHistory workflowHistory = process.fetchWorkflowHistory(mapID);
String workflowOriginator = workflowHistory.getOriginator();
// Iterate through each item in the Workflow History
while (workflowHistory.hasNext()) {
// Get step history objects for each workflow history
VWStepHistory stepHistory = workflowHistory.next();
String stepName = stepHistory.getStepName();
System.out.println("step history name = " + stepName);
// Iterate through each item in the Step History
while (stepHistory.hasNext()) {
// Get step occurrence history
// objects for each step history object
VWStepOccurrenceHistory stepOccurenceHistory = stepHistory.next();
Date stepOcurrenceDateReceived = stepOccurenceHistory.getDateReceived();
Date stepOcurrenceDateCompleted = stepOccurenceHistory.getCompletionDate();
while (stepOccurenceHistory.hasNext()) {
// Get step work object information
// for each step occurrence
VWStepWorkObjectHistory stepWorkObjectHistory = stepOccurenceHistory.next();
stepWorkObjectHistory.resetFetch();
// Get participant information for each work object
while (stepWorkObjectHistory.hasNext()) {
VWParticipantHistory participantHistory = stepWorkObjectHistory.next();
String opName = participantHistory.getOperationName();
System.out.println("operation name = " + opName);
Date participantDateReceived = participantHistory.getDateReceived();
String participantComments = participantHistory.getComments();
String participantUser = participantHistory.getUserName();
String participantName = participantHistory.getParticipantName();
VWDataField[] logFields = participantHistory.getLogFields();
System.out.println("** start get log fields **");
for (int index=0; index<logFields.length; index++){
VWDataField dataField = logFields[index];
String name = dataField.getName();
String val = dataField.getStringValue();
System.out.println("name = " + name + " , value = " + val);
}
System.out.println("** end get log fields **");
} // while stepWorkObjectHistory
} // while stepOccurenceHistory
} // while stepHistory
} // while workflowHistory
} // for workflow maps

Resize uploaded image in MVC 6

What is the best way to resize an uploaded image in MVC 6? I'd like to store multiple variants of an image (such as small, large, etc.) to be able to choose which to display later.
Here's my code for the action.
[HttpPost]
public async Task<IActionResult> UploadPhoto()
{
if (Request.Form.Files.Count != 1)
return new HttpStatusCodeResult((int)HttpStatusCode.BadRequest);
IFormFile file = Request.Form.Files[0];
// calculate hash
var sha = System.Security.Cryptography.SHA256.Create();
byte[] hash = sha.ComputeHash(file.OpenReadStream());
// calculate name and patch where to store the file
string extention = ExtentionFromContentType(file.ContentType);
if (String.IsNullOrEmpty(extention))
return HttpBadRequest("File type not supported");
string name = WebEncoders.Base64UrlEncode(hash) + extention;
string path = "uploads/photo/" + name;
// save the file
await file.SaveAsAsync(this.HostingEnvironment.MapPath(path));
}
I would suggest using Image Processor library.
http://imageprocessor.org/imageprocessor/
Then you can just do something along the lines of:
using (var imageFactory = new ImageFactory())
using (var fileStream = new FileStream(path))
{
file.Value.Seek(0, SeekOrigin.Begin);
imageFactory.FixGamma = false;
imageFactory.Load(file.Value)
.Resize(new ResizeLayer(new Size(264, 176)))
.Format(new JpegFormat
{
Quality = 100
})
.Quality(100)
.Save(fileStream);
}
Where file.Value is your file that was uploaded (the stream) (I don't know what it is in MVC, this is code I use in a Nancy project)

Adding dynamic values in an input box using watin for a web based application

I am working on a web based application which takes care of online orders placed by customers .
we are using watin for sanity.This is what my code reads
mybrowser.TextField(Find.ByName("searchBox")).Value = "milk";
mybrowser.Image(Find.ByName("search")).Click();
In the input field i want to add any string value(e.g meat/bakery) of X length
Please help
As I read your question you want to be able to generate and input a string of a specific, given length X. Here is some code I wrote a while ago for that.
public static string GetRandomString(int length)
{
StringBuilder randomString = new StringBuilder();
Random randomNumber = new Random();
for (int i = 0; i < length; i++)
{
randomString.Append(Convert.ToChar(Convert.ToInt32(Math.Floor(26 * randomNumber.NextDouble() + 65))));
}
return randomString.ToString();
}
If you want to pick from a specific list of items I would use code like this
public static string GenerateRandomFood()
{
string[] foods = {"Bread", "Cheese", "Milk", };
// There are 3 food names
return foods[GetRandomInt(0, 2)];
}
Hope that is what you are after.

Resources