Run length calculation

LasseThid
Advanced member
Posts: 353
Joined: Tue Mar 03, 2015 2:30 pm
Location: Molndal, Sweden

Run length calculation

Post by LasseThid »

I'm working on a flow where I get an XML file for each PDF containing amongst other things number of ordered copies, height and width of the product.
From this information I need to calculate how many sheets we need to print in order to print the ordered number of copies.
As I know the sheet size I can calculate how many copies will fit along the width and height of the sheet. I then need to divide the number of ordered copies by this number to get the run length. Atleast that's the theory of it, but how on earth do I convert it into practise?
If I try to do the math as a variable the number of characters needed to define it is huge... :D
Doing the math in Javascript would be easier, but how do I read the XML file, which will have a different name for every job that is processed, into the Javascript so I can define variables for the calculations and how do I return the run length to the XML file? :?
Enfocus Switch, Enfocus PitStop Server, Enfocus PDF Review, HP SmartStream& Kodak Prinergy with RBA
Offset 72x102, Offset Large Format, Digital Large Format and Digital print.
bens
Advanced member
Posts: 252
Joined: Thu Mar 03, 2011 10:13 am

Re: Run length calculation

Post by bens »

You can read/write xml through the xml module of the scripting API. This can be somewhat cumbersome to write though.

For example (untested):

Code: Select all

var thePathToXml = "/some/path/" + job.getNameProper() + ".xml";
var theDocument = new Document( thePathToXml ); // create an xml Document
var theWidth = theDocument.evalToNumber( "/xslt/to/width" ); // read the width
// ... read other required variables
// var theRunLength = ...; // do the calculation
var theParentXmlElement = theDocument.evalToNode( "/xslt/to/parent/element" ); // where in the xml do we want to add the new info?
var theNewElement = theDocument.createElement( "runLength" ); // create a Node to hold the new info
var theText = theDocument.createText( theRunLength ); // create a text node containing the actual value; could also be an attribute
theNewElement.appendChild( theText ); // add the text to the new element
theParentXmlElement.appendChild( theNewElement ); // add the new element to the parent
theDocument.save( thePathToXml); // save the modified document
Alternatively, you could first use an xml pickup to get the xml into a dataset. This might make it a bit easier to find the xml, but editing it would be comparable.
LasseThid
Advanced member
Posts: 353
Joined: Tue Mar 03, 2015 2:30 pm
Location: Molndal, Sweden

Re: Run length calculation

Post by LasseThid »

I am using the xml pickup to embed the xml as metadata (Metadata alongside asset) in order to use the metadata to pick up the correct imposition for the job, but I don't know how to access that metadata with a Javascript or if it would be easier to get the information from the xml file.

Currently the flow looks like this:
Image

Somehow I need to let HP Digital Front End JDF Control know the number of copies to print, so I either need to have a branch from the Dismantled job to a Javascript to calculate the Run length and then write it back to the xml, put another XML Pickup after Imposed PDF and then just use the Run length variable or find a way to use the metadata to do the same thing.
Enfocus Switch, Enfocus PitStop Server, Enfocus PDF Review, HP SmartStream& Kodak Prinergy with RBA
Offset 72x102, Offset Large Format, Digital Large Format and Digital print.
bens
Advanced member
Posts: 252
Joined: Thu Mar 03, 2011 10:13 am

Re: Run length calculation

Post by bens »

I suggest adding a script element after the XML pickup. Reading the values remains largely the same, except you would use the dataset instead of a Document. If you need to use the result in a property of the HP configurator, I suggest putting it into private data.

Code: Select all

