Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ' #INDEX# =======================================================================================================================
- ' Title .........: Akk
- ' Description ...: Dartmouth DTSS TeleBASIC BBS
- ' Author(s) .....: Searinox, props to underwood and devon, i used and learned some things from your code
- ' ===============================================================================================================================
- ' #CURRENT# =====================================================================================================================
- '
- ' ===============================================================================================================================
- ' #INTERNAL_USE_ONLY# ===========================================================================================================
- '
- ' ===============================================================================================================================
- <main> '
- goto <init>
- clear : end
- <>
- <init> '
- print "init ";arg$
- initArg = 0
- prompt$ = user$+"@akk:~$"
- debug% = 0
- initTimer% = timer
- port$ = str$(port%)
- 'ANSI Escape Sequences
- E$ = chr$(27) \ Esc$ = E$ 'Escape char
- SGR0$ = E$ + "[0m"'\ Modesoff$ = SGR0$ 'Turn off character attributes
- SGR1$ = E$ + "[1m" \ Bold$ = SGR1$ 'Turn bold mode on
- SGR2$ = E$ + "[2m" \ Lowint$ = SGR2$ 'Turn low intensity mode on
- SGR4$ = E$ + "[4m" \ Underline$ = SGR4$ 'Turn underline mode on
- SGR5$ = E$ + "[5m" \ Blink$ = SGR5$ 'Turn blinking mode on
- SGR7$ = E$ + "[7m" \ Reverse$ = SGR7$ 'Turn reverse video on
- SGR8$ = E$ + "[8m" \ Invisible$ = SGR8$ 'Turn invisible text mode on
- SGR27$ = E$ + "[27m" 'Turn reverse video off
- EL0$ = E$ + "[0K" \ Cleareol$ = EL0$ 'Clear line from cursor right
- EL1$ = E$ + "[1K" \ Clearbol$ = EL1$ 'Clear line from cursor left
- EL2$ = E$ + "[2K" \ Clearline$ = EL2$ 'Clear entire line
- gosub <initArray>
- gosub <initColor>
- gosub <initDebug>
- gosub <initFile>
- gosub <initMath>
- gosub <initMisc>
- gosub <initString>
- gosub <initTime>
- gosub <initUa>
- if len(arg$) then goto <initArg>
- goto <initBbs>
- <>
- ' #ARRAY# =======================================================================================================================
- <initArray> '
- return
- <>
- 'sort ELEMENTS of an array, descending (bubble-sort)
- ' call: A(n)= array, F= 1st position, L= last position, D= descending order, S= string sort
- ' exit: A(n)= sorted, descending, positions F thru L
- ' temp: I= Incr, J= Incr, swapped%
- <bubbleSort> '
- for I = F to L - 1
- swapped% = 0
- for J = F to L - I - 1
- if S = 1 and uaRowsSort$(J + D) > uaRowsSort$(J + (D = 0)) then gosub <bubbleSortSwap>
- if S = 0 and val(uaRowsSort$(J + D)) > val(uaRowsSort$(J + (D = 0))) then gosub <bubbleSortSwap>
- next J
- if swapped% = 0 then J = L - I - 1
- next I
- return
- <>
- <bubbleSortSwap> '
- swapTmp$ = uaRowsSort$(J)
- uaRowsSort$(J) = uaRowsSort$(J + 1)
- uaRowsSort$(J + 1) = swapTmp$
- swapTmp$ = uaRows$(J)
- uaRows$(J) = uaRows$(J + 1)
- uaRows$(J + 1) = swapTmp$
- swapped% = 1
- return
- <>
- ' ===============================================================================================================================
- ' #COLOR# =======================================================================================================================
- <initColor> '
- dim color$(1)
- data 0, black, 1, red , 2, green, 3, yellow
- data 4, blue , 5, magenta, 6, cyan , 7, white
- color$("len") = str$(7)
- for colorIdx% = 0 to color$("len")
- read colorNum%, colorName$
- color$(colorName$) = str$(colorNum%)
- color$(colorNum%) = colorName$
- next colorIdx%
- def fnFgColor(aColor$) = E$ + "[38;5;" + color$(aColor$) + "m"
- def fnBgColor(aColor$) = E$ + "[48;5;" + color$(aColor$) + "m"
- return
- <>
- ' ===============================================================================================================================
- ' #DEBUG# =======================================================================================================================
- <initDebug> '
- def fnAssert(x$,y$,t$)=fn_Assert(t$,(x$<>y$),fnFgColor("red"))
- def fn_Assert(t$,c%,f$)=mid$(f$,1,c%*len(f$))+t$+" '"+x$+"'='"+y$+"'"+SGR0$
- return
- <>
- <cmdDebug> '
- debug% = not debug%
- print "Debugging "+fnIf$(debug%, "on ", "off")+" (debug="+str$(debug%)+")."
- cmdExec = 1 : return
- <>
- ' ===============================================================================================================================
- ' #FILE# ========================================================================================================================
- <initFile> '
- dim aFile$(1)
- writeFileName$ = "_writeTest.txt"
- return
- <>
- <cmdDir> '
- print "cmdDir"
- print dir$
- cmdExec = 1 : return
- <>
- <readFile> '
- rfIdx% = 1 : rfChr% = 0
- open pFileName$, as #1
- for rfW% = 0 to 1 : rfW% = 0
- read #1, rfIdx%; aFile$(pFileName$, rfIdx%) : sleep 0
- rfChr% = rfChr% + len(aFile$(pFileName$, rfIdx%))
- rfIdx% = rfIdx% + 1
- if eof(1) = -1 then rfW% = 1 : rfIdx% = rfIdx% - 1
- next rfW%
- close #1
- aFile$(pFileName$, "len") = str$(rfIdx%)
- aFile$(pFileName$, "size") = str$(rfIdx% + rfChr%)
- return
- <>
- <readFileTest> '
- pFileName$ = "telehack.txt"
- gosub <readFile>
- for ln% = 1 to aFile$(pFileName$, "len")
- print str$(ln%), aFile$(pFileName$, ln%) : sleep 0
- next ln%
- print "len:", aFile$(pFileName$, "len")
- print "size:", aFile$(pFileName$, "size")
- return
- <>
- <writeFile> '
- open writeFileName$, as #1
- print# 1, "writeText$"
- close #1
- cmdExec = 1 : return
- <>
- <appendFile> '
- open appendFileName$, as #1
- <appendFileLoop> '
- if eof(1) = -1 then goto <appendFileAppend>
- input# 1, dumpp$
- goto <appendFileLoop>
- <appendFileAppend> '
- print# 1, appendText$
- close #1
- cmdExec = 1 : return
- <>
- <printFile> '
- open printFileName$, as #1
- <printFile_loop> '
- if eof(1) = -1 then goto <pf_close_fd>
- input# 1, a$: print a$: sleep .05
- goto <printFile_loop>
- <pf_close_fd> '
- close #1
- return
- <>
- ' ===============================================================================================================================
- ' #MATH# ========================================================================================================================
- <initMath> '
- def fnMax(x%,y%)=(x%>=y%)*x% + (x%<y%)*y%
- def fnMin(x%,y%)=(x%<=y%)*x% + (x%>y%)*y%
- return
- <>
- <maxTest> '
- print fnMax(3, 3) : print fnMax(1, 3) : print fnMax(-1, -3)
- return
- <>
- <decStrToInt> '
- byte1% = 0 : byte2% = 0 : byte3% = 0 : byte4% = 0
- decStrToInt% = fnIf%(len(decStrToInt$), 0, -1)
- if decStrToInt% = -1 then return
- pArr$ = "decStrToInt" : pSplit$ = decStrToInt$ : pDelim$ = " " : gosub <split>
- for dstiIdx% = 0 to decStrToIntByte% - 1
- decStrToInt% = decStrToInt% + int(aSplit$(pArr$, dstiIdx%)) * 256 ^ dstiIdx%
- next dstiIdx%
- return
- <>
- ' ===============================================================================================================================
- ' #MISC# ========================================================================================================================
- <initMisc> '
- def fnIf%(c%,x%,y%)=(c%<>0)*x%+(c%=0)*y%
- def fnIf$(c%,x$,y$)=mid$(x$,1,(c%<>0)*len(x$))+mid$(y$,1,(c%=0)*len(y$))
- return
- <>
- ' ===============================================================================================================================
- ' #STRING# ======================================================================================================================
- <initString> '
- dim aSplit$(1)
- def fnFirstWord(s$)=mid$(s$, 1, instr(s$, " "))
- def fnLeftPad(c$,l%,p$)=string$(fnMax(l%-len(c$),0),fnIf$(len(p$)>0,mid$(p$,1,1)," "))+c$
- def fnRemLeft$(s$,n%)=right$(s$, len(s$) - n%)
- '/**
- ' * Replaces first occurrence of a substring of a string with a new substring.
- ' * @param {string} t$ The base string from which to remove.
- ' * @param {string} s$ The string to replace.
- ' * @param {string} r$ The replacement string.
- ' * @return {string} A copy of `t$` with `s$` replaced by
- ' * `r$` or the original string if nothing is replaced.
- ' * @temp p%= position, f%= found, g%= not found, l%= len text, m%= len search, n%= len replace
- ' * @temp w%= len left, x%= len middle, y%= pos right, z%= len right
- ' */
- def fnReplace(t$,s$,r$)=fn_Replace(t$,s$,r$,instr(t$,s$))
- def fn_Replace(t$,s$,r$,p%)=fn__Replace(t$,r$,p%,p%>-1,p%=-1,len(t$),len(s$),len(r$))
- def fn__Replace(t$,r$,p%,f%,g%,l%,m%,n%)=fn___Replace(t$,r$,f%*p%+g%*l%,f%*n%,f%*(1+p%+m%),f%*l%)
- def fn___Replace(t$,r$,w%,x%,y%,z%)=mid$(t$,1,w%)+mid$(r$,1,x%)+mid$(t$,(y%<>0)*y%+(y%=0),z%)
- return
- <>
- <leftPadTest> '
- test$ = "Padding an empty string to a length of 0 results in an empty string"
- print fnAssert(fnLeftPad("", 0, "X"), "", test$)
- test$ = "Padding a non-empty string to a shorter length results in the same string"
- print fnAssert(fnLeftPad("foobar", 3, "X"), "foobar", test$)
- test$ = "Padding a non-empty string to a negative length results in the same string"
- print fnAssert(fnLeftPad("foobar", -3, "X"), "foobar", test$)
- test$ = "Padding a non-empty string to its length results in the same string"
- print fnAssert(fnLeftPad("foobar", 6, "X"), "foobar", test$)
- test$ = "Padding to a longer length with a single character fills to the left"
- print fnAssert(fnLeftPad("foobar", 8, "X"), "XXfoobar", test$)
- test$ = "Padding to a longer length with surplus characters fills using only first"
- print fnAssert(fnLeftPad("foobar", 10, "XY"), "XXXXfoobar", test$)
- test$ = "Padding to a longer length with an empty string fills with space"
- print fnAssert(fnLeftPad("foobar", 8, ""), " foobar", test$)
- return
- <>
- <replaceTest> '
- print fnReplace("aaabbbccc", "zzz", "zzz")
- print fnReplace("aaabbbccc", "aaa", "zzz")
- print fnReplace("aaabbbccc", "bbb", "zzz")
- print fnReplace("aaabbbccc", "ccc", "zzz")
- print fnReplace("aaabbbccc", "", "zzz")
- print fnReplace("aaabbbccc", "", "")
- print fnReplace("", "z", "")
- print fnReplace("", "zz", "")
- print fnReplace("", "zzz", "")
- print fnReplace("", "", "z")
- print fnReplace("", "", "zz")
- print fnReplace("", "", "zzz")
- print fnReplace("", "z", "z")
- return
- <>
- 'Function to count uppercase, lowercase,
- 'special characters and numbers
- <count> '
- upper% = 0 : lower% = 0 : number% = 0 : special% = 0
- for I = 1 to len(aStr$)
- ch% = asc(mid$(aStr$, I, 1))
- gosub <countSub>
- next I
- return
- <>
- <countSub> '
- if ch% >= 65 and ch% <= 90 then upper% = upper% + 1 : return
- if ch% >= 97 and ch% <= 122 then lower% = lower% + 1 : return
- if ch% >= 48 and ch% <= 57 then number% = number% + 1 : return
- special% = special% + 1
- return
- <>
- <countTest> '
- aStr$ = "#GeeKs01fOr@gEEks07"
- gosub <count>
- print "Upper case letters : "+str$(upper%)
- print "Lower case letters : "+str$(lower%)
- print "Number : "+str$(number%)
- print "Special characters : "+str$(special%)
- return
- <>
- <replace> '
- if casesense% = 1 then srPos% = instr(srText$, srSearch$, startPos%)
- if casesense% = 0 then srPos% = instr(ups$(srText$), ups$(srSearch$), startPos%)
- if srPos% = -1 then srResult$ = srText$ : return
- srFirst$ = mid$(srText$, 1, srPos%)
- srLast$ = mid$(srText$, 1 + srPos% + len(srSearch$))
- srResult$ = srFirst$ + srReplace$ + srLast$
- return
- <>
- <replaceBat> '
- if casesense% = 1 then srPos% = instr(srText$, srSearch$, startPos%)
- if casesense% = 0 then srPos% = instr(ups$(srText$), ups$(srSearch$), startPos%)
- if srPos% = -1 then srResult$ = srText$ : return
- srFirst$ = mid$(srText$, 1, srPos%)
- srLast$ = mid$(srText$, srPos% + 1 + len(srSearch$))
- srResult$ = srFirst$+srReplace$+mid$(srText$,srPos%+1,len(srSearch$))+SGR0$+srLast$
- return
- <>
- <replaceAll> '
- startPos% = 0
- for wRa% = 0 to 1 : wRa% = 0
- gosub <replaceBat>
- if srPos% = -1 then wRa% = 1
- startPos% = len(srResult$) - len(srLast$)
- srText$ = srResult$
- next wRa%
- startPos% = 0
- return
- <>
- <split> '
- iSplit% = 1 : iSplitArr% = 0
- jSplit% = pos(pSplit$, pDelim$)
- aSplit$(pArr$, "len") = "0"
- if jSplit% = 0 then aSplit$(pArr$, iSplitArr%) = pSplit$ : return
- delimLen% = len(pDelim$)
- for wSplit% = 0 to 1 : wSplit% = 0
- aSplit$(pArr$, iSplitArr%) = mid$(pSplit$, iSplit%, jSplit% - iSplit%)
- iSplitArr% = iSplitArr% + 1
- jSplit% = jSplit% + delimLen% : iSplit% = jSplit%
- jSplit% = instr(pSplit$, pDelim$, jSplit%) + 1
- if jSplit% = 0 then wSplit% = 1 : aSplit$(pArr$, iSplitArr%) = mid$(pSplit$, iSplit%)
- next wSplit%
- aSplit$(pArr$, "len") = str$(iSplitArr%)
- return
- <>
- <splitTest> '
- pArr$ = "test1" : pSplit$ = "0,1,2,3,4" : pDelim$ = "," : gosub <split>
- gosub <splitTestSub>
- pArr$ = "test2" : pSplit$ = ", 0, 1, 2, 3, 4, " : pDelim$ = ", " : gosub <split>
- gosub <splitTestSub>
- pArr$ = "test3" : pSplit$ = "0,1,2,3,4," : pDelim$ = "X" : gosub <split>
- gosub <splitTestSub>
- pArr$ = "test4" : pSplit$ = dir$ : pDelim$ = " " : gosub <split>
- gosub <splitTestSub>
- return
- <>
- <splitTestSub> '
- print "splitTest: "+pArr$
- for stIdx% = 0 to aSplit$(pArr$, "len")
- print stIdx%, "'"+aSplit$(pArr$, stIdx%)+"'" : sleep 0
- next stIdx%
- <>
- <stringBetween> '
- err% = 0 : err$ = ""
- stringBetween$ = ""
- sbLeftPos% = instr(sbStr$, sbLeft$)
- sbRightPos% = instr(sbStr$, sbRight$, sbLeftPos% + 1)
- if sbLeftPos% = -1 then err% = 1 : err$ = "ERR sbLeftPos -1 " + sbLeft$ : return
- if sbRightPos% = -1 then err% = 2 : err$ = "ERR sbRightPos -1 " + sbRight$ : return
- if sbLeftPos% > sbRightPos% then err% = 3 : err$ = "ERR sbLeftPos% > sbRightPos% " + str$(sbLeftPos%) + " " + str$(sbRightPos%) + " " + sbLeft$ + " " + sbRight$: return
- sbStart% = sbLeftPos% + 1 + len(sbLeft$)
- sbLen% = sbRightPos% - sbStart%
- stringBetween$ = mid$(sbStr$, sbStart%, sbLen% + 1)
- return
- <>
- <strToDecStr> '
- strToDecStr$ = ""
- for i = 1 to len(inputText$)
- strToDecStr$ = strToDecStr$ + str$(asc(mid$(inputText$, i, 1))) + " "
- next i
- return
- <>
- ' ===============================================================================================================================
- ' #TIME# ========================================================================================================================
- <initTime> '
- dim days_in_month$(1) : days_in_month("len") = 11
- data 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29
- for dimIdx% = 0 to days_in_month("len")
- read days_in_month(dimIdx%)
- next dimIdx%
- return
- <>
- <runTime> '
- runTime% = timer - initTimer% : runTime$ = str$(runTime%)
- return
- <>
- <tsToDateTime> '
- UnixTimeToHuman% = tsToDateTime%
- gosub <UnixTimeToHuman>
- tm_year$ = str$(tm_year)
- tm_mon$ = fnLeftPad(str$(tm_mon), 2, "0")
- tm_mday$ = fnLeftPad(str$(tm_mday), 2, "0")
- tm_hour$ = fnLeftPad(str$(tm_hour), 2, "0")
- tm_min$ = fnLeftPad(str$(tm_min), 2, "0")
- tm_sec$ = fnLeftPad(str$(tm_sec), 2, "0")
- tsToDateTime$ = tm_year$+"-"+tm_mon$+"-"+tm_mday$+" "+tm_hour$+":"+tm_min$+":"+tm_sec$
- return
- <>
- <UnixTimeToHuman> ' Unix Time to Human Time
- ' https://github.com/telnet23/bas/blob/master/unix-to-human.bas
- t = UnixTimeToHuman%
- ' https://git.musl-libc.org/cgit/musl/tree/src/time/__secs_to_tm.c
- leapoch = (946684800 + 86400 * (31 + 29))
- days_per_400y = (365 * 400 + 97)
- days_per_100y = (365 * 100 + 24)
- days_per_4y = (365 * 4 + 1)
- secs = t - leapoch
- days = int(secs / 86400)
- remsecs = secs mod 86400
- if remsecs < 0 then remsecs = remsecs + 86400 : days = days - 1
- wday = (3 + days) mod 7
- if wday < 0 then wday = wday + 7
- qc_cycles = int(days / days_per_400y)
- remdays = days mod days_per_400y
- if remdays < 0 then remdays = remdays + days_per_400y : qc_cycles = qc_cycles - 1
- c_cycles = int(remdays / days_per_100y)
- if c_cycles = 4 then c_cycles = c_cycles - 1
- remdays = remdays - c_cycles * days_per_100y
- q_cycles = int(remdays / days_per_4y)
- if q_cycles = 25 then q_cycles = q_cycles - 1
- remdays = remdays - q_cycles * days_per_4y
- remyears = int(remdays / 365)
- if remyears = 4 then remyears = remyears - 1
- remdays = remdays - remyears * 365
- leap = not remyears and (q_cycles or not c_cycles)
- yday = remdays + 31 + 28 + leap
- if yday >= 365 + leap then yday = yday - (365 + leap)
- years = remyears + 4 * q_cycles + 100 * c_cycles + 400 * qc_cycles
- months = 0
- <9470> '
- if days_in_month(months) > remdays then goto <9510>
- remdays = remdays - days_in_month(months)
- months = months + 1
- goto <9470>
- <9510> '
- tm_year = years + 100
- tm_mon = months + 2
- if tm_mon >= 12 then tm_mon = tm_mon - 12 : tm_year = tm_year + 1
- tm_mday = remdays + 1
- tm_wday = wday
- tm_yday = yday
- tm_hour = int(remsecs / 3600)
- tm_min = int(remsecs / 60) mod 60
- tm_sec = remsecs mod 60
- tm_mon = tm_mon + 1 ' not in musl
- tm_year = 1970 + int(t / 31557600) ' not in musl
- ' print "Year", tm_year
- ' print "Month", tm_mon
- ' print "Day", tm_mday
- ' print "Day of Week", tm_wday
- ' print "Day of Year", tm_yday
- ' print "Hour", tm_hour
- ' print "Minute", tm_min
- ' print "Second", tm_sec
- return
- <>
- 0 ' #INDEX# =======================================================================================================================
- 1 ' Title .........: Akk
- 2 ' Description ...: Dartmouth DTSS TeleBASIC BBS
- 3 ' Author(s) .....: Searinox, props to underwood and devon, i used and learned some things from your code
- 4 ' ===============================================================================================================================
- 5 ' #CURRENT# =====================================================================================================================
- 6 '
- 7 ' ===============================================================================================================================
- 8 ' #INTERNAL_USE_ONLY# ===========================================================================================================
- 9 '
- 10 ' ===============================================================================================================================
- 11 '
- 12 goto 14
- 13 clear : end
- 14 '
- 15 print "init ";arg$
- 16 initArg = 0
- 17 prompt$ = user$+"@akk:~$"
- 18 debug% = 0
- 19 initTimer% = timer
- 20 port$ = str$(port%)
- 21 'ANSI Escape Sequences
- 22 E$ = chr$(27) \ Esc$ = E$ 'Escape char
- 23 SGR0$ = E$ + "[0m"'\ Modesoff$ = SGR0$ 'Turn off character attributes
- 24 SGR1$ = E$ + "[1m" \ Bold$ = SGR1$ 'Turn bold mode on
- 25 SGR2$ = E$ + "[2m" \ Lowint$ = SGR2$ 'Turn low intensity mode on
- 26 SGR4$ = E$ + "[4m" \ Underline$ = SGR4$ 'Turn underline mode on
- 27 SGR5$ = E$ + "[5m" \ Blink$ = SGR5$ 'Turn blinking mode on
- 28 SGR7$ = E$ + "[7m" \ Reverse$ = SGR7$ 'Turn reverse video on
- 29 SGR8$ = E$ + "[8m" \ Invisible$ = SGR8$ 'Turn invisible text mode on
- 30 SGR27$ = E$ + "[27m" 'Turn reverse video off
- 31
- 32 EL0$ = E$ + "[0K" \ Cleareol$ = EL0$ 'Clear line from cursor right
- 33 EL1$ = E$ + "[1K" \ Clearbol$ = EL1$ 'Clear line from cursor left
- 34 EL2$ = E$ + "[2K" \ Clearline$ = EL2$ 'Clear entire line
- 35 gosub 47
- 36 gosub 75
- 37 gosub 90
- 38 gosub 100
- 39 gosub 156
- 40 gosub 174
- 41 gosub 180
- 42 gosub 330
- 43 gosub 588
- 44 if len(arg$) then goto 411
- 45 goto 417
- 46 ' #ARRAY# =======================================================================================================================
- 47 '
- 48 return
- 49 'sort ELEMENTS of an array, descending (bubble-sort)
- 50 ' call: A(n)= array, F= 1st position, L= last position, D= descending order, S= string sort
- 51 ' exit: A(n)= sorted, descending, positions F thru L
- 52 ' temp: I= Incr, J= Incr, swapped%
- 53 '
- 54 for I = F to L - 1
- 55 swapped% = 0
- 56 for J = F to L - I - 1
- 57 if S = 1 and uaRowsSort$(J + D) > uaRowsSort$(J + (D = 0)) then gosub 63
- 58 if S = 0 and val(uaRowsSort$(J + D)) > val(uaRowsSort$(J + (D = 0))) then gosub 63
- 59 next J
- 60 if swapped% = 0 then J = L - I - 1
- 61 next I
- 62 return
- 63 '
- 64 swapTmp$ = uaRowsSort$(J)
- 65 uaRowsSort$(J) = uaRowsSort$(J + 1)
- 66 uaRowsSort$(J + 1) = swapTmp$
- 67 swapTmp$ = uaRows$(J)
- 68 uaRows$(J) = uaRows$(J + 1)
- 69 uaRows$(J + 1) = swapTmp$
- 70
- 71 swapped% = 1
- 72 return
- 73 ' ===============================================================================================================================
- 74 ' #COLOR# =======================================================================================================================
- 75 '
- 76 dim color$(1)
- 77 data 0, black, 1, red , 2, green, 3, yellow
- 78 data 4, blue , 5, magenta, 6, cyan , 7, white
- 79 color$("len") = str$(7)
- 80 for colorIdx% = 0 to color$("len")
- 81 read colorNum%, colorName$
- 82 color$(colorName$) = str$(colorNum%)
- 83 color$(colorNum%) = colorName$
- 84 next colorIdx%
- 85 def fnFgColor(aColor$) = E$ + "[38;5;" + color$(aColor$) + "m"
- 86 def fnBgColor(aColor$) = E$ + "[48;5;" + color$(aColor$) + "m"
- 87 return
- 88 ' ===============================================================================================================================
- 89 ' #DEBUG# =======================================================================================================================
- 90 '
- 91 def fnAssert(x$,y$,t$)=fn_Assert(t$,(x$<>y$),fnFgColor("red"))
- 92 def fn_Assert(t$,c%,f$)=mid$(f$,1,c%*len(f$))+t$+" '"+x$+"'='"+y$+"'"+SGR0$
- 93 return
- 94 '
- 95 debug% = not debug%
- 96 print "Debugging "+fnIf$(debug%, "on ", "off")+" (debug="+str$(debug%)+")."
- 97 cmdExec = 1 : return
- 98 ' ===============================================================================================================================
- 99 ' #FILE# ========================================================================================================================
- 100 '
- 101 dim aFile$(1)
- 102 writeFileName$ = "_writeTest.txt"
- 103 return
- 104 '
- 105 print "cmdDir"
- 106 print dir$
- 107 cmdExec = 1 : return
- 108 '
- 109 rfIdx% = 1 : rfChr% = 0
- 110 open pFileName$, as #1
- 111 for rfW% = 0 to 1 : rfW% = 0
- 112 read #1, rfIdx%; aFile$(pFileName$, rfIdx%) : sleep 0
- 113 rfChr% = rfChr% + len(aFile$(pFileName$, rfIdx%))
- 114 rfIdx% = rfIdx% + 1
- 115 if eof(1) = -1 then rfW% = 1 : rfIdx% = rfIdx% - 1
- 116 next rfW%
- 117 close #1
- 118 aFile$(pFileName$, "len") = str$(rfIdx%)
- 119 aFile$(pFileName$, "size") = str$(rfIdx% + rfChr%)
- 120 return
- 121 '
- 122 pFileName$ = "telehack.txt"
- 123 gosub 108
- 124 for ln% = 1 to aFile$(pFileName$, "len")
- 125 print str$(ln%), aFile$(pFileName$, ln%) : sleep 0
- 126 next ln%
- 127 print "len:", aFile$(pFileName$, "len")
- 128 print "size:", aFile$(pFileName$, "size")
- 129 return
- 130 '
- 131 open writeFileName$, as #1
- 132 print# 1, "writeText$"
- 133 close #1
- 134 cmdExec = 1 : return
- 135 '
- 136 open appendFileName$, as #1
- 137 '
- 138 if eof(1) = -1 then goto 141
- 139 input# 1, dumpp$
- 140 goto 137
- 141 '
- 142 print# 1, appendText$
- 143 close #1
- 144 cmdExec = 1 : return
- 145 '
- 146 open printFileName$, as #1
- 147 '
- 148 if eof(1) = -1 then goto 151
- 149 input# 1, a$: print a$: sleep .05
- 150 goto 147
- 151 '
- 152 close #1
- 153 return
- 154 ' ===============================================================================================================================
- 155 ' #MATH# ========================================================================================================================
- 156 '
- 157 def fnMax(x%,y%)=(x%>=y%)*x% + (x%<y%)*y%
- 158 def fnMin(x%,y%)=(x%<=y%)*x% + (x%>y%)*y%
- 159 return
- 160 '
- 161 print fnMax(3, 3) : print fnMax(1, 3) : print fnMax(-1, -3)
- 162 return
- 163 '
- 164 byte1% = 0 : byte2% = 0 : byte3% = 0 : byte4% = 0
- 165 decStrToInt% = fnIf%(len(decStrToInt$), 0, -1)
- 166 if decStrToInt% = -1 then return
- 167 pArr$ = "decStrToInt" : pSplit$ = decStrToInt$ : pDelim$ = " " : gosub 280
- 168 for dstiIdx% = 0 to decStrToIntByte% - 1
- 169 decStrToInt% = decStrToInt% + int(aSplit$(pArr$, dstiIdx%)) * 256 ^ dstiIdx%
- 170 next dstiIdx%
- 171 return
- 172 ' ===============================================================================================================================
- 173 ' #MISC# ========================================================================================================================
- 174 '
- 175 def fnIf%(c%,x%,y%)=(c%<>0)*x%+(c%=0)*y%
- 176 def fnIf$(c%,x$,y$)=mid$(x$,1,(c%<>0)*len(x$))+mid$(y$,1,(c%=0)*len(y$))
- 177 return
- 178 ' ===============================================================================================================================
- 179 ' #STRING# ======================================================================================================================
- 180 '
- 181 dim aSplit$(1)
- 182 def fnFirstWord(s$)=mid$(s$, 1, instr(s$, " "))
- 183 def fnLeftPad(c$,l%,p$)=string$(fnMax(l%-len(c$),0),fnIf$(len(p$)>0,mid$(p$,1,1)," "))+c$
- 184 def fnRemLeft$(s$,n%)=right$(s$, len(s$) - n%)
- 185 '/**
- 186 ' * Replaces first occurrence of a substring of a string with a new substring.
- 187 ' * @param {string} t$ The base string from which to remove.
- 188 ' * @param {string} s$ The string to replace.
- 189 ' * @param {string} r$ The replacement string.
- 190 ' * @return {string} A copy of `t$` with `s$` replaced by
- 191 ' * `r$` or the original string if nothing is replaced.
- 192 ' * @temp p%= position, f%= found, g%= not found, l%= len text, m%= len search, n%= len replace
- 193 ' * @temp w%= len left, x%= len middle, y%= pos right, z%= len right
- 194 ' */
- 195 def fnReplace(t$,s$,r$)=fn_Replace(t$,s$,r$,instr(t$,s$))
- 196 def fn_Replace(t$,s$,r$,p%)=fn__Replace(t$,r$,p%,p%>-1,p%=-1,len(t$),len(s$),len(r$))
- 197 def fn__Replace(t$,r$,p%,f%,g%,l%,m%,n%)=fn___Replace(t$,r$,f%*p%+g%*l%,f%*n%,f%*(1+p%+m%),f%*l%)
- 198 def fn___Replace(t$,r$,w%,x%,y%,z%)=mid$(t$,1,w%)+mid$(r$,1,x%)+mid$(t$,(y%<>0)*y%+(y%=0),z%)
- 199 return
- 200 '
- 201 test$ = "Padding an empty string to a length of 0 results in an empty string"
- 202 print fnAssert(fnLeftPad("", 0, "X"), "", test$)
- 203 test$ = "Padding a non-empty string to a shorter length results in the same string"
- 204 print fnAssert(fnLeftPad("foobar", 3, "X"), "foobar", test$)
- 205 test$ = "Padding a non-empty string to a negative length results in the same string"
- 206 print fnAssert(fnLeftPad("foobar", -3, "X"), "foobar", test$)
- 207 test$ = "Padding a non-empty string to its length results in the same string"
- 208 print fnAssert(fnLeftPad("foobar", 6, "X"), "foobar", test$)
- 209 test$ = "Padding to a longer length with a single character fills to the left"
- 210 print fnAssert(fnLeftPad("foobar", 8, "X"), "XXfoobar", test$)
- 211 test$ = "Padding to a longer length with surplus characters fills using only first"
- 212 print fnAssert(fnLeftPad("foobar", 10, "XY"), "XXXXfoobar", test$)
- 213 test$ = "Padding to a longer length with an empty string fills with space"
- 214 print fnAssert(fnLeftPad("foobar", 8, ""), " foobar", test$)
- 215 return
- 216 '
- 217 print fnReplace("aaabbbccc", "zzz", "zzz")
- 218 print fnReplace("aaabbbccc", "aaa", "zzz")
- 219 print fnReplace("aaabbbccc", "bbb", "zzz")
- 220 print fnReplace("aaabbbccc", "ccc", "zzz")
- 221 print fnReplace("aaabbbccc", "", "zzz")
- 222 print fnReplace("aaabbbccc", "", "")
- 223 print fnReplace("", "z", "")
- 224 print fnReplace("", "zz", "")
- 225 print fnReplace("", "zzz", "")
- 226 print fnReplace("", "", "z")
- 227 print fnReplace("", "", "zz")
- 228 print fnReplace("", "", "zzz")
- 229 print fnReplace("", "z", "z")
- 230 return
- 231 'Function to count uppercase, lowercase,
- 232 'special characters and numbers
- 233 '
- 234 upper% = 0 : lower% = 0 : number% = 0 : special% = 0
- 235 for I = 1 to len(aStr$)
- 236 ch% = asc(mid$(aStr$, I, 1))
- 237 gosub 240
- 238 next I
- 239 return
- 240 '
- 241 if ch% >= 65 and ch% <= 90 then upper% = upper% + 1 : return
- 242 if ch% >= 97 and ch% <= 122 then lower% = lower% + 1 : return
- 243 if ch% >= 48 and ch% <= 57 then number% = number% + 1 : return
- 244 special% = special% + 1
- 245 return
- 246 '
- 247 aStr$ = "#GeeKs01fOr@gEEks07"
- 248 gosub 233
- 249 print "Upper case letters : "+str$(upper%)
- 250 print "Lower case letters : "+str$(lower%)
- 251 print "Number : "+str$(number%)
- 252 print "Special characters : "+str$(special%)
- 253 return
- 254 '
- 255 if casesense% = 1 then srPos% = instr(srText$, srSearch$, startPos%)
- 256 if casesense% = 0 then srPos% = instr(ups$(srText$), ups$(srSearch$), startPos%)
- 257 if srPos% = -1 then srResult$ = srText$ : return
- 258 srFirst$ = mid$(srText$, 1, srPos%)
- 259 srLast$ = mid$(srText$, 1 + srPos% + len(srSearch$))
- 260 srResult$ = srFirst$ + srReplace$ + srLast$
- 261 return
- 262 '
- 263 if casesense% = 1 then srPos% = instr(srText$, srSearch$, startPos%)
- 264 if casesense% = 0 then srPos% = instr(ups$(srText$), ups$(srSearch$), startPos%)
- 265 if srPos% = -1 then srResult$ = srText$ : return
- 266 srFirst$ = mid$(srText$, 1, srPos%)
- 267 srLast$ = mid$(srText$, srPos% + 1 + len(srSearch$))
- 268 srResult$ = srFirst$+srReplace$+mid$(srText$,srPos%+1,len(srSearch$))+SGR0$+srLast$
- 269 return
- 270 '
- 271 startPos% = 0
- 272 for wRa% = 0 to 1 : wRa% = 0
- 273 gosub 262
- 274 if srPos% = -1 then wRa% = 1
- 275 startPos% = len(srResult$) - len(srLast$)
- 276 srText$ = srResult$
- 277 next wRa%
- 278 startPos% = 0
- 279 return
- 280 '
- 281 iSplit% = 1 : iSplitArr% = 0
- 282 jSplit% = pos(pSplit$, pDelim$)
- 283 aSplit$(pArr$, "len") = "0"
- 284 if jSplit% = 0 then aSplit$(pArr$, iSplitArr%) = pSplit$ : return
- 285 delimLen% = len(pDelim$)
- 286 for wSplit% = 0 to 1 : wSplit% = 0
- 287 aSplit$(pArr$, iSplitArr%) = mid$(pSplit$, iSplit%, jSplit% - iSplit%)
- 288 iSplitArr% = iSplitArr% + 1
- 289 jSplit% = jSplit% + delimLen% : iSplit% = jSplit%
- 290 jSplit% = instr(pSplit$, pDelim$, jSplit%) + 1
- 291 if jSplit% = 0 then wSplit% = 1 : aSplit$(pArr$, iSplitArr%) = mid$(pSplit$, iSplit%)
- 292 next wSplit%
- 293 aSplit$(pArr$, "len") = str$(iSplitArr%)
- 294 return
- 295 '
- 296 pArr$ = "test1" : pSplit$ = "0,1,2,3,4" : pDelim$ = "," : gosub 280
- 297 gosub 305
- 298 pArr$ = "test2" : pSplit$ = ", 0, 1, 2, 3, 4, " : pDelim$ = ", " : gosub 280
- 299 gosub 305
- 300 pArr$ = "test3" : pSplit$ = "0,1,2,3,4," : pDelim$ = "X" : gosub 280
- 301 gosub 305
- 302 pArr$ = "test4" : pSplit$ = dir$ : pDelim$ = " " : gosub 280
- 303 gosub 305
- 304 return
- 305 '
- 306 print "splitTest: "+pArr$
- 307 for stIdx% = 0 to aSplit$(pArr$, "len")
- 308 print stIdx%, "'"+aSplit$(pArr$, stIdx%)+"'" : sleep 0
- 309 next stIdx%
- 310 '
- 311 err% = 0 : err$ = ""
- 312 stringBetween$ = ""
- 313 sbLeftPos% = instr(sbStr$, sbLeft$)
- 314 sbRightPos% = instr(sbStr$, sbRight$, sbLeftPos% + 1)
- 315 if sbLeftPos% = -1 then err% = 1 : err$ = "ERR sbLeftPos -1 " + sbLeft$ : return
- 316 if sbRightPos% = -1 then err% = 2 : err$ = "ERR sbRightPos -1 " + sbRight$ : return
- 317 if sbLeftPos% > sbRightPos% then err% = 3 : err$ = "ERR sbLeftPos% > sbRightPos% " + str$(sbLeftPos%) + " " + str$(sbRightPos%) + " " + sbLeft$ + " " + sbRight$: return
- 318 sbStart% = sbLeftPos% + 1 + len(sbLeft$)
- 319 sbLen% = sbRightPos% - sbStart%
- 320 stringBetween$ = mid$(sbStr$, sbStart%, sbLen% + 1)
- 321 return
- 322 '
- 323 strToDecStr$ = ""
- 324 for i = 1 to len(inputText$)
- 325 strToDecStr$ = strToDecStr$ + str$(asc(mid$(inputText$, i, 1))) + " "
- 326 next i
- 327 return
- 328 ' ===============================================================================================================================
- 329 ' #TIME# ========================================================================================================================
- 330 '
- 331 dim days_in_month$(1) : days_in_month("len") = 11
- 332 data 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29
- 333 for dimIdx% = 0 to days_in_month("len")
- 334 read days_in_month(dimIdx%)
- 335 next dimIdx%
- 336 return
- 337 '
- 338 runTime% = timer - initTimer% : runTime$ = str$(runTime%)
- 339 return
- 340 '
- 341 UnixTimeToHuman% = tsToDateTime%
- 342 gosub 351
- 343 tm_year$ = str$(tm_year)
- 344 tm_mon$ = fnLeftPad(str$(tm_mon), 2, "0")
- 345 tm_mday$ = fnLeftPad(str$(tm_mday), 2, "0")
- 346 tm_hour$ = fnLeftPad(str$(tm_hour), 2, "0")
- 347 tm_min$ = fnLeftPad(str$(tm_min), 2, "0")
- 348 tm_sec$ = fnLeftPad(str$(tm_sec), 2, "0")
- 349 tsToDateTime$ = tm_year$+"-"+tm_mon$+"-"+tm_mday$+" "+tm_hour$+":"+tm_min$+":"+tm_sec$
- 350 return
- 351 ' Unix Time to Human Time
- 352 ' https://github.com/telnet23/bas/blob/master/unix-to-human.bas
- 353 t = UnixTimeToHuman%
- 354 ' https://git.musl-libc.org/cgit/musl/tree/src/time/__secs_to_tm.c
- 355 leapoch = (946684800 + 86400 * (31 + 29))
- 356 days_per_400y = (365 * 400 + 97)
- 357 days_per_100y = (365 * 100 + 24)
- 358 days_per_4y = (365 * 4 + 1)
- 359 secs = t - leapoch
- 360 days = int(secs / 86400)
- 361 remsecs = secs mod 86400
- 362 if remsecs < 0 then remsecs = remsecs + 86400 : days = days - 1
- 363 wday = (3 + days) mod 7
- 364 if wday < 0 then wday = wday + 7
- 365 qc_cycles = int(days / days_per_400y)
- 366 remdays = days mod days_per_400y
- 367 if remdays < 0 then remdays = remdays + days_per_400y : qc_cycles = qc_cycles - 1
- 368 c_cycles = int(remdays / days_per_100y)
- 369 if c_cycles = 4 then c_cycles = c_cycles - 1
- 370 remdays = remdays - c_cycles * days_per_100y
- 371 q_cycles = int(remdays / days_per_4y)
- 372 if q_cycles = 25 then q_cycles = q_cycles - 1
- 373 remdays = remdays - q_cycles * days_per_4y
- 374 remyears = int(remdays / 365)
- 375 if remyears = 4 then remyears = remyears - 1
- 376 remdays = remdays - remyears * 365
- 377 leap = not remyears and (q_cycles or not c_cycles)
- 378 yday = remdays + 31 + 28 + leap
- 379 if yday >= 365 + leap then yday = yday - (365 + leap)
- 380 years = remyears + 4 * q_cycles + 100 * c_cycles + 400 * qc_cycles
- 381 months = 0
- 382 '
- 383 if days_in_month(months) > remdays then goto 387
- 384 remdays = remdays - days_in_month(months)
- 385 months = months + 1
- 386 goto 382
- 387 '
- 388 tm_year = years + 100
- 389 tm_mon = months + 2
- 390 if tm_mon >= 12 then tm_mon = tm_mon - 12 : tm_year = tm_year + 1
- 391 tm_mday = remdays + 1
- 392 tm_wday = wday
- 393 tm_yday = yday
- 394 tm_hour = int(remsecs / 3600)
- 395 tm_min = int(remsecs / 60) mod 60
- 396 tm_sec = remsecs mod 60
- 397 tm_mon = tm_mon + 1 ' not in musl
- 398 tm_year = 1970 + int(t / 31557600) ' not in musl
- 399 ' print "Year", tm_year
- 400 ' print "Month", tm_mon
- 401 ' print "Day", tm_mday
- 402 ' print "Day of Week", tm_wday
- 403 ' print "Day of Year", tm_yday
- 404 ' print "Hour", tm_hour
- 405 ' print "Minute", tm_min
- 406 ' print "Second", tm_sec
- 407 return
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement