Calling script alot on ticket template causing hang

I have just found out my first issue on v5.1.56 causing by calling a lot of scripts on Ticket Template and previewing it, it will causing the sambapos to hang/not responding.

The Ticket Template :

[LAYOUT]
-- General layout
<ec>
<BMP>C:\Users\Este\Documents\SambaPOS5\Logo.bmp
<el>
<J00>
<T>Ticket
<L00>Date: {TICKET DATE}
<L00>Time: {TIME}
<L00>Server: {USER NAME}
{ENTITIES}
<L00>Ticket No:{TICKET NO}
<F>-
{ORDERS}
<F>=
<EB>
{DISCOUNTS}
[<J10>Total Gift:| Rp {CALL:str.pad('{ORDER STATE TOTAL:Gift}','left',13," ")}]
{SERVICES}
<J10>Total:| Rp {CALL:str.pad('{TICKET TOTAL}','left',13," ")}
<F>=
<J00>{TICKET TAG:GCN}| Balance: Rp [=F(TN('{TICKET TAG:GCB}'))]
[<J00>Total FREE:| Rp {CALL:str.pad('{ORDER STATE TOTAL:Gift}','left',13," ")}
[<J00>Discounts:| Rp [=F(TN('{ORDER TAG TOTAL:Discount}')+TN('{ORDER TAG TOTAL:VIP Discount}')+TN('{ORDER TAG TOTAL:HH Discount}'))]]
[<J00>TOTAL SAVINGS:| Rp [=F(-1*(TN('{ORDER TAG TOTAL:Discount}')+TN('{ORDER TAG TOTAL:VIP Discount}')+TN('{ORDER TAG TOTAL:HH Discount}'))+TN('{ORDER STATE TOTAL:Gift}'))]]
{PAYMENTS}
<DB>
<F>=

[DISCOUNTS]
<J00>{CALCULATION NAME} %{CALCULATION AMOUNT}|{CALCULATION TOTAL}

[SERVICES]
<J00>{CALCULATION NAME}|{CALCULATION TOTAL}

[PAYMENTS]
<J00>{PAYMENT NAME}|Rp {CALL:str.pad('{PAYMENT AMOUNT}','left',13," ")}

[ORDERS]
-- Default format for orders
<L00>- {CALL:str.pad('{QUANTITY}','right',2," ")} {CALL:str.cut('{NAME}','30','1')}
<J00> {CALL:str.cut('{NAME}','30','2')} | Rp {CALL:str.pad('{TOTAL PRICE}','left',13," ")}
{ORDER TAGS}

[ORDERS:Gift]
-- Format for gifted orders
<L00>- {CALL:str.pad('{QUANTITY}','right',2," ")} {CALL:str.cut('{NAME}','30','1')}
<J00> {CALL:str.cut('{NAME}','30','2')} | **GIFT**
{ORDER TAGS}

[ORDERS:Void]
-- Nothing will print for void lines

[ORDER TAGS]
-- Format for order tags
<J00> * {ORDER TAG NAME} | {ORDER TAG PRICE}

[ENTITIES:Table]
-- Table entity format
<L00>Table: {ENTITY NAME}

[ENTITIES:Customer]
-- Customer entity format
<J00>Customer: {ENTITY NAME} | Phone : {ENTITY DATA:Phone}

The script :

function pad(s,d,l,c) {

  // s : input string
  // d : direction - left or right pad
  // l : length of output string
  // c : pad character (0," ")
  
  // ensure the input is a string, not a number
  s = ''+s+'';
  
  var outstring = "";
  var padding = "";
  
  // build string padding
  padding=Array(l+1).join(c);
  
  // pad the input right or left
  if (d=='right') {
    outstring = (s+padding).substring(0,padding.length);
  } else {
    outstring = (padding+s).slice(0-padding.length);
  }
  return outstring;
}

function cut(fullWord,maxLength,operation)
{
   var fullLength = fullWord.Length
   if (typeof(maxLength) == "undefined") { var maxLength = '30'; }
   if (maxLength == "0") { var maxLength = '30'; }
   var trimmedString1 = fullWord.substr(0, maxLength)
   trimmedString1 = trimmedString1.substr(0, Math.min(trimmedString1.length, trimmedString1.lastIndexOf(" ")));
   var trimmedString2 = fullWord.substr(Math.min(trimmedString1.length, trimmedString1.lastIndexOf(" ")), fullLength)
   trimmedString2 = trimmedString2.substr(trimmedString1.length-trimmedString1.lastIndexOf(" "), trimmedString2.length);
   if (operation == "1") { return trimmedString1; } 
   if (operation == "2") { return trimmedString2; } 
}

To reproduce add the script to automation, make a transaction with normal and gift on it, and the ticket template and click preview.

Printing the ticket which has the offending ticket template also caused hang.

Looks like the hang threshold is if the script call above 10 times, more than 10 it will hang

Wow thats a rediculous amount of scripts just to print a ticket. Surely there would be a more efficient way?

Why are you using that many script calls just to format a ticket? Can you explain the formatting your trying to achieve maybe we can find a more efficient way to do that. We shouldnt need that many script calls just to format a ticket.

Imagine if you had more than 1 terminal using that same template in a live environment. LOL I can almost feel the computer crying

It’s tidiness formatting the Rp automatically so all of them in-line together :
Not formatted :

                                          
░░░░░░░░░░░░░░░ T i c k e t ░░░░░░░░░░░░░░
Date: 16/12/2015
Time: 13:10
Server: Administrator
Table: B10
Ticket No:1
------------------------------------------
- 1  Chocolate Cheese
  Cake.Loyang                     **GIFT**
- 1  Blueberry Cheese
  Cake.Slice                      **GIFT**
- 1  Chocolate Cheese
  Cake.Loyang             Rp    180.000,00
- 1  Chocolate Cheese
  Cake.Slice              Rp     18.000,00
- 1  Blueberry Cheese
  Cake.Slice              Rp     18.000,00
==========================================
Total Gift:               Rp    198.000,00
Total:                    Rp    216.000,00
==========================================
                          Balance: Rp 0,00
Total FREE:                  Rp 198.000,00
TOTAL SAVINGS:               Rp 198.000,00
Cash                      Rp    216.000,00
==========================================

Formatted :

░░░░░░░░░░░░░░░ T i c k e t ░░░░░░░░░░░░░░
Date: 16/12/2015
Time: 13:10
Server: Administrator
Table: B10
Ticket No:1
------------------------------------------
- 1  Chocolate Cheese
  Cake.Loyang                     **GIFT**
- 1  Blueberry Cheese
  Cake.Slice                      **GIFT**
- 1  Chocolate Cheese
  Cake.Loyang             Rp    180.000,00
- 1  Chocolate Cheese
  Cake.Slice              Rp     18.000,00
- 1  Blueberry Cheese
  Cake.Slice              Rp     18.000,00
==========================================
Total Gift:               Rp    198.000,00
Total:                    Rp    216.000,00
==========================================
                          Balance: Rp 0,00
Total FREE:               Rp    198.000,00
TOTAL SAVINGS:            Rp    198.000,00
Cash                      Rp    216.000,00
==========================================

I don’t think so, because sambapos forum source code is much more using cpu cycle than calling those script above.
Right click on this page and “view page source” on chrome. The script above only measly/really small and not noticeable in performance than current webpage modern standard. I know that sambapos not using chrome engine but still this is a bug and not supposed to be happened.

I found one mistake you made and its the culpret.

<J00>{TICKET TAG:GCN}| Balance: Rp [=F(TN('{TICKET TAG:GCB}'))]
[<J00>Total FREE:| Rp {CALL:str.pad('{ORDER STATE TOTAL:Gift}','left',13," ")}
[<J00>Discounts:| Rp [=F(TN('{ORDER TAG TOTAL:Discount}')+TN('{ORDER TAG TOTAL:VIP Discount}')+TN('{ORDER TAG TOTAL:HH Discount}'))]]
[<J00>TOTAL SAVINGS:| Rp [=F(-1*(TN('{ORDER TAG TOTAL:Discount}')+TN('{ORDER TAG TOTAL:VIP Discount}')+TN('{ORDER TAG TOTAL:HH Discount}'))+TN('{ORDER STATE TOTAL:Gift}'))]]

Do you see the open ended bracket?

[<J00>Total FREE:| Rp {CALL:str.pad('{ORDER STATE TOTAL:Gift}','left',13," ")}

Should be

[<J00>Total FREE:| Rp {CALL:str.pad('{ORDER STATE TOTAL:Gift}','left',13," ")}]

Template works fine once you fix that mistake.

Doh again, how i can totally missed that silly mistake! :frowning:, i apologize, because normally a mistakes in Ticket Template doesn’t cause it to hang, probably @emre should make it not hang. Thanks kendash,

Other question. A calculation in ticket template is not possible within script call?. I am trying this :

[<J00>TOTAL SAVINGS:| Rp {CALL:str.pad('[=F(-1*(TN('{ORDER TAG TOTAL:Discount}')+TN('{ORDER TAG TOTAL:VIP Discount}')+TN('{ORDER TAG TOTAL:HH Discount}'))+TN('{ORDER STATE TOTAL:Gift}'))]','left',13," ")}]

Probably not. You could do the calculation in the script though.

I guess it wouldn’t be probable as i would be need calling two script at once ( calling the calculation script & the padding script) :frowning:.

Can you paste str.pad function with the screenshot here?

@emre
Sure :

function pad(s,d,l,c) {

  // s : input string
  // d : direction - left or right pad
  // l : length of output string
  // c : pad character (0," ")
  
  // ensure the input is a string, not a number
  s = ''+s+'';
  
  var outstring = "";
  var padding = "";
  
  // build string padding
  padding=Array(l+1).join(c);
  
  // pad the input right or left
  if (d=='right') {
    outstring = (s+padding).substring(0,padding.length);
  } else {
    outstring = (padding+s).slice(0-padding.length);
  }
  return outstring;
}

Add this function into str script.

function sumpad(d,l,c)
{
   var result = 0;
   for(i=3;i<arguments.length;i++)
   {result += Number(arguments[i]);}
   return pad(result,d,l,c);
}

… and try calling it like.

{CALL:str.sumpad('left',13,' ','{ORDER TAG TOTAL:Discount}','{ORDER TAG TOTAL:VIP Discount}','{ORDER TAG TOTAL:HH Discount}','{ORDER STATE TOTAL:Gift}')}

I didn’t tested it with real data but I think you’ll get the idea.

Ok, that is cool. That is why @emre is the real code-master here - not like the rest of us “wannabees” :stuck_out_tongue_winking_eye:

lol got it. As it was originally your stuff that makes you the real master.

Returned “NaN” on me, called on script debugger using “sumpad(‘left’,13,’ ',‘198.000,00’);” .

@emre
How about the hang issue?, when the script calls missing a enclosure?

For example :

[<J00>Total FREE:| Rp {CALL:str.pad('{ORDER STATE TOTAL:Gift}','left',13," ")}

It seems Number() doesn’t accept pre-formatted variable, Now i have modified the script to the following :

function pad(s,d,l,c) {

  // s : input string
  // d : direction - left or right pad
  // l : length of output string
  // c : pad character (0," ")
  
  // ensure the input is a string, not a number
  s = ''+s+'';
  
  var outstring = "";
  var padding = "";
  
  // build string padding
  padding=Array(l+1).join(c);
  
  // pad the input right or left
  if (d=='right') {
    outstring = (s+padding).substring(0,padding.length);
  } else {
    outstring = (padding+s).slice(0-padding.length);
  }
  return outstring;
}

/**
 * Number.prototype.format(n, x, s, c)
 * 
 * @param integer n: length of decimal
 * @param integer x: length of whole part
 * @param mixed   s: sections delimiter
 * @param mixed   c: decimal delimiter
 */
Number.prototype.format = function(n, x, s, c) {
    var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\D' : '$') + ')',
        num = this.toFixed(Math.max(0, ~~n));

    return (c ? num.replace('.', c) : num).replace(new RegExp(re, 'g'), '$&' + (s || ','));
};

function sumpad(d,l,c)
{
   var result = 0;
   for(i=3;i<arguments.length;i++)
   {
      var temp = 0;
      temp = Number(arguments[i].replace(/\./g, '').replace(/,/,'.'));
      if(temp < 0) {temp *= '-1';}
      result += temp;
   }
   result = result.format(2, 3, '.', ',')
   return pad(result,d,l,c);
}

Calling it through “sumpad(‘left’,13,’ ',‘198.000,00’);” works fine, and returning formatted string, but when called using :

{CALL:str.sumpad('left',13,' ','{ORDER TAG TOTAL:Discount}','{ORDER TAG TOTAL:VIP Discount}','{ORDER TAG TOTAL:HH Discount}','{ORDER STATE TOTAL:Gift}')}

It Return empty reply or “NaN”.

Scratch that, after restarting sambapos seems works fine :smile:.

Thanks emre

There are 45 lines in this ticket and each line uses pad function 3 times so it gets called +120 times to preview that result. I didn’t noticed a hang… That might happen for a specific case so it will be awesome if we can create a reproducible example.

@emre
Yup, the scripts works wonder and fast if the enclosure entered right, what i have meant was if in ticket template for example

In above there should be ended by a “]”, try it without enclosing it with “]” ending and click preview, in my part sambapos is hang. Normally it just returning an empty preview if the ticket template is wrong but in this case causing sambapos to hang.

I can send you my database dump if you want.

[Edit]
Sorry if you have read the first post, as you can see through the thread, the hang not caused by overflow of calling the scripts but by missing enclosure, i just want to pinpoint to you that the condition shouldn’t caused sambapos to hang.

OK got it. Thank you very much for reporting.

Great :smile:, it’s a minor annoyance but become major as when editing other configs, user won’t be able to save the unsaved works.