var theDataset = job.getDataset( "Xml" ); // "Xml" is the dataset name from the pickup element
theDataset.evalToNumber( "/xslt/to/width" ); // read the width
// ... read other required variables
// var theRunLength = ...; // do the calculation
job.setPrivateData( "runLength", theRunLength );
Then in the HP configurator you can use a variable to retrieve the private data where needed, e.g. [Job.PrivateData:Key="runLength"].
If you can't use a variable you could write to xml (see the previous example), or maybe use a small javascript expression (job.getPrivateData( "runLength" );
User avatar
gabrielp
Advanced member
Posts: 645
Joined: Fri Aug 08, 2014 4:31 pm
Location: Boston
Contact:

Re: Run length calculation

Post by gabrielp »

To expand on what bens said, if you don't want to write a new script, you can put values in private data with a simple script.

Also, your flow is very easy to read. Really nice that you have your folders representing the state/assumptions about the job instead of just leaving it as "Folder (37)". Goes a long way with debugging problem jobs as well.
Free Switch scripts: open-automation @ GitHub
Free Switch apps: open-automation @ Enfocus appstore

Want to hire me? I'm looking for my next gig. Contact me on LinkedIn or via email.
LasseThid
Advanced member
Posts: 353
Joined: Tue Mar 03, 2015 2:30 pm
Location: Molndal, Sweden

Re: Run length calculation

Post by LasseThid »

Thank you very much for your comments and suggestions.
I will look it in to it as soon as I can. Unfortunately JavaScript is still new to me, I started to learn it online about two weeks ago :D , so I need to find some time to analyze your scripts in order to understand them.

Regarding the folder names I don't know if that is something still stuck from when I learned JSP in the late 80's or if I did that just so I would know where I stopped last time I was working on the script, but as you said it does make it easier to understand what hopefully happens where. :D
Enfocus Switch, Enfocus PitStop Server, Enfocus PDF Review, HP SmartStream& Kodak Prinergy with RBA
Offset 72x102, Offset Large Format, Digital Large Format and Digital print.
LasseThid
Advanced member
Posts: 353
Joined: Tue Mar 03, 2015 2:30 pm
Location: Molndal, Sweden

Re: Run length calculation

Post by LasseThid »

Ok, let's see how much I misunderstood of your comments and scripts... :lol:

The XML I get looks like this:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<order>
	<ordernumber>P14166</ordernumber>
	<system>customerX</system>
	<products>
		<product>
			<filename>P14166_businesscard.pdf</filename>
			<type>businesscard</type>
			<quantity>100</quantity>
			<paper>MultiOffset</paper>
			<color>4+0</color>
			<width>90</width>
			<height>55</height>
			<weight>4</weight>
		</product>
	</products>
</order>
and this is what I came up with after modifying your code:

Code: Select all

var theDataset = job.getDataset( ”Xml” ); // ”Xml” is the dataset name from the pickup element
var theWidth = theDataset.evalToNumber( ”/xslt/to/width” ); // read the width
var theHeight = theDataset.evalToNumber( ”/xslt/to/height” ); // read the height
var theQuantity = theDataset.evalToNumber( ”/xslt/to/quantity” ); // read the quantity
if (theWidth>theHeight) {
	var theRunLength = Math.floor(theQuantity/(Math.floor(318/(theWidth+5))*(Math.floor(460/(theHeight+5))))+1); // landscape product
	} else {
	var theRunLength = Math.floor(theQuantity/(Math.floor(318/(theHeight+5))*(Math.floor(460/(theWidth+5))))+1); // portrait product
	}
job.setPrivateData( ”runLength”, theRunLength );
Does that look like it could work?
Enfocus Switch, Enfocus PitStop Server, Enfocus PDF Review, HP SmartStream& Kodak Prinergy with RBA
Offset 72x102, Offset Large Format, Digital Large Format and Digital print.
User avatar
gabrielp
Advanced member
Posts: 645
Joined: Fri Aug 08, 2014 4:31 pm
Location: Boston
Contact:

Re: Run length calculation

Post by gabrielp »

