Πέμπτη 26 Σεπτεμβρίου 2019

Chess Board Example

This example use Unicode chess characters. Look the print screen, at the background of  these characters on the board. Normaly the color inside are the same as the font, because only the line of font drawing. So to have white inside pawns, we have to print the characters in white background using a non antialliasing printing (so we get black pixels for black colored characters), and we have to use flood fil in a pixel outside the chess character to fill the square with desired color.

for each board we feed a Forsyth–Edwards Notation (FEN) a string which define a board position.



Just copy this and paste to a module a empty code block.

Font "Arial Unicode MS"
if not Fontname$="Arial Unicode MS" then
font "DejaVu Sans"
End if
ChColor$=fontname$
Font "Verdana" : Cls 15 : Pen 0 : Form 40,32 : Gradient 3,5
Def White$="PNBRQK", Black$="pnbrqk", WhiteDisp$="♙♘♗♖♕♔"
Def BlackDisp$="♟♞♝♜♛♚", empty$="12345678"
Dim emptydisp$(1 to 8)
For i=1 to 8 :emptydisp$(i)=string$(" ",i):Next
Def board$, status$, oldI
Dim line$()
Double
OldI=Italic
Italic 1
Pen 14 {
Report 2, "Chess Board Example"
}
Italic OldI
Normal
SetBoard("rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq c6 0 2")
DrawBoard(1000, 2000, 600, 15)
SetBoard("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")
DrawBoard(11500, 2000, 300, 15)
SetBoard("rnbqkbnr/pp1ppppp/2p5/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")
DrawBoard(11500, 8000, 180, 15)
// wait for key
Push Key$
Drop
Cls
End
Sub DrawBoard(leftmargin, topmargin, squarewidth, labelcolor)
Refresh 10000
local boolean a=true, z=bold : bold 0
Local l=squarewidth, k=2*l, k1=k*.85, N1=6, N=6, M=4, B=k*8, B1
Local d=0
Repeat
N=N1
N1+=.25
Until K1<size.Y("A", "Arial", N1)
topmargin-=l
leftmargin-=l
move leftmargin+l,topmargin+l
B1=(l div 300)*twipsX
step -B1,-B1
B+=B1*2
Width b1 div 2+1 {
color #666688 , 1{
Polygon 0, B, 0, 0, B, -B, 0, 0, -B
}
}
M=N*.65
For i=1 to 9
d=leftmargin
move d, topmargin
if i<9 then
step 0, k
Pen labelcolor{Legend str$(9-i,""), "Arial", M,0,2}
step 0, -k
else
N=M
End if
For j=1 to 8
If i<9 then
step l, l
color #666688,1 {
fill k,k, 15
}
step -l, -l
\\ Last parameter is 0 For no antialliasing
Legend mid$(line$(i),j,1), chColor$, N, 0, 2,0
step l-twipsX*2, l-twipsX*2
if not a then floodfill ,,#666688 else floodfill , , #ccddff
a~
else
step k, k
pen labelcolor {
Legend mid$(line$(i),j,1), chColor$, N, 0, 2
}
End If
d+=k
move d, topmargin
Next
a~ : topmargin+=k
Next
bold z
Refresh 60
End Sub
Sub SetBoard(chessboard$)
board$=leftpart$(chessboard$," ")
status$=rightpart$(chessboard$," ")
nl$={
}
For i=1 to 6
board$=replace$(mid$(White$,i,1),mid$(WhiteDisp$,i,1), board$)
board$=replace$(mid$(Black$,i,1),mid$(BlackDisp$,i,1), board$)
Next
For j=1 to 8
board$=replace$(str$(j,""),emptydisp$(j), board$)
Next
line$()=piece$(board$,"/")
Dim line$(1 to 9)
line$(9)="abcdefgh"
End Sub

Και εδώ η εικόνα (Windows 10 Pro)











Τετάρτη 25 Σεπτεμβρίου 2019

Αναθεώρηση 46, Έκδοση 9.8

Διορθώσεις πάνω στις τελευταίες αλλαγές. Επίσης μπήκαν δυο νέα τμήματα στο info.gsb, το ένα κάνει εξαγωγή του ελληνικού κειμένου βοήθειας από τη βάση δεδομένων ή του αγγλικού (διαλέγουμε). Το ελληνικό κείμενο είναι πάνω από διακόσιες σελίδες Α4. Το δεύτερο τμήμα είναι ένα πρόγραμμα για να αλλάζουμε το κείμενο απευθείας στη βάση δεδομένων.

Τρίτη 24 Σεπτεμβρίου 2019

Ανάκτηση αρχείου σε αστοχία εκτέλεσης κατά την αποθήκευση.

Εδώ και πολύ καιρό προσπαθώ να βρω το bug που εμφανίζεται ως εξής:
Κατά το σώσιμο του προγράμματος όταν το πρόγραμμα υπάρχει ήδη μια φορά σωμένο, ανοίγει ένας διάλογος (msgbox) για να ρωτήσει αν θέλουμε να το σώσουμε ή όχι.  Ορισμένες φορές αντί να ανοίξει η φόρμα διαλόγου βγάζει πρόβλημα το σύστημα και ρίχνει το περιβάλλον.

