Julius Kavay · Sep 3, 2024 go to post

By the way, if you need again and again a local timestamp with decimals, just create a user defined system variable. Make a one line entry into the %ZLANGV00.mac routine:

%ZLANGV00 ; User defined (system) variables

	// Local timestamp with decimals
ZLTS()	quit $now($ztz-$s($SYSTEM.Util.IsDST():60,1:0))

You can use whatever name you want as long as it starts with Z, contains uppercase chars only and do not conflict with existing names.  Use it as a standard $-variable

write $zlts, $zdt($zlts,3,1,3)
67086,85681.092746
2024-09-03 23:48:01.092
Julius Kavay · Sep 3, 2024 go to post

Together with $now() and timezone adjustment you can have the desired result

for time=$h, $now($ztz-$s($SYSTEM.Util.IsDST():60,1:0)) write time,?20,$zdt(time,3,1,3),!
// assuming 60 min summertime offset
//
// you should get an output like thisL
67086,83334         2024-09-03 23:08:54.000
67086,83334.1341026 2024-09-03 23:08:54.134

There is an (old) undocumented function which gives the $h value with several  decimal places, unfortunately the recommended replacement is more or less the above solution instead of a simple $zlts (z-local-timestamp).

Julius Kavay · Aug 28, 2024 go to post

This is possible, but you have to use it the correct way. $SYSTEM.OBJ is just a shorthand for ##class(%SYSTEM.OBJECT), so the correct syntax for your desire is:

job ##class(%SYSTEM.OBJ).Export("yourRoutine.mac","yourPathAndFilename.xml")
Julius Kavay · Aug 22, 2024 go to post

in a routine or class, the line

ClassMethod ALine()
{
    quit $st($st,"MCODE")
}

gives you the line quit $st($st,"MCODE")

The systemvariable $zname gives you the name of the routine, where you reference $zname and in a classmethod $this gives you the name of the class

Julius Kavay · Aug 13, 2024 go to post

We need the source code, so the compiler flag for keeping the source must be on. The 38 char version does the job

ClassMethod ascii() [ ProcedureBlock = 0 ]
{
x	n i f i=32:1:126 w:$t(x)'[$c(i) *i
}

The 34-character version does the job too  has a side effect (leaving the variable i with the last value)

ClassMethod ascii() [ ProcedureBlock = 0 ]
{
y	f i=32:1:126 w:$t(y)'[$c(i) *i
}
Julius Kavay · Aug 9, 2024 go to post

It shouldn't be invalid because there are no corresponding constraints.

At the beginning, I thought not to participate, because of the problematic specification and example, but now, as I see, I'm not the only one with questions without answers, hence I offer an 38 char solution too (including the hint to compiler flags) and a shorter version with 34 chars, a correkt result but with "a little bit" of side effect.

Julius Kavay · Aug 9, 2024 go to post

The problem is, the specification for this task is simple unprecise, and according to my opinion, gives a faulty example. Your exmple code has just a Set command but the task talks about "print out" - hence, I expected to see either a Write "whatever" or at last a Quit "whatever" comand.
Also, if we talk about a method signature, I take in account the number of arguments (maybe their types) only and the return type but never their method keywords, as in the solution from Eduard, hence his solution is not only creative but valid too.
I think, a fair way to mesure the size of a solution is, if you take the size of the routine which will be executed, and that is the INT routine, which is directly (we neglect the possible compiler optimizations, that's the compilers and not the users credit) compiled into a executable. How I got that code (some generator or via a macro or whatever other method) is actually irrelevant.
A very good example for using or not using a method keyword is the "codemode=expression":

/// you save that "Quit " but have to write "codemode=expression"
/// which is not taken in account by the Implementation.Size
ClassMethod Test() [ codemode = expression]
{
 123
}

/// you have to write "Quit " and save the writing of "codemode..."
/// The Implementation.Size counts that "quit "
ClassMethod Test2()
{
 quit 123
}

Whatever you choose, the corresponding INT code is always "quit ..."

So the bottom line is, either you should define all constraints and conditions or accept each end every clever solution.

Julius Kavay · Aug 7, 2024 go to post
ClassMethod TimeDiff(inpTime = "2024-08-07 17:58:51.563")
{
	set current=$h // or $now(tz-offset)
	set inpTime=$zdth(inpTime,3)
	quit current-inpTime*86400+$p(current,",",2)-$p(inpTime,",",2)
}
Julius Kavay · Aug 5, 2024 go to post

First convert the dynamic array to a Cache List and then the Cache List to Python List - voila the job is done

/// Convert a dynamic array to a Cache List
/// 
ClassMethod ArrayToList(arr)
{
	q:'arr.%Size() $lb()
	s list="", it=arr.%GetIterator()
	while it,it.%GetNext(.key,.val) {
		s typ=arr.%GetTypeOf(key)
		s list=list_$case(typ,"object":$lb(val.%ToJSON()),"array":$lb(..ArrayToList(val)),"null":$lb(),:$lb(val))
	}
	q list
}
Julius Kavay · Aug 2, 2024 go to post

First, I presume, the Studio lacks such a functionality because usually each nsp contains independent data. As an example, for each of my customers (applications) I have an dedicated namespace  (of course, you may say, one can allways have an exeption),

and second, if there is no readymade functionality, then make your own. Sometimes it takes longer asking questions or searching the internet then writing a quick-and-dirty "one liner", something like this:

// classdefinitions are stored in ^oddDEF, mac-routines in ^rMAC
// as said above, quick-and-dirty:
// if the SEARCHTERM occurs in %-items, then you will get multiple hits
//
// the one-liner version
k n i ##class(%SYS.Namespace).ListAll(.n) s n="" f  s n=$o(n(n)) q:n=""  f s="^|n|rMAC","^|n|oddDEF" f  s s=$q(@s) q:s=""  w:@s_s["SEARCHTERM" s," ",@s,!

// for folks with less experience
//
ClassMethod SearchAllNSP(searchterm)
{
   i ##class(%SYS.Namespace).ListAll(.n) {
      s n=""
      f  {s n=$o(n(n)) q:n=""
          f s="^|n|rMAC","^|n|oddDEF" {
             f  s s=$q(@s) q:s=""  w:@s_s[searchterm s," ",@s,!
          }
      }
   }
}

It's up to you to left out all those multiple %-items and to add some formatting...

So the bottom line of my answer is: yes, there is a way to search (whatever you want) in one go

Julius Kavay · Jun 23, 2024 go to post
Class DC.BigJSON Extends %RegisteredObject
{

ClassMethod Test(filename)
{
	if ..SaveToFile(..MakeJSON(), filename) {
		write "Save OK",!
		write "Size ",##class(%File).GetFileSize(filename),!
		
		set input=##class(%File).%New(filename)
		set sts=input.Open("RS")
		if sts {
			set json={}.%FromJSON(input)
			set iter=json.%GetIterator()
			while iter.%GetNext(.key, .val) {
				write "key=",key," size=",$l(val)," data=",$e(val,1,10)_"...",!
			}
		} else  { write $system.Status.GetOneErrorText(sts),! }
	}
}

ClassMethod MakeJSON()
{
	set obj={}
	set obj.text1=$tr($j("",3600000)," ","a")
	set obj.text2=$tr($j("",3600000)," ","b")
	set obj.text3=$tr($j("",3600000)," ","c")
	quit obj
}

ClassMethod SaveToFile(obj, filename)
{
	set file=##class(%File).%New(filename)
	set sts=file.Open("wnu")
	if sts {
		do obj.%ToJSON(file)
		do file.Rewind()
		use file.Name 
		do file.OutputToDevice()
		do file.Close()
		quit 1
	} else { quit sts }
}

}

The size shouldn't be a problem


USER>do ##class(DC.BigJSON).Test("/tmp/test1.txt")
Save OK
Size 10800034
key=text1 size=3600000 data=aaaaaaaaaa...
key=text2 size=3600000 data=bbbbbbbbbb...
key=text3 size=3600000 data=cccccccccc...

Julius Kavay · Jun 22, 2024 go to post

The first part (Base 64 encoding is not able to encode ... unicode (2 byte) characters)  is correct. The second part (data-->utf8-->base64 and base64-->utf8-->data) is correct only if there is an agreement beetwen the sender and receiver about the double-encoding (utf8+base64).

If I was told, I get a base64 encoded file then I expect a file which is only base64 encoded and not a mix of several encodings including base64. A simple way to encode your document could be something like this:

ClassMethod Encode(infile, outfile)
{
    // file-binary reads bytes and not characters
    set str = ##class(%Stream.FileBinary).%New()
    set str.Filename = infile
    set len = 24000 // len #3 must be 0 !
    set nonl = 1    // no-newline: do not insert CR+LF
    do str.Rewind()

    open outfile:"nwu":0
    if $test {
        use outfile
        while 'str.AtEnd { write $system.Encryption.Base64Encode(str.Read(len),nonl) }
        close outfile
    }
    quit $test
}
Julius Kavay · May 30, 2024 go to post

Take a look at the classes $system.Security and $system.License, whichever better fulfills your needs

Julius Kavay · May 29, 2024 go to post

Sadly, I haven't a shorher solution than yours but another one (with the same size)

ClassMethod Count(s)
{
	q $l($tr(s,")]}D>"_s,1E4))
}
Julius Kavay · May 28, 2024 go to post

It seems the task definition lacks the preciseness and you have the power of observation. What about this?

ClassMethod Count(s)
{
	q $l($tr(s,")]}>","DDDD"),"D")-1
}
Julius Kavay · May 28, 2024 go to post

In the past we got challenges with a better definition... ;-((  ☹


In the original post, I'm pretty sure, there were
")s)).:D :~) ;~D :) xD ))" instead of
")s).:D :~) ;~D :) xD"

and
"(smiley) ))" instead of
"(smiley)"

Nevertheless,

"Sadness >:( :[ :{ :("  ---> you say: 0
         >                     I say: 1 (0 Eyses, 0 noses 1 mouth)
and there is no rule about interspace requirements

My quick solution:

ClassMethod Count(s)
{
	while $locate(s,"[:;8B=]?[co\^~-]?[\)\]\}D>]",$g(i),i),$i(n){} q +$g(n)
}

/// If one accepts "" as 0 then change +$g(n) to $g(n)

/// I would like a solution as (see the + char in regex)
/// but then the rules should be changed
///
ClassMethod Count(s)
{
	while $locate(s,"[:;8B=]?[co\^~-]?[\)\]\}D>]+",$g(i),i),$i(n){} q +$g(n)
}
Julius Kavay · May 15, 2024 go to post

According to your definition, "A number is Esthetic if ... between every pair of its adjacent digits ...", the test example

test.assert_equals(esthetic(1), [2, 3, 4, 5, 6, 7, 8, 9, 10])

is wrong, because the number one (1) converted in whatever number base is always 1. Looking on that 1 I do NOT see any ADJACENT digit(s), except you define that a single digit is always an esthetic number (but I do not see such a definition).

justmy2cents

Julius Kavay · May 13, 2024 go to post

If your system does not support JSON (i.e. pre 2016.2?) then give this "dirty trick" a try:

- add a zero-width-space character to your numbers
- create the output stream
- remove the zero-width-space characters

Instead of the zero-width-space you can use any other character too, which does not appear in your data (binary data should be base64 encoded).

ClassMethod WithQuotes()
{
	set zwsp = $c(8203) // zero-width-space
	set obj = ##class(%ZEN.proxyObject).%New()
	
	set obj.ID = 1234_zwsp
	set obj.Number=123.45_zwsp
	
	if ##class(%ZEN.Auxiliary.jsonArrayProvider).%WriteJSONStreamFromObject(.tmp,obj) {
  		set json=##class(%Stream.TmpBinary).%New()
		do tmp.Rewind()
		while 'tmp.AtEnd { do json.Write($tr(tmp.Read(32000),zwsp)) }
	}
	
	do json.Rewind()
	write json.Read(json.Size)
}
Julius Kavay · May 2, 2024 go to post

Can you show us your iterator so we can tell you what's wrong with it. Or should we try to guess your code?

Julius Kavay · Apr 26, 2024 go to post

The one way is to use %XML.TextReader

ClassMethod Reader(str, pth, ByRef val)
{
	kill val
	set val=0
	// Adjust the method name below to your needs
	// ParseString(), ParseStream(), ParseFile() 
	if ##class(%XML.TextReader).ParseString(str,.rdr) {
		while rdr.Read() {
			if rdr.NodeType="chars",rdr.Path=pth set val($i(val))=rdr.Value
		}
		quit 1
	}
	quit 0
}

set str="<?xml version=""1.0"" encoding=""UTF-8""?><Input><data><Ids><Id><Type>A</Type><Value>123</Value></Id><Id><Type>B</Type><Value>456</Value></Id></Ids></data></Input>"
write ##class(yourClass).Reader(str,"/Input/data/Ids/Id/Value",.val) --> 1
zw val -->
val=2
val(1)=123
val(2)=456

The other way is to use %XML.Reader() and correlate to a class which describes your XML structure

Julius Kavay · Apr 18, 2024 go to post

I can't help with "how to transfer a file to Azure" (I do not use Azure) but before you transfer an IRIS.dat (or an Cache.dat)  you should DISMOUNT the corresponding database. Transferring a mounted database is like tire changing in a moving car - it's possible but dangerous.

Julius Kavay · Apr 18, 2024 go to post

In the above code just insert a Lock and Unlock, and the problem is solved

  //Buid table if it doesn't exist
  
  lock +^LockOutOthers // or any other name you wish
                       // No timeout! At this point everybody has to wait
                       // as long as the current job does a table check/update
  &SQL(
  ...
  ...
  }
  
  lock -^LockOutOthers  // let the others in
  
  Quit outVisitID
  
Julius Kavay · Apr 15, 2024 go to post

As you wrote,  %XML.TextReader is used to read arbtrary XML documents. "A text where in the middle a little bit xml-structure sits" isn't XML!

Maybe there is a Pyhton library for extracting XML from a text. If not, probably you have to read char-after-char, count each "<" (+1) and ">" (-1) and if the counter is 0 then between the first "<"  and the last ">" probably you have a correct XML structure. Oh, and don't forget for <![CDATA[...]]> sequences, which makes the reading more challenging.

Julius Kavay · Apr 15, 2024 go to post

According to your screenshot, you have 22 licenses, of which 21 are available.  On the left side of the control panel, there should be a node named Process. Click on it, and you see all the current active processes including the user name, if the login process make use of the License.Login() (as far as I remember)

Julius Kavay · Apr 15, 2024 go to post

The above screenshot is from your old Cache (5.x.x)!

You get a "License limit exceeded" error if
- all the licenses are in use
- there is no license set
- possibly when licenses are expired (I'm not sure)

Julius Kavay · Apr 15, 2024 go to post

Your subject (compilation error iris terminal class not found) and the screenshot
- workinhg on Class: Class TESTsAMTraining.NewClassDemo1
- calling a class: do ##class(MyCos.COSTest).Main
- and the error message: <CLASS DOES NOT EXISTS>

do not match!

I do not see anything about a "compilation error" on the other hand, there is an error saying, a class do not exists.

So please help us to help you and try to give us correct data about your problem.
Thank you.

Julius Kavay · Apr 13, 2024 go to post

Just came to my mind
- Cache-5.0.x is likely to be 32 Bit version, Win-11 is 64 Bit (only) (in case, the application uses some .dll, .ocx, etc.)
- unlikely that you use it, but as a hint, LAT is not supported anymore
- user database is now provided by ISC. In case your application maintains its own users, you can still use your own user database, but the login process will require some "adaption"

Julius Kavay · Apr 13, 2024 go to post

As a first step, I would contact your ISC Sales because Cache-5.0.x licenses neither work with (the latest) Cache nor with IRIS. Second, there was a lot of change between Cache-5.0.x and recent Cache/IRIS versions, so I would check to see if there are any problems to expect. A customer of mine "upgraded" fom Cache-5.0.21 to IRIS  some four years ago...