That looks like it would work, you'll just need to set the proper xpath to find those values in the XML. But again, you can do this without any coding by utilizing a private data configurator like the one I linked to. You would just consume the XML, then in the private data configurator, make the key "YourKey" and then for the value, select inline text with variables and use Switch to point and click to the path of the value within the dataset. You can then use Switch to do all sorts of math on that value before its stored in private value.
Free Switch scripts: open-automation @ GitHub
Free Switch apps: open-automation @ Enfocus appstore

Want to hire me? I'm looking for my next gig. Contact me on LinkedIn or via email.
LasseThid
Advanced member
Posts: 353
Joined: Tue Mar 03, 2015 2:30 pm
Location: Molndal, Sweden

Re: Run length calculation

Post by LasseThid »

Aha... so instead of

Code: Select all

var theWidth = theDataset.evalToNumber( ”/xslt/to/width” )
I should type

Code: Select all

var theWidth = theDataset.evalToNumber( ”/order/products/product/width” )
and so on? Should I keep the " or remove them?
Enfocus Switch, Enfocus PitStop Server, Enfocus PDF Review, HP SmartStream& Kodak Prinergy with RBA
Offset 72x102, Offset Large Format, Digital Large Format and Digital print.
dkelly
TOP CONTRIBUTOR
Posts: 658
Joined: Mon Nov 29, 2010 8:45 pm
Location: Alpharetta GA USA
Contact:

Re: Run length calculation

Post by dkelly »

Should I keep the " or remove them?
keep them since they are a string
bens
Advanced member
Posts: 252
Joined: Thu Mar 03, 2011 10:13 am

Re: Run length calculation

Post by bens »

LasseThid wrote:

Code: Select all

if (theWidth>theHeight) {
	var theRunLength = Math.floor(theQuantity/(Math.floor(318/(theWidth+5))*(Math.floor(460/(theHeight+5))))+1); // landscape product
	} else {
	var theRunLength = Math.floor(theQuantity/(Math.floor(318/(theHeight+5))*(Math.floor(460/(theWidth+5))))+1); // portrait product
	}
job.setPrivateData( ”runLength”, theRunLength );
You're definitely on the right track :-)
Be careful with the scope of your variables though. You have "var theRunLength = ..." between curly braces. That means the variable "theRunLength" only exists within those curly braces. Once the script reaches the end of that block, the variable no longer exists. To fix this, just put the declaration outside of the block:

Code: Select all

var theRunLength = 0;
if (theWidth>theHeight) {
    theRunLength = Math.floor(theQuantity/(Math.floor(318/(theWidth+5))*(Math.floor(460/(theHeight+5))))+1); // landscape product
} else {
    theRunLength = Math.floor(theQuantity/(Math.floor(318/(theHeight+5))*(Math.floor(460/(theWidth+5))))+1); // portrait product
}
job.setPrivateData( ”runLength”, theRunLength );
LasseThid
Advanced member
Posts: 353
Joined: Tue Mar 03, 2015 2:30 pm
Location: Molndal, Sweden

Re: Run length calculation

Post by LasseThid »

I added the code in SwitchScripter, but I had to do some modifications in order to be able to save it (syntax errors), but when I run the flow the pdf is not processed by the Script element, it just sits in the PDF with Metadata folder, so obviously there's something I have missed.

Any Ideas?

Code: Select all

function jobArrived( s : Switch, job : Job )
{
	var theDataset = job.getDataset( "Xml" ); // ”Xml” is the dataset name from the pickup element
	var theWidth = theDataset.evalToNumber( /order/products/product/width ); // read the width
	var theHeight = theDataset.evalToNumber( /order/products/product/height ); // read the height
	var theQuantity = theDataset.evalToNumber( /order/products/product/quantity ); // read the quantity
	if (theWidth>theHeight) {
	   var theRunLength = Math.floor(theQuantity/(Math.floor(318/(theWidth+5))*(Math.floor(460/(theHeight+5))))+1); // landscape product
   } else {
	   var theRunLength = Math.floor(theQuantity/(Math.floor(318/(theHeight+5))*(Math.floor(460/(theWidth+5))))+1); // portrait product
   }
job.setPrivateData( runLength, theRunLength );
}
The modified flow looks like this:
Image
Enfocus Switch, Enfocus PitStop Server, Enfocus PDF Review, HP SmartStream& Kodak Prinergy with RBA
Offset 72x102, Offset Large Format, Digital Large Format and Digital print.
bens
Advanced member
Posts: 252
Joined: Thu Mar 03, 2011 10:13 am

Re: Run length calculation

Post by bens »

There should be quotes around the xslt paths, theRunLength should be declared outside of the if, and the job has to be sent to the outgoing connection(s). If you don't tell Switch that the job should be sent along the flow, it will stay in the input folder forever.

Code: Select all

function jobArrived( s : Switch, job : Job )
{
   var theDataset = job.getDataset( "Xml" ); // ”Xml” is the dataset name from the pickup element
   var theWidth = theDataset.evalToNumber( "/order/products/product/width" ); // read the width
   var theHeight = theDataset.evalToNumber( "/order/products/product/height" ); // read the height
   var theQuantity = theDataset.evalToNumber( "/order/products/product/quantity" ); // read the quantity
   var theRunLength = 0;
   if (theWidth>theHeight) {
     theRunLength = Math.floor(theQuantity/(Math.floor(318/(theWidth+5))*(Math.floor(460/(theHeight+5))))+1); // landscape product
   } else {
     theRunLength = Math.floor(theQuantity/(Math.floor(318/(theHeight+5))*(Math.floor(460/(theWidth+5))))+1); // portrait product
   }
   job.setPrivateData( runLength, theRunLength );
   job.sendToSingle( job.getPath() );
}
LasseThid
Advanced member
Posts: 353
Joined: Tue Mar 03, 2015 2:30 pm
Location: Molndal, Sweden

Re: Run length calculation

Post by LasseThid »

I copied your code and pasted it into SwitchScripter and this time I didn't get the syntax error I got last time I had the quotes...
Unfortunately the pdf is still stuck in the PDF with metadata folder, I though the job.sendToSingle was the part that would tell Switch to send the job along, but perhaps that's wrong.

After googling a little I did a minor change to the script, but still the file is not sent along...

Code: Select all

function jobArrived( s : Switch, job : Job )
{
   var theDataset = job.getDataset( "Xml" ); // ”Xml” is the dataset name from the pickup element
   var theWidth = theDataset.evalToNumber( "/order/products/product/width" ); // read the width
   var theHeight = theDataset.evalToNumber( "/order/products/product/height" ); // read the height
   var theQuantity = theDataset.evalToNumber( "/order/products/product/quantity" ); // read the quantity
   var theFileName = theDataset.evalToString( "/order/products/product/filename" ); // read the filename
   var inputJob = job.getPath();	
   var theRunLength = 0;
   if (theWidth>theHeight) {
     theRunLength = Math.floor(theQuantity/(Math.floor(318/(theWidth+5))*(Math.floor(460/(theHeight+5))))+1); // landscape product
   } else {
     theRunLength = Math.floor(theQuantity/(Math.floor(318/(theHeight+5))*(Math.floor(460/(theWidth+5))))+1); // portrait product
   }
   job.setPrivateData( runLength, theRunLength );
   job.sendToSingle( inputJob, theFileName );
}
Enfocus Switch, Enfocus PitStop Server, Enfocus PDF Review, HP SmartStream& Kodak Prinergy with RBA
Offset 72x102, Offset Large Format, Digital Large Format and Digital print.
dkelly
TOP CONTRIBUTOR
Posts: 658
Joined: Mon Nov 29, 2010 8:45 pm
Location: Alpharetta GA USA
Contact:

Re: Run length calculation

Post by dkelly »

You have to tell Switch to discard the input file, add the following to the end of your script.

Code: Select all

job.sendToNull(job.getPath);
Post Reply