Στην έκδοση 9.8 αναθεώρηση 45 δεν έχει βρεθεί ακόμα το bug (σχετίζεται με μια ασύγχρονη λειτουργία). Όμως έχει ξεπεραστεί το πρόβλημα με το σύστημα της πρόσκαιρης αποθήκευσης πριν την ερώτηση αν θέλουμε ή όχι να αποθηκεύσουμε πάνω στο παλιό.
Ισχύει ότι η αποθήκευση δημιουργεί ένα αρχείο τύπου bck για το παλιό αρχείο.

Πώς γίνεται η ανάκτηση:
Όταν λοιπόν πάμε να σώσουμε πρώτα σώνει το αρχείο με κατάληξη gsb1 και αν πέσει το σύστημα τότε: ανοίγουμε τον διερμηνευτή και φορτώνουμε το αρχείο, και το gsb1 αυτόματα μετονομάζεται με κατάληξη gsb. Στην ουσία αλλάζει τύπο στο gsb ως bck1 και γράφει το νέο στο gsb1 πριν το ερώτημα ώστε αν δηλώσουμε ότι δεν θέλουμε να γράψουμε στο αρχείο τότε το bck1 γίνεται πάλι gsb και διαγράφεται το gsb1.

Έχω προσπαθήσει να βρω το πρόβλημα χωρίς επιτυχία. Οι προσπάθειες συνεχίζονται. Σπάνια συμβαίνει αλλά.

Όταν με την Φόρτωση ή τη Load φορτώσουμε ένα αρχείο τότε αν αυτό υπάρχει το φορτώνει, αν όχι κοιτάει αν υπάρχει με κατάληξη gsb1 και αν ναι τότε πρώτα του αλλάζει τύπο σε gsb και μετά το φορτώνει.


Αναθεώρηση 45, Έκδοση 9.8

Εικόνα από την νέα έκδοση:


Σε αυτήν την αναθεώρηση:

1. Διορθώθηκε ο κώδικας εξαγωγής σε html, οπότε το </ γράφεται σωστά, και το βλέπουμε εδώ (είναι αντιγραφή κειμένου από τον htmleditor που υπάρχει στο info.gsb - υπάρχει στο setup).

<!DOCTYPE html>
<html lang = "en-US">
  <head>
    <meta charset = "UTF-8">
    <title>externalStyle.html</title>
    <link rel = "stylesheet"
          type = "text/css"
          href = "myStyle.css" />
  </head>
  <body>
    <h1>External Style</h1>
    <p>
      This page has styles set for paragraphs, body, and header 1.
    </p>
    <p>
      The styles are defined in an external style sheet.
    </p>
  </body>
</html>
2. Δυο νέες ιδιότητες για το EditBox. Η HighlighParagraph με τιμή True κάνει την παράγραφο που έχουμε το δρομέα να "φωτίζεται". Το χρώμα του φόντου για το "φώτισμα" το παίρνει από την HighlightColor.  Η χρώμα(0χ33, 0χ33, 0χ33) ή το #333333 δίνει αρνητικό νούμερο οπότε βάζουμε ένα - πριν για να δώσουμε τη θετική τιμή. Η Μ2000 χρησιμοποιεί τρία σετ χρωμάτων και τα ξεχωρίζει με τα πρόσημα και τη περιοχή τιμής: RGB σετ 0 έως -2^24-1, Windows Colors 0 to 15, και System Colors από 0χ80000000. Δεκαεξαδικά νούμερα γράφονται με 0χ ή 0x, ως αριθμοί χωρίς πρόσημο, και με τα & και % στο τέλος όταν έχουν πρόσημο για 32 και 16bit. Έτσι το 0χFFFF% είναι το -1 σε 16 bit. To #AABBCC (html χρώμα) είναι αυτό -0χCCBBAA, διότι το AA είναι στη θέση για το κόκκινο και γράφεται στη χαμηλή θέση στη μνήμη (little endian), άρα στο δεκαεξαδικό νούμερο θα είναι το πιο δεξιό κομμάτι. Αλλά σαν html χρώμα θέλουμε να βλέπουμε το RGB, δηλαδή το κόκκινο με τιμή 0χAA να είναι στα αριστερά.

Στην αναθεώρηση 44:

