go to post Julius Kavay · Feb 18, 2021 I think, your solution is an "ad hoc" solution for a particular task, anyway, I want to point out two problems. First, the solution fails, if the size of <source> is less then than the size of <target>: set source={"Name":"Joe", "Age":50 } set target={"Name":"Joe", "Age":50, "Phone":"123-456"} write CompareJSON(source,target) ---> 1 write CompareJSON(target,source) ---> 0 The same goes for data like: set source={"Name":"Joe", "Age":50, "Data":[10,20] } set target={"Name":"Joe", "Age":50, "Data":[10,20,30]} Maybe your data do not have such cases. A quick check could be: if source.%Size()-target.%Size() { quit "Size-problem" } Second, in a more "general" case, comparing lists could sometimes lead to an philosophical question:are two lists with the same elements but in a different sequence (of those elements) equal or not? list1: [aaa, bbb] list2: [bbb, aaa] The answer MAY depend on the question, what is stored in those lists? If the lists contains, for example, some kind of instructions, then the sequence of those instructions will mattern, but if those list are just list of, say my hobbies, then the sequence is unimportant (except, if one implies some kind of weighting, like the first entry is my preferred hobby). This implies to me, to compare two list, you MAY need an extra info, something like:dependsOnSequence = yes | no One more hint, in the line s tSC= ..CompareJSON(value,target.%Get(key),RefNo) what happens if target.%Get(key) is empty (or not a corresponding object)? Just my2cents
go to post Julius Kavay · Jan 15, 2021 Ok, here I am... sorry for the delay. *********************************************** Forget it! I'm unable to copy and paste a program (in this case a method) into this text box! After paste operation, some lines are joint, others not, the indention is lost... Maybe I'm just too dumb to work with the text box... ***************************************** If you want this class, you can it download from my FTP. ftp: ftp.kavay.at usr: dcmember psw: member-of-DC
go to post Julius Kavay · Jan 14, 2021 I'm not sure, what you want to do, but if you want to read a tiff file by byte-by-byte and the interpret it in some kind, there is a very simple example for the start. The method below returns the file type (gif,jpg,png or tif) based on the magic number. /// Identify an image by its magic number /// (only for gif,jpg,png and tif) ClassMethod ImageType(file, ByRef err) { o file:"ru":0 i $t { s io=$i, err="" u file r x#8 i x?1"GIF8"1(1"7",1"9")1"a" { s typ="gif" } elseif $e(x,1,2)=$c(255,216), $$end()=$c(255,217) { s typ="jpg" } elseif x=$c(137,80,78,71,13,10,26,10) { s typ="png" } elseif $case($e(x,1,4), $c(73,73,42,0):1, $c(77,77,0,42):1, :0) { s typ="tif" } else { s typ="", err="File type unknown" } c file u:io]"" io } else { s typ="", err="Can't open "_file } q typ end() s t="" r:$zseek(-2,2) t#2 q t } I have also a method to retrive the image size (pixelsWidth and pixelsHeight) for the same (gif,jpg,png and tif) files. If you are working on similar problem, I could post this method too.
go to post Julius Kavay · Jan 14, 2021 By the way, the above method returns the OS, Cache or IRIS was built for. Because you can only install a product (Cache or IRIS) on a OS for which the product was built, so the above method returns the OS where your product runs.
go to post Julius Kavay · Jan 11, 2021 I see right now, cut-and-paste without looking-and-checking isn't good! Sorry, for some stupid reason, I copied the wrong lines. The correct ones are: ClassMethod Diamond(n) { f n=1:1:n w ! f j=1:1:n,n-1:-1:1 w !?n-j f i=1:1:j,j-1:-1:1 w i } ClassMethod Infinite(n) { f n=1:1:n w ! f j=1:1:n,n-1:-1:1 w !?n-j f i=1:1:j,j-1:-1:1 w i#10 } Also, Dimond() works from 0 thru 9 (and not thru 10). The line lengths (with 63 and 66 chars) were correct. Finally, the correct output: do ##class(DC.CodeGolf).Diamond(3) 1 1 121 1 1 121 12321 121 1
go to post Julius Kavay · Jan 11, 2021 OK, you want it short and endless? You can get it! Diamond() works from 0 thru 10 using 63 chars Infinite() works from 0 thru Cache's maxint and has 66 chars of source code. ClassMethod Diamond(n) { f n=1:1:n w ! f j=1:1:n,n-1:-1:1 w !?n-j f i=1:1:2*j-1 w i#-j+j } ClassMethod Infinite(n) { f n=1:1:n w ! f j=1:1:n,n-1:-1:1 w !?n-j f i=1:1:2*j-1 w i#-j+j#10 } Some output USER> USER>d ##class(DC.CodeGolf).Diamond(0) USER>d ##class(DC.CodeGolf).Diamond(3) 1 1 121 1 1 121 12312 121 1 USER>d ##class(DC.CodeGolf).Infinite(13) 1 1 121 1 1 121 12312 121 1 1 121 12312 1234123 12312 121 1 1 121 12312 1234123 123451234 1234123 12312 121 1 1 121 12312 1234123 123451234 12345612345 123451234 1234123 12312 121 1 1 121 12312 1234123 123451234 12345612345 1234567123456 12345612345 123451234 1234123 12312 121 1 1 121 12312 1234123 123451234 12345612345 1234567123456 123456781234567 1234567123456 12345612345 123451234 1234123 12312 121 1 1 121 12312 1234123 123451234 12345612345 1234567123456 123456781234567 12345678912345678 123456781234567 1234567123456 12345612345 123451234 1234123 12312 121 1 1 121 12312 1234123 123451234 12345612345 1234567123456 123456781234567 12345678912345678 1234567890123456789 12345678912345678 123456781234567 1234567123456 12345612345 123451234 1234123 12312 121 1 1 121 12312 1234123 123451234 12345612345 1234567123456 123456781234567 12345678912345678 1234567890123456789 123456789011234567890 1234567890123456789 12345678912345678 123456781234567 1234567123456 12345612345 123451234 1234123 12312 121 1 1 121 12312 1234123 123451234 12345612345 1234567123456 123456781234567 12345678912345678 1234567890123456789 123456789011234567890 12345678901212345678901 123456789011234567890 1234567890123456789 12345678912345678 123456781234567 1234567123456 12345612345 123451234 1234123 12312 121 1 1 121 12312 1234123 123451234 12345612345 1234567123456 123456781234567 12345678912345678 1234567890123456789 123456789011234567890 12345678901212345678901 1234567890123123456789012 12345678901212345678901 123456789011234567890 1234567890123456789 12345678912345678 123456781234567 1234567123456 12345612345 123451234 1234123 12312 121 1 USER>
go to post Julius Kavay · Jan 10, 2021 Maybe there are shorter solutions, but somebody must start the game... (I hope, class- and method name does not count) Class DC.CodeGolf Extends %RegisteredObject { /// Diamonds from 1 thru 9 (max) ClassMethod Diamond9(n) { f n=1:1:n f i=1:1:n-1,n,n-1:-1:1 {s a=$e(1234567890,1,i-1) w ?n-i,a,i,$re(a),!} w ! } /// Diamonds from 1 thru 16 (max) ClassMethod Diamond16(n) { f n=1:1:n f i=1:1:n-1,n,n-1:-1:1 {s a=$e("1234567890abcdef",1,i) w ?n-i,a,$re($e(a,1,*-1)),!} w ! } }
go to post Julius Kavay · Dec 31, 2020 If your input (date and time) format is the same as the example you provided, set inpDateTime = "12/10/2019 21:41" then use this one: write $tr($zdt($zdth(inpDateTime,1,2),8,1),": ") --> 20191210214100 and if you want it "a little bit faster", the try this one write $tr("abcdefghijkl00","ef/gh/abcd ij:kl",inpDateTime) --> 20191210214100 and you will get a speed gain of over 33% Happy New Year! (But this time, without Covid-19, if possible!)
go to post Julius Kavay · Dec 9, 2020 SystemAdministration-->Configuration-->NationalLanguageSettings-->Defaults/Defs/Imp/Exp First you have to start with a predefined/default table, copy under a new name, select this new table and click on the properties.
go to post Julius Kavay · Dec 9, 2020 To make things clear, the mentioned popup message should be seen by someone, who is (most of the time) working on the servers console. Is it so? Or you want to popup this message on an arbitrary desktop, where a user works? If I need to send a message to a user, either I send an email or I activate a popup message in my client (I have a very special client-UI). By the way, you wrote, I quote "an email is NOT a realistic expectation and far from reliable". Today, (almost) everybody has a smartphone and I think, if somebody does not read an email, he/she won't read thos popup messages either. Of course, you should send short plain text messages and not those fancy bloated colorful emails. So, a way to a solution... you could write a small program (C++, VB, Delphi, etc.) which is started after user login. The program should listen on a TCP port for messages from an arbitrary Cache/Iris (possibly background) application. If such a message arrives, this helper program changes to foreground, displays the message with or without an OK button. That's it.
go to post Julius Kavay · Dec 9, 2020 Store only hashed passwords... that's all. Class DC.MyUsers Extends %Persistent { Property Name As %String; Property Password As %String; Property passHash As %String [ Internal, Private, ReadOnly ]; Property passSalt As %String [ Internal, Private, ReadOnly ]; Parameter ITER = 1024; Parameter LENGTH = 20; Method PassCheck(psw) As %Boolean { set salt = $system.Encryption.Base64Decode(..passSalt) set hash = $system.Encryption.Base64Decode(..passHash) quit $system.Encryption.PBKDF2(psw, ..#ITER, salt, ..#LENGTH)=hash } Method PasswordSet(psw) As %Status { // optionally, quality/requirement-check if '..pswQuality(psw) quit $$Error^%apiOBJ(5001,"Poor password quality") set salt=$system.Encryption.GenCryptRand(8) set hash=$system.Encryption.PBKDF2(psw, ..#ITER, salt, ..#LENGTH) set i%passHash=$system.Encryption.Base64Encode(hash) set i%passSalt=$system.Encryption.Base64Encode(salt) quit $$$OK } Method pswQuality(psw) As %Boolean { quit 1 } }
go to post Julius Kavay · Dec 9, 2020 There are two points, the first (catchwords: server, interaction) was already answered by Dmitriy Maslennikov the second is your 10 second popup button. In my over 40 years of IT-experience, there is one thing (along with others) I have learnd, is: every timeout is wrong, but messages with timeouts are evil! Whatever time you use, it's either too short or too long. Imagine, the phone is ringing abd the user has a hot 20 minute discussion on the phone, in the meantime, your popups comes and goes! Unseen! Sometimes several times! The only resonable solutions are, - if the message is (just) informative and the message text never changes, then put it into a logfile and show nothing. If the message text is a variable text ("Data is saved" vs. "Can't save: No disk space available") then do the popup with one button (or textinput), see below, but DO NOT use timeouts! - if the situation allows the user to choose between multiple answers, then let the popup window with those OK, YES, NO, CANCEL, etc. buttons stay there, as long as the user chooses one of them, or as an alternative (application dependent), offer an ordinary text input and at sometime the user types the answer and pushes the enter key. Messages with (possible with short) timeouts requires a user all the time gazing on the display - which you can't expect. justmy2cents
go to post Julius Kavay · Dec 5, 2020 Just in addition to what Robert wrote, Mumps has the concept of multithreading for over 50 years! Long before C++ and Java was born. justmy2cents
go to post Julius Kavay · Dec 4, 2020 Instead of inserting debug_macros, try Intersystems TRACE utility. write $$DIR^TRACE("c:\Temp") ; to set an output directory write $$ON^TRACE(jobnr) ; the pid of the process you want to trace ; zn "appNamespace" ; do ^yourProgram ; zn "%SYS" write $$OFF^TRACE(jobnr) ; to stopp the trace do ^TRACE ; to display the trace result TRACE displays the function-/method-calls with arguments.
go to post Julius Kavay · Nov 30, 2020 I said nothing about a documentation. I don't do it even By the way, what's the definition of an empty set? Answer: 4(%@3%4@')6%.@"9@).4%23%#4)/.@/&@-5-03@02/'2!-%23@!.$@4(%)2@$/#5-%.4!4)/.
go to post Julius Kavay · Nov 30, 2020 A internet search engine can be of great help and, of course, some luck, Carefully reading the DC is also a good source of information, See this articles https://community.intersystems.com/post/yet-another-use-case-translate-d... https://community.intersystems.com/post/convert-numeric-expression202010... (last reply)
go to post Julius Kavay · Nov 24, 2020 After seeing several solutions I got the idea to make a comparison.The bottom line is, it's advisable to check how an algorithm (or function or method etc.) performs over another.So try the below program snippet... you will be surprised! Test // s date="20201121090000" s new="" s t0=$zh f i=1:1:1E6 s new=$e(date,1,4)_"-"_$e(date,5,6)_"-"_$e(date,7,8)_" "_$e(date,9,10)_":"_$e(date,11,12)_":"_$e(date,13,14) s t1=$zh f i=1:1:1E6 s new=$tr("abcd-ef-gh ij:kl:mn","abcdefghijklmn",date) s t2=$zh f i=1:1:1E6 s new=$zd($zdh($e(date,1,8),8),3)_" "_$e(date,9,10)_":"_$e(date,11,12)_":"_$e(date,13,14) s t3=$zh f i=1:1:1E6 s new=$system.SQL.TOTIMESTAMP(date, "YYYYMMDDHHMISS") s t4=$zh f i=1:1:1E6 &SQL(SELECT TO_TIMESTAMP(:date,'YYYYMMDDHHMISS') INTO :new) s t5=$zh w "$e() only",?12,t1-t0,! w "$tr()",?12,t2-t1,! w "$e()+$zd()",?12,t3-t2,! w "SQL/class",?12,t4-t3,! w "SQL/static",?12,t5-t4,! q Of course, the results will depend on hardware, on Cache/IRIS version and on utilisation of your system
go to post Julius Kavay · Nov 24, 2020 Use $tr() in backward mode set date=" 20201121090000" write $tr("abcd-ef-gh ij:kl:mn","abcdefghijklmn",date) --> 2020-11-21 09:00:00