1. Αφαιρέθηκε ένα σφάλμα που έκανε τις φόρμες χρήστη να μην ανοίγουν από την γραμμή εργασιών (Task Bar), αν τις κάναμε minimized. (δεν άνοιγαν ούτε με ctrl-tab), μπορούσαν μόνο να κλείσουν από την taskbar.
2. Μεγάλη βελτίωση στους διορθωτές (τον βασικό πάνω στην κονσόλα της Μ2000, και το EditBox το στοιχείο ελέγχου για φόρμες χρήστη.
Οι φόρμες χρήση δουλεύουν με ένα βασικό στοιχείο ελέγχου και πάνω σε αυτό άλλα αντικείμενα του αλλάζουν την χρήση. Το βασικό είναι ένα list box. Αυτό γίνεται και επεξεργαστής κειμένου, με σύστημα για χρωματισμό κειμένου/κώδικα.
Σε αυτήν την αναθεώρηση μπήκε το Ctrl πάνω στα βελάκια ή στο delete ή στο Backspace (τα δυο τελευταία είδα ότι "άλλαξαν" αφού έφτιαξα το σύστημα για τα βελάκια. Με το ctrl και τα βελάκια αριστερά και δεξιά μετακινούμε το δρομέα βάσει του περιεχόμενου. Σκοπός είναι να μετακινούμε το δρομέα με ένα κλικ από το τέλος μιας λέξης μέχρι την αρχή της και το ανάποδο, καθώς και να περνάμε διαστήματα, είτε προς τα αριστερά είτε προς τα δεξιά. Επιπλέον σε παρενθέσεις και άλλα σύμβολα θέλουμε ξεχωριστή στάση. Μπορούμε να συνδυάσουμε και το SHIFT, ώστε να μαρκάρουμε κατά την μετακίνηση (μπορούσαμε και πριν, αλλά τώρα με πολύ γρήγορο τρόπο γιατί ο δρομέας με μια κίνηση πάει στην επόμενη στάση, όπως ορίζεται από την λογική του προγράμματος.

Επίσης με τα F2 και F3 (αναζήτηση προς την αρχή και προς το τέλος)  τώρα έχουν έναν εσωτερικό διακόπτη που αρχικά ορίζει η αναζήτηση να γίνεται με λέξεις. Για να αναζητήσουμε κάτι απλά το μαρκάρουμε στο κείμενο,. αν υπάρχει ήδη ή με τα shift και control επιλέγουμε την αναζήτηση βάσει ενός πεδίου εισαγωγής σε μια φόρμα διαλόγου. Με το Shift και το F2 ή F3 η αναζήτηση γίνεται με βάσει ότι δίνουμε, ακόμα και μέρος λέξης. Με το Ctrl και το F2 ή F3 η αναζήτηση γίνεται για μεταβλητές, και γενικά για ονόματα. Σε αυτήν την αναθεώρηση η χρήση των   F2 ή F3 ακολουθεί το τελευταίο  τρόπο αναζήτησης, ενώ ξεκινάει με αναζήτηση λέξεων.

Επίσης άλλη αλλαγή (που μερικώς είχε γίνει στο προηγούμενη αναθεώρηση) έγινε στο τρόπο 'απασχόλησης" του εγγράφου εντός του EditBox, ώστε σε περίπτωση αντικατάστασης λέξης ή γραμμάτων (F5 και shift F5) να μπορεί η φόρμα να χρησιμοποιείται (να παίρνει "γεγονότα"). Αυτό το έκανα με χρήση ενός ρολογιού υψηλής ανάλυσης, ανά αντικείμενο EditBox, όπου κατά την διάρκεια της επανάληψης της αναζήτησης ελέγχει το πρόγραμμα αν ένα χρονικό διάστημα έχει περάσει για να δώσει χρόνο στο σύστημα. Ενώ στον διορθωτή για την Μ2000 στην κονσόλα για μικρά κείμενα εμφανίζονται οι αλλαγές με διαδοχική κίνηση του κειμένου, στο EditoBox η αλλαγή γίνεται ακαριαία.

Και οι δυο κειμενογράφοι ΄(έχουν σε μεγάλο βαθμό όμοιο κώδικα, όμως ο κειμενογράφος της κονσόλας ανήκει σε μαι σταθερή φόρμα, ενώ το Editbox μπορούμε να το βάλουμε όσες φορές θέλουμε πάνω σε μια ή περισσότερες φόρμες - Η Μ2000 υποστηρίζει πίνακες; φορμών και πίνακες στοιχείων οπότε τα γεγονότα από ένα πίνακα φορμών με πίνακες στοιχείων θα έχει αρχικά δυο τιμές, τον αριθμός φόρμας και τον αριθμό στοιχείου (και η φόρμα και το στοιχείο έχουν ονόματα, άρα μπορούμε να έχουμε και άλλα σετ φορμών-στοιχείων ή φορμών-στοιχείωνΑ-στοιχείωνΝ ή μιας φόρμας με πολλούς πίνακες στοιχείων.

Αύξησα τις δυνατότητες χρωματισμού. Τώρα χρωματίζει και HTML, πράγμα αρκετά δύσκολο, γιατί η γλώσσα αυτή έχει tags, ενώ δεν έχει αλλαγές γραμμών (μπορούν να μπουν οπουδήποτε αλλά δεν μετράνε). Στη προηγούμενη αναθεώρηση είχα δώσει μια πρώτη έκδοση. Τώρα ήρθε η πιο βελτιωμένη. Επίσης μπορούμε να αλλάξουμε τα χρώματα τόσο του EditBox τα βασικά όσο και του χρωματισμού. Ενώ υπήρχαν δυο σετ χρωμάτων, για φωτεινό και για σκούρο φόντο, τώρα μπήκε και ένα προγραμματιζόμενο. Σε κάθε περίπτωση η αντιγραφή στο πρόχειρο (που δίνει δυο πράγματα, κείμενο και Html με χρωματισμένο κώδικα) ακολουθεί ένα από τα δύο βασικά, ανάλογα με τι έχουμε δώσει στις ρυθμίσεις. Με το htmleditor θα πάρουμε χρωματισμένο html σε κωδικοποίηση html, και μπορούμε να το επικολλήσουμε είτε σε επεξεργαστή κειμένου είτε σε blog, όπως αυτό εδώ.

float
float

Σάββατο 14 Σεπτεμβρίου 2019

Τελική Αναθεώρηση 40 για την έκδοση 9.8

Ολοκληρώθηκε η 9.8 έκδοση της Μ2000 με την αναθεώρηση 40. Ο διερμηνευτής έγινε πιο γρήγορος. Τρέχει από Windows XP και πάνω, και σε Linux με Wine. Επίσης τρέχει σε συστήματα με πολλαπλές οθόνες.

Παρασκευή 13 Σεπτεμβρίου 2019

Revision 39 Version 9.8

New revision and now we can use surrogates for UTF16LE, which is the encoding system for M2000 strings. M2000 is an interpreter written and compiled in Visual Basic 6.



M2000 Environment is built with VB6 naked forms (without title and control buttons). The problem of control buttons in VB6 exist in exit button [X}. When we press this button any thread halted until button released,or perform the hit. Because M2000 has a thread internal system, which implements an interval per thread, this halt is not allowed. So from version 7 of M2000 interpreter introduced a GUI system based in a single type form, and with a basic user control the glis4.ctl .This gui control in association with other objects, which can handle events make all the GUI controls of M2000. Before the GUI system was a form to emulate a console with graphics, like the screen of an 8-bit computer, with scolling, and split screen function (the low part of console can scroll, and the top part is static). This form actually exist, and is the main form when we open the interpreter in immediate mode. The editor for M2000 works with a TextViewer.cls (an object in VB6) similar to EditBox, the editor for gui. All gui elements have siblings for some utility forms, with a basic difference: The gui controls send events to interpreted user program at execution time, the other controls send the events to compiled code inside the interpreter.



So the job to include the surrogates for M2000 had three parts:

1. The console form which commands like INPUT and PRINT (similar to BASIC) use an internal key buffer (we can wait for key using KEY$ without stopping any thread - $ used when a string to indicate a string type of identifier). Characters on console layers (there are 32 plus 2 more layers)  and on user forms layers. can be displayed in a canvas style, using the Print command, where each character is at specific row and column, or using proportional spacing  using columns, justification, at specific rows, or by using the Report command we use proportional spacing but without columns, using tabs characters if we wish, for rendering text at a specific with, where only the left margin adjusted to the cursor row position. A last option is the Legend command which we can print text at graphic positions, using angle and justification.



From these four types of printing text in forms (same for printer paper), the last one (Legend command) use Win32 calls to perform all the tasks. The Report command has own justification routine (written by me), and before this revision only utf-16 diacritics handled proper. The same for the Print command



2. Editors updated to include the surrogates. The cursor always move one byte, but when discover a surrogate advance one more, or do the opposite if the cursor move to the left. Del and backspace/

3. Functions Chrcode$(numeric_expression) and Chtcode(string_expression) now work with surrogates. chrcode(chrcode$(0x10437))=0x10437.


This is an image of five programs running, one with full screen, another with modification to console, using transparency (a clock gadget), plus three editors using M2000 user forms. One editor for M2000 code, one for C# and another for an educational tiny language called ΓΛΩΣΣΑ (means language). From all editors we can copy to clipboard each time to two forms, one for plain text (utf-16) and one for html (utf-8).



Δευτέρα 9 Σεπτεμβρίου 2019

Αναθεώρηση 36 Έκδοση 9.8

Σε αυτήν την αναθεώρηση έφτιαξα το EditBox (στοιχείο ελέγχου σε φόρμες) και το υποκείμενο Document, ώστε να μπορούν να χειριστούν κώδικα της C#. Μάλιστα επειδή υπάρχει ο μεταφραστής της C# σε κάθε υπολογιστή με Windows και .Net, μπορούμε να μεταφράσουμε το πρόγραμμα και να εκτελέσουμε το αποτέλεσμα. Το ενδιαφέρον για μένα προγραμματιστικά για τον χρωματισμό της C# ήταν να μπορέσω με κατάλληλες αλλαγές να κάνω το EditBox να λειτουργεί πρώτα για λέξεις όπου τα πεζά-κεφαλαία να έχουν σημασία (ενώ στη Μ2000 όπως και στην Basic δεν είναι σημαντικά. Έτσι όταν επιλέγουμε ένα αναγνωριστικό με τα F2 και F3 πάμε στο ίδιο πάνω ή κάτω (αν υπάρχει), με τα γράμματα ως έχουν, έτσι το Book με το book είναι διαφορετικά, και αν αναζητούμε το Book δεν θα μας δώσει το book. Επίσης με το F5 αλλάζουμε μια λέξη και τώρα η αλλαγή γίνεται μόνο για τη λέξη με τα συγκεκριμένα και κεφαλαία.

Μια άλλη αλλαγή έγινε για να μπορώ να βλέπω τις λέξεις χωρίς τις τελείες, έτσι το Book.Title είναι δυο λέξεις, και αν κάνω αλλαγή στο Book με το F5 ως One τότε θα αλλάξει οπουδήποτε ακόμα και στο Book.Title (στη Μ2000 δεν γίνεται αυτό, γιατί το Book.Title τότε το βλέπει σαν μια λέξη). Αν επιλέξω με shift και βελάκια ή με shift και το ποντίκι, όλη τη λέξη τότε το F5 θα μας ζητήσει μια λέξη για να αλλάξει αυτό που δώσαμε με κάτι άλλο. Έτσι μπορούμε να αλλάξουμε και συνδεδεμένες λέξεις με τελεία. Επιπλέον μια άλλη αλλαγή έγινε με τις παρενθέσεις. Ενώ στη Μ2000 χρωματίζονται με τρεις διαφορετικούς τρόπους, ανάλογα αν είναι σε συνάρτηση εσωτερική ή σε συνάρτηση χρήστη ή είναι απλά παρενθέσεις, στο χρωματισμό για την C# έκανα τις παρενθέσεις ένα χρώμα. Τις συναρτήσεις τις έχουμε με ξεχωριστό χρώμα στις παρενθέσεις. Επίσης τρεις άλλες  αλλαγές χρειάζονταν, μια για το πώς διευθετούμε τα [ ], μια άλλη για τα < > και μια άλλη για τα σύμβολα στην αρχή της γραμμής (μπορούμε να έχουμε μια γραμμή εντολών σπασμένη σε δυο ή περισσότερες γραμμές).

Ο διορθωτής μπορεί να γυρίσει σε txt από cs, και το ανάποδο.




 Αν ένα εκτελέσιμο τρέχει μόνο σε κονσόλα και εξάγει στοιχεία μπορούμε να το εκτελέσουμε με εξαγωγή στο out.txt και να το ανοίξουμε με την τελευταία επιλογή στο RUN.


Αν ένα  πρόγραμμα δέχεται εισαγωγή από κονσόλα το τρέχουμε χωρίς την επιλογή για έξοδο στο out.txt
Αν στο πρόγραμμά μας υπάρχει το System.Windows.Forms, τότε  κατά την εκτέλεση της επιλογής Compile εφαρμόζει αυτόματα το target:winexe και έτσι δεν χρησιμοποιεί το out.txt και στην εκτέλεση τρέχει την παραθυρική εφαρμογή. Στο info όταν ανοίξουμε το cs θα εμφανίσει το pendulum.cs και μπορούμε να το κάνουμε compile, και όταν γίνει θα ενημερωθεί το μενού και θα μας επιτρέψει να το τρέξουμε. 

Πέμπτη 5 Σεπτεμβρίου 2019

Αναθεώρηση 34, Έκδοση 9.8

Μια μικρή αναθεώρηση. Διορθώθηκε ένα σφάλμα στην επιλογή με διπλό κλικ στη φόρμα βοήθειας. Επίσης οι ειδικές συναρτήσεις για tuple ή αυτόματους πίνακες, στα ελληνικά δεν εμφανίζονταν με κλικ γιατί από παράληψη δεν είχε μπει κώδικας για έλεγχο της γλώσσας στο δεύτερο γράμμα (αφού το πρώτο είναι το #, και το επιλεγμένο το λάμβανε ως λέξη στα αγγλικά οπότε δεν το έβρισκε το πρόγραμμα στο αγγλικό ευρετήριο).

Οι συναρτήσεις που τώρα εμφανίζονται στη βοήθεια είναι οι παρακάτω:
#ΑΘΡ(), #ΑΝΑΠ(), #ΑΝΤ(), #ΘΕΣΗ(), #ΜΕΓ(), #ΜΕΡΟΣ(), #ΜΙΚ(), #ΠΑΚ(), #ΤΙΜΗ()
#ΜΕΓ$(), #ΜΙΚ$(), #ΠΑΚ$(), #ΤΙΜΗ$()

Αυτές είναι ειδικές συναρτήσεις γιατί πρέπει να κληθούν με ένα αποτέλεσμα tuple στα αριστερά τους:

\\ #αθρ() ή #sum()
Τύπωσε (1,2,3)#αθρ()=6
Πίνακας Α(10)=1
Τύπωσε Α()#αθρ()=10
μ=(1,2,3,4)
κ=(1,2,3)
Τύπωσε μ#αθρ()=10
\\ δεν χρειάζονται παρενθέσεις αν έχουμε συνθήκη
Τύπωσε (1,2,3,4)#αθρ()>(1,2,3)#αθρ()
\\ χρειάζονται παρενθέσεις εδώ
Τύπωσε ((1,2,3,4)#αθρ())+((1,2,3,4)#αθρ())=20
\\ δεν χρειάζονται παρενθέσεις αν έχουμε μεταβλητή που δείχνει σε πίνακα
Τύπωσε μ#αθρ()>κ#αθρ()
Τύπωσε μ#αθρ()+μ#αθρ()=20
\\ #αναπ() ή #rev()
Τύπωσε (1,2,3)#αναπ()  ' δίνει 3 2 1
\\ #μέρος() ή #slice()
Τύπωσε μ     ' 1 2 3 4 
Τύπωσε μ#μέρος(1,2) ' 2,3
\\ #μεγ() ή #max() \\ #μεγ$() ή #max$() για αλφαριθμητικά αλ=("α","β","γ") Τύπωσε αλ#μεγ$()="γ" Τύπωσε μ#μέρος(1,2)#μεγ()=3 \\ #μικ() ή #min() \\ #μικ$() ή #min$() για αλφαριθμητικά Τύπωσε αλ#μικ$()="α" Τύπωσε μ#μέρος(1,2)#μικ()=2

Τύπωσε μ#μέρος(1,2)#αθρ()=5
\\ #τιμη() ή #val() \\ #τιμη$() ή #val$() για αλφαριθμητικά
Τύπωσε μ#τιμή(2)=3
μ=((1,2,3),(4,5,6)) Τύπωσε μ#τιμή(1)#αθρ()=15 Τύπωσε μ#τιμή(0)#αθρ()=6
Δες οκ { Τύπωσε μ#τιμή(2)=3 } Αν λάθος ή όχι οκ Τότε Τύπωσε Λάθος$ ' Δείκτης εκτός ορίων
\\ #θέση() ή #pos() μ=(1,1,0,1,1,1,1,0,1,1,0) Τύπωσε μ#θέση(1,0,1)=1 ' 2η θέση (1+1) Τύπωσε μ#θέση(5 -> 1,0,1)=6 ' 7η θέση Τύπωσε μ#θέση(2,3)=-1 ' δεν υπάρχει μ=(1,"α","β","γ",2,"γ","δ","ε") Τύπωσε μ#αθρ()=3 ν=μ#θέση("γ","δ") Αν ν>=0 Τότε Τύπωσε μ#μέρος(ν-1,ν+2) ' 2 γ δ ε

\\ #φίλτρο() ή #filter() \\ δουλεύει με μια λάμδα συνάρτηση α=(1,2,3,4,5,6,7,8,9)
μονός=λάμδα (χ)->χ υπόλοιπο 2=1 β=α#φίλτρο(μονός, (,)) Τύπωσε α#φίλτρο(μονός, (,)) ' 1,3,5,7,9 Τύπωσε β ' 1,3,5,7,9
\\ #αντ() ή #map() αντ1=λάμδα ->{ Βάλε ΧαρΚωδ$(αριθμός+64) } ζ=α#φίλτρο(μονός)#αντ(αντ1) Τύπωσε ζ ' A C E G I
\\ #πακ() ή #fold() \\ #πακ$() ή #fold$() για αλφαριθμητικό \\ δουλεύει με μια λάμδα συνάρτηση πακ2=λάμδα ->{ φερε 2 βάλε γραμμα$+"-"+γραμμα$ } Τύπωσε "["+α#φίλτρο(μονός)#αντ(αντ1)#πακ$(πακ2, "CODE")+"]"="[CODE-A-C-E-G-I]" συνάρτηση σειρά_γραμμάτων (αρχικό$, πόσα, φορές) { α=(,) β=χαρκωδ(αρχικό$)-1 για ι=1 εως πόσα προσθήκη α, (επαν$(χαρκωδ$(β+ι), φορές),) επόμενο =α }
\\ κλείσμο της ζ αντ1=λάμδα ζ=σειρά_γραμμάτων("D", 10, 2) ->{ Βάλε ζ#τιμή$((αριθμός-1) υπολ 10) }
Τύπωσε "["+α#φίλτρο(μονός)#αντ(αντ1)#πακ$(πακ2, "CODE")+"]"="[CODE-DD-FF-HH-JJ-LL]"

\\ φτιάχνουμε ένα γεγονός που είναι μια λίστα συναρτήσεων \\ μπορούμε να δώσουμε συνάρτηση από υπάρχον αντικείμενο τύπου ομάδα \\ με αυτόν τον τρόπο μαζεύουμε τα αποτελέσματα στο έγγραφο κωδικοί$ \\ η ομάδα έχει δυο ονόματα, το αποτέλεσμα και το αποτέλεσμα$ \\ το πρώτο το χρησιμοποιούμε για τις ιδιότητες, το δεύτερο για το αποτέλεσμα \\ επειδή εδώ είναι αλφαριθμητικό. Γεγονός Αλφα { Διάβασε Κ, &Τ$ } Ομάδα αποτέλεσμα$ { Ιδιωτικό: Ζ=("1ΑΒ","2ΓΥ","ΚΜΝ","832","5ΝΜ","ΚΖΛ","Μ13","ΤΚΛ","1Α5","234") Λ=(5,8,1,2,0,3,4,7,9,6) Μ=0 Τελική Τ$={#Τέλος Κωδικών } Έγγραφο Κωδικοί$={#Κωδικοί: } Δημόσιο: Αξία { =.Κωδικοί$+.Τ$ } Συνάρτηση Τελική κοίτα (που ως ακεραιος, &α$) { που=απολ(που) υπολ 10 α$=#τιμη$(#τιμη(που)) .Κωδικοί$<=Αν$(=0 ->"","-")+α$ ++ Αν =5 Τότε .Κωδικοί$<={ } <=0 Τέλος ΑΝ } }
\\ οι συναρτήσεις που δίνουμε πρέπει να έχουν την ίδια υπογραφή (αυτό θα φανεί στην εκτέλεση) Γεγονος Αλφα Νέο &αποτέλεσμα.κοίτα() αντ1=λάμδα Αλφα, αυτό$="" ->{ Κάλεσε Γεγονός Αλφα, αριθμός-1, &αυτό$ Βάλε αυτό$ } Τύπωσε "["+α#φίλτρο(μονός)#αντ(αντ1)#πακ$(πακ2, "CODE")+"]"="[CODE-ΚΖΛ-2ΓΥ-1ΑΒ-5ΝΜ-234]"
\\ τυπώνει με αναλογική γραφή κείμενο. Περιμένει στα 3/4 τη σελίδας για να προχωρήσει \\ να δώσουμε διάστημα ή πάτημα αριστερού πλήκτρου ποντικιού Αναφορά αποτέλεσμα$ Τύπωσε "["+α#μέρος(4,8)#αντ(αντ1)#πακ$(πακ2, "CODE")+"]"="[CODE-1ΑΒ-832-5ΝΜ-ΤΚΛ-234]" \\ τυπώνει στην κονσόλα σαν έξοδος σε αρχείο με το κανάλι -2 με μη αναλογική γραφή Τύπωσε #-2, αποτέλεσμα$ Σημ { #Κωδικοί: ΚΖΛ-2ΓΥ-1ΑΒ-5ΝΜ-234 1ΑΒ-832-5ΝΜ-ΤΚΛ-234 #Τέλος Κωδικών }


Τρίτη 3 Σεπτεμβρίου 2019

Αναθεώρηση 33 Έκδοση 9.8

Έφτιαξα την execute για βάσεις δεδομένων να εκτελεί πολλαπλές εντολές, με διαχωριστικό το ελληνικό ερωτηματικό. Δεν είχα ασχοληθεί πολύ με το θέμα, και είχα αφήσει την execute να μην επιστρέφει τιμές. Ίσως γιατί υπήρχαν άλλες εντολές για ανάκτηση πεδίων από αρχείο από βάση δεδομένων (εδώ λέμε αρχείο το πίνακα σε μια βάση). Όμως το αποφάσισα καθώς διάβαζα για την SQL και χθες το έφτιαξα.

Επειδή χρησιμοποιώ το αντικείμενο ADOdb και με εξ ορισμού τύπου την βάση mdb της Access, η SQL είναι λίγο διαφορετική. Κυρίως στο πώς ορίζουμε πεδία σε πίνακες.

Στο παράδειγμα παρακάτω με ενδιαφέρει να δείξω τη χρήση του  NULL. Μπορούμε σε ένα πεδίο να έχουμε NULL τιμή. Αυτό δεν σημαίνει μηδενικού μήκους αλφαριθμητικό (κενό). Με την χρήση της εντολής ΑΝΑΚΤΗΣΗ (RETRIEVE) δεν έχουμε επιστροφή NULL, μετατρέπεται σε κενό αλφαριθμητικό.


Το παράδειγμα υπάρχει στο νέο info.gsb ως baseG

Need new revision 33, version 9.8

\\ remove base if exist in current directory
base "gSQL"
\\ Make a new table and insert values (M2000 use ADOdb with a special connection string)
\\ data taken from example's of MOSH HAMEDANI for SQL, see this video
\\ https://www.youtube.com/watch?v=7S_tz1z_5bA
\\ Create table changed from original to be used here, but the schema is the same.
\\ Maybe integer definition maybe not the same with original int(11).
\\ We use 3 times execute. One return nothing, but the other two return a record set each \\ recordset saved to stack of values (as top value each time) \\ so we call subroutine passing just the stack of values, so we read from there.
\\ Inside each subroutine we make some local variables, using a way to link recordset with properties \\ property fields of recordset used 3 times, to produce different items. One is the actual object, and the \\ other two by using an index value we get field value (the default property), one as numeric and \\ the other as string.
\\ So we have to see about NULL. A NULL can exist if table schema allow it. When a field has NULL value \\ we get it as numeric type of NULL (we can't use it as a value in expressions, always return NULL), \\ but if we read it as string value we get empty string.
\\ Here we see two rows, one with a NULL phone and one with empty string (which isn't Null) \\ To examine if we have NULL we have to check the numeric variant of field.
\\ for checking the NULL we have a string function which return "NULL" or the string value, \\ including empty string.

execute "gSQL", { CREATE TABLE customers ( customer_id AUTOINCREMENT PRIMARY KEY, first_name VARCHAR(50) NOT NULL, last_name VARCHAR(50) NOT NULL, birth_date date DEFAULT NULL, phone VARCHAR(50) DEFAULT NULL, address VARCHAR(50) NOT NULL, city VARCHAR(50) NOT NULL, state char(2) NOT NULL, points integer NOT NULL DEFAULT 0 ); INSERT INTO `customers` VALUES (1,'Babara','MacCaffrey','1986-03-28','781-932-9754','0 Sage Terrace','Waltham','MA',2273); INSERT INTO `customers` VALUES (2,'Ines','Brushfield','1986-04-13','804-427-9456','14187 Commercial Trail','Hampton','VA',947); INSERT INTO `customers` VALUES (3,'Freddi','Boagey','1985-02-07','719-724-7869','251 Springs Junction','Colorado Springs','CO',2967); INSERT INTO `customers` VALUES (4,'Ambur','Roseburgh','1974-04-14','407-231-8017','30 Arapahoe Terrace','Orlando','FL',457); INSERT INTO `customers` VALUES (5,'Clemmie','Betchley','1973-11-07',NULL,'5 Spohn Circle','Arlington','TX',3675); INSERT INTO `customers` VALUES (6,'Elka','Twiddell','1991-09-04','312-480-8498','7 Manley Drive','Chicago','IL',3073); INSERT INTO `customers` VALUES (7,'Ilene','Dowson','1964-08-30','615-641-4759','50 Lillian Crossing','Nashville','TN',1672); INSERT INTO `customers` VALUES (8,'Thacher','Naseby','1993-07-17','941-527-3977','538 Mosinee Center','Sarasota','FL',205); INSERT INTO `customers` VALUES (9,'Romola','Rumgay','1992-05-23','559-181-3744','3520 Ohio Trail','Visalia','CA',1486); INSERT INTO `customers` VALUES (10,'Levy','Mynett','1969-10-13','','68 Lawn Avenue','Atlanta','GA',796); }
\\ id 10 has no Null phone, has no phone (is an empty string) \\ Null means "no information yet" report "customers created" \\ execute a SE`LECT query to get a Recordset report "Selected customers where Points<1000 in descending order" execute "gSQL",{ SELECT customer_id, last_name, first_name, phone, points FROM `customers` WHERE Points<1000 ORDER BY Points DESC, last_name, first_name } Def CheckNull$(a, a$)=If$(type$(a)="Null"->"NULL", a$)
GetListA() ' value is already in stack
report  "Select customers id where phone is null" execute "gSQL",{ SELECT customer_id, phone FROM `customers` WHERE phone IS Null ORDER BY customer_id } GetIDwithNullPhone() ' value is already in stack

\\ using list to check the variable names list \\ there are no variables in module, at this moment. \\ All variables was local to subs, and they erased at the exit of subs \\ we can use dots in names, like a normal variable. \\ so rs.fields is a norma variable name. This variable is a PropReference type. \\ This type of variable is an object which link a property to an object \\ We can't use these variables as return values, because the use a hard link, \\ and not a standard reference to object. So PropReference can't hold alive a linked object. \\ So if we return the PropReference from where we make it then became invalid, and we have \\ to use it to raise the error.

sub GetListA(RS) if type$(RS)="Recordset" then with RS, "EOF" as new rs.eof, "fields" as new fields(), "fields" as new fields$(), "fields" as new rs.fields with rs.fields, "count" as new rs.fields.count print "Test number of fields:", rs.fields.count while not rs.eof print $(6),fields(0), print $(9)," ";fields$(1);" ";fields$(2);@(32); CheckNull$(fields(3), fields$(3));@(42), fields(4) method rs, "movenext" end while print $(0),, end if end sub sub GetIDwithNullPhone(RS) if type$(RS)="Recordset" then with RS, "EOF" as new rs.eof, "fields" as new fields(), "fields" as new fields$(), "fields" as new rs.fields with rs.fields, "count" as new rs.fields.count print "Test number of fields:", rs.fields.count while not rs.eof print $(4), fields(0), $(7), CheckNull$(fields(1), fields$(1)), $(0) method rs, "movenext" end while print end